diff options
Diffstat (limited to 'drivers')
162 files changed, 5005 insertions, 1961 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 8a5bf3b356fa..55b5b90c2a44 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -395,7 +395,7 @@ struct pci_dev *acpi_get_pci_dev(acpi_handle handle) | |||
395 | fn = adr & 0xffff; | 395 | fn = adr & 0xffff; |
396 | 396 | ||
397 | pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); | 397 | pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); |
398 | if (hnd == handle) | 398 | if (!pdev || hnd == handle) |
399 | break; | 399 | break; |
400 | 400 | ||
401 | pbus = pdev->subordinate; | 401 | pbus = pdev->subordinate; |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index c7a527c08a09..65a0655e7fc8 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -226,8 +226,18 @@ static inline void addQ(struct hlist_head *list, CommandList_struct *c) | |||
226 | 226 | ||
227 | static inline void removeQ(CommandList_struct *c) | 227 | static inline void removeQ(CommandList_struct *c) |
228 | { | 228 | { |
229 | if (WARN_ON(hlist_unhashed(&c->list))) | 229 | /* |
230 | * After kexec/dump some commands might still | ||
231 | * be in flight, which the firmware will try | ||
232 | * to complete. Resetting the firmware doesn't work | ||
233 | * with old fw revisions, so we have to mark | ||
234 | * them off as 'stale' to prevent the driver from | ||
235 | * falling over. | ||
236 | */ | ||
237 | if (WARN_ON(hlist_unhashed(&c->list))) { | ||
238 | c->cmd_type = CMD_MSG_STALE; | ||
230 | return; | 239 | return; |
240 | } | ||
231 | 241 | ||
232 | hlist_del_init(&c->list); | 242 | hlist_del_init(&c->list); |
233 | } | 243 | } |
@@ -4246,7 +4256,8 @@ static void fail_all_cmds(unsigned long ctlr) | |||
4246 | while (!hlist_empty(&h->cmpQ)) { | 4256 | while (!hlist_empty(&h->cmpQ)) { |
4247 | c = hlist_entry(h->cmpQ.first, CommandList_struct, list); | 4257 | c = hlist_entry(h->cmpQ.first, CommandList_struct, list); |
4248 | removeQ(c); | 4258 | removeQ(c); |
4249 | c->err_info->CommandStatus = CMD_HARDWARE_ERR; | 4259 | if (c->cmd_type != CMD_MSG_STALE) |
4260 | c->err_info->CommandStatus = CMD_HARDWARE_ERR; | ||
4250 | if (c->cmd_type == CMD_RWREQ) { | 4261 | if (c->cmd_type == CMD_RWREQ) { |
4251 | complete_command(h, c, 0); | 4262 | complete_command(h, c, 0); |
4252 | } else if (c->cmd_type == CMD_IOCTL_PEND) | 4263 | } else if (c->cmd_type == CMD_IOCTL_PEND) |
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index cd665b00c7c5..dbaed1ea0da3 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h | |||
@@ -274,6 +274,7 @@ typedef struct _ErrorInfo_struct { | |||
274 | #define CMD_SCSI 0x03 | 274 | #define CMD_SCSI 0x03 |
275 | #define CMD_MSG_DONE 0x04 | 275 | #define CMD_MSG_DONE 0x04 |
276 | #define CMD_MSG_TIMEOUT 0x05 | 276 | #define CMD_MSG_TIMEOUT 0x05 |
277 | #define CMD_MSG_STALE 0xff | ||
277 | 278 | ||
278 | /* This structure needs to be divisible by 8 for new | 279 | /* This structure needs to be divisible by 8 for new |
279 | * indexing method. | 280 | * indexing method. |
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 862b40c90181..91b753013780 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -3327,7 +3327,10 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, | |||
3327 | if (!capable(CAP_SYS_ADMIN)) | 3327 | if (!capable(CAP_SYS_ADMIN)) |
3328 | return -EPERM; | 3328 | return -EPERM; |
3329 | mutex_lock(&open_lock); | 3329 | mutex_lock(&open_lock); |
3330 | LOCK_FDC(drive, 1); | 3330 | if (lock_fdc(drive, 1)) { |
3331 | mutex_unlock(&open_lock); | ||
3332 | return -EINTR; | ||
3333 | } | ||
3331 | floppy_type[type] = *g; | 3334 | floppy_type[type] = *g; |
3332 | floppy_type[type].name = "user format"; | 3335 | floppy_type[type].name = "user format"; |
3333 | for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) | 3336 | for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 0bd01f49cfd8..6a06913b01d3 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -1029,10 +1029,6 @@ config CS5535_GPIO | |||
1029 | 1029 | ||
1030 | If compiled as a module, it will be called cs5535_gpio. | 1030 | If compiled as a module, it will be called cs5535_gpio. |
1031 | 1031 | ||
1032 | config GPIO_VR41XX | ||
1033 | tristate "NEC VR4100 series General-purpose I/O Unit support" | ||
1034 | depends on CPU_VR41XX | ||
1035 | |||
1036 | config RAW_DRIVER | 1032 | config RAW_DRIVER |
1037 | tristate "RAW driver (/dev/raw/rawN)" | 1033 | tristate "RAW driver (/dev/raw/rawN)" |
1038 | depends on BLOCK | 1034 | depends on BLOCK |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 189efcff08ce..66f779ad4f4c 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -95,7 +95,6 @@ obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o | |||
95 | obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o | 95 | obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o |
96 | obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o | 96 | obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o |
97 | obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o | 97 | obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o |
98 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o | ||
99 | obj-$(CONFIG_GPIO_TB0219) += tb0219.o | 98 | obj-$(CONFIG_GPIO_TB0219) += tb0219.o |
100 | obj-$(CONFIG_TELCLOCK) += tlclk.o | 99 | obj-$(CONFIG_TELCLOCK) += tlclk.o |
101 | 100 | ||
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index 140ea10ecb88..c02db01f736e 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/cdev.h> | 27 | #include <linux/cdev.h> |
28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | #include <asm/pgtable.h> | ||
30 | #include <asm/io.h> | 31 | #include <asm/io.h> |
31 | 32 | ||
32 | /* | 33 | /* |
@@ -75,12 +76,13 @@ static struct class *bsr_class; | |||
75 | static int bsr_major; | 76 | static int bsr_major; |
76 | 77 | ||
77 | enum { | 78 | enum { |
78 | BSR_8 = 0, | 79 | BSR_8 = 0, |
79 | BSR_16 = 1, | 80 | BSR_16 = 1, |
80 | BSR_64 = 2, | 81 | BSR_64 = 2, |
81 | BSR_128 = 3, | 82 | BSR_128 = 3, |
82 | BSR_UNKNOWN = 4, | 83 | BSR_4096 = 4, |
83 | BSR_MAX = 5, | 84 | BSR_UNKNOWN = 5, |
85 | BSR_MAX = 6, | ||
84 | }; | 86 | }; |
85 | 87 | ||
86 | static unsigned bsr_types[BSR_MAX]; | 88 | static unsigned bsr_types[BSR_MAX]; |
@@ -117,15 +119,22 @@ static int bsr_mmap(struct file *filp, struct vm_area_struct *vma) | |||
117 | { | 119 | { |
118 | unsigned long size = vma->vm_end - vma->vm_start; | 120 | unsigned long size = vma->vm_end - vma->vm_start; |
119 | struct bsr_dev *dev = filp->private_data; | 121 | struct bsr_dev *dev = filp->private_data; |
122 | int ret; | ||
120 | 123 | ||
121 | if (size > dev->bsr_len || (size & (PAGE_SIZE-1))) | ||
122 | return -EINVAL; | ||
123 | |||
124 | vma->vm_flags |= (VM_IO | VM_DONTEXPAND); | ||
125 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 124 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
126 | 125 | ||
127 | if (io_remap_pfn_range(vma, vma->vm_start, dev->bsr_addr >> PAGE_SHIFT, | 126 | /* check for the case of a small BSR device and map one 4k page for it*/ |
128 | size, vma->vm_page_prot)) | 127 | if (dev->bsr_len < PAGE_SIZE && size == PAGE_SIZE) |
128 | ret = remap_4k_pfn(vma, vma->vm_start, dev->bsr_addr >> 12, | ||
129 | vma->vm_page_prot); | ||
130 | else if (size <= dev->bsr_len) | ||
131 | ret = io_remap_pfn_range(vma, vma->vm_start, | ||
132 | dev->bsr_addr >> PAGE_SHIFT, | ||
133 | size, vma->vm_page_prot); | ||
134 | else | ||
135 | return -EINVAL; | ||
136 | |||
137 | if (ret) | ||
129 | return -EAGAIN; | 138 | return -EAGAIN; |
130 | 139 | ||
131 | return 0; | 140 | return 0; |
@@ -205,6 +214,11 @@ static int bsr_add_node(struct device_node *bn) | |||
205 | cur->bsr_stride = bsr_stride[i]; | 214 | cur->bsr_stride = bsr_stride[i]; |
206 | cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs); | 215 | cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs); |
207 | 216 | ||
217 | /* if we have a bsr_len of > 4k and less then PAGE_SIZE (64k pages) */ | ||
218 | /* we can only map 4k of it, so only advertise the 4k in sysfs */ | ||
219 | if (cur->bsr_len > 4096 && cur->bsr_len < PAGE_SIZE) | ||
220 | cur->bsr_len = 4096; | ||
221 | |||
208 | switch(cur->bsr_bytes) { | 222 | switch(cur->bsr_bytes) { |
209 | case 8: | 223 | case 8: |
210 | cur->bsr_type = BSR_8; | 224 | cur->bsr_type = BSR_8; |
@@ -218,9 +232,11 @@ static int bsr_add_node(struct device_node *bn) | |||
218 | case 128: | 232 | case 128: |
219 | cur->bsr_type = BSR_128; | 233 | cur->bsr_type = BSR_128; |
220 | break; | 234 | break; |
235 | case 4096: | ||
236 | cur->bsr_type = BSR_4096; | ||
237 | break; | ||
221 | default: | 238 | default: |
222 | cur->bsr_type = BSR_UNKNOWN; | 239 | cur->bsr_type = BSR_UNKNOWN; |
223 | printk(KERN_INFO "unknown BSR size %d\n",cur->bsr_bytes); | ||
224 | } | 240 | } |
225 | 241 | ||
226 | cur->bsr_num = bsr_types[cur->bsr_type]; | 242 | cur->bsr_num = bsr_types[cur->bsr_type]; |
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c index 6062b62800fd..b3ec9b10e292 100644 --- a/drivers/char/tb0219.c +++ b/drivers/char/tb0219.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for TANBAC TB0219 base board. | 2 | * Driver for TANBAC TB0219 base board. |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2005 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -28,7 +28,7 @@ | |||
28 | #include <asm/vr41xx/giu.h> | 28 | #include <asm/vr41xx/giu.h> |
29 | #include <asm/vr41xx/tb0219.h> | 29 | #include <asm/vr41xx/tb0219.h> |
30 | 30 | ||
31 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 31 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
32 | MODULE_DESCRIPTION("TANBAC TB0219 base board driver"); | 32 | MODULE_DESCRIPTION("TANBAC TB0219 base board driver"); |
33 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
34 | 34 | ||
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index a19e935847b0..913aa8d3f1c5 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
@@ -867,15 +867,22 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
867 | tty_ldisc_wait_idle(tty); | 867 | tty_ldisc_wait_idle(tty); |
868 | 868 | ||
869 | /* | 869 | /* |
870 | * Shutdown the current line discipline, and reset it to N_TTY. | 870 | * Now kill off the ldisc |
871 | * | ||
872 | * FIXME: this MUST get fixed for the new reflocking | ||
873 | */ | 871 | */ |
872 | tty_ldisc_close(tty, tty->ldisc); | ||
873 | tty_ldisc_put(tty->ldisc); | ||
874 | /* Force an oops if we mess this up */ | ||
875 | tty->ldisc = NULL; | ||
876 | |||
877 | /* Ensure the next open requests the N_TTY ldisc */ | ||
878 | tty_set_termios_ldisc(tty, N_TTY); | ||
874 | 879 | ||
875 | tty_ldisc_reinit(tty); | ||
876 | /* This will need doing differently if we need to lock */ | 880 | /* This will need doing differently if we need to lock */ |
877 | if (o_tty) | 881 | if (o_tty) |
878 | tty_ldisc_release(o_tty, NULL); | 882 | tty_ldisc_release(o_tty, NULL); |
883 | |||
884 | /* And the memory resources remaining (buffers, termios) will be | ||
885 | disposed of when the kref hits zero */ | ||
879 | } | 886 | } |
880 | 887 | ||
881 | /** | 888 | /** |
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index 54c837288d19..e69de29bb2d1 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c | |||
@@ -1,680 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for NEC VR4100 series General-purpose I/O Unit. | ||
3 | * | ||
4 | * Copyright (C) 2002 MontaVista Software Inc. | ||
5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> | ||
6 | * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | ||
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 as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/smp_lock.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | #include <linux/types.h> | ||
33 | |||
34 | #include <asm/io.h> | ||
35 | #include <asm/vr41xx/giu.h> | ||
36 | #include <asm/vr41xx/irq.h> | ||
37 | #include <asm/vr41xx/vr41xx.h> | ||
38 | |||
39 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | ||
40 | MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | |||
43 | static int major; /* default is dynamic major device number */ | ||
44 | module_param(major, int, 0); | ||
45 | MODULE_PARM_DESC(major, "Major device number"); | ||
46 | |||
47 | #define GIUIOSELL 0x00 | ||
48 | #define GIUIOSELH 0x02 | ||
49 | #define GIUPIODL 0x04 | ||
50 | #define GIUPIODH 0x06 | ||
51 | #define GIUINTSTATL 0x08 | ||
52 | #define GIUINTSTATH 0x0a | ||
53 | #define GIUINTENL 0x0c | ||
54 | #define GIUINTENH 0x0e | ||
55 | #define GIUINTTYPL 0x10 | ||
56 | #define GIUINTTYPH 0x12 | ||
57 | #define GIUINTALSELL 0x14 | ||
58 | #define GIUINTALSELH 0x16 | ||
59 | #define GIUINTHTSELL 0x18 | ||
60 | #define GIUINTHTSELH 0x1a | ||
61 | #define GIUPODATL 0x1c | ||
62 | #define GIUPODATEN 0x1c | ||
63 | #define GIUPODATH 0x1e | ||
64 | #define PIOEN0 0x0100 | ||
65 | #define PIOEN1 0x0200 | ||
66 | #define GIUPODAT 0x1e | ||
67 | #define GIUFEDGEINHL 0x20 | ||
68 | #define GIUFEDGEINHH 0x22 | ||
69 | #define GIUREDGEINHL 0x24 | ||
70 | #define GIUREDGEINHH 0x26 | ||
71 | |||
72 | #define GIUUSEUPDN 0x1e0 | ||
73 | #define GIUTERMUPDN 0x1e2 | ||
74 | |||
75 | #define GPIO_HAS_PULLUPDOWN_IO 0x0001 | ||
76 | #define GPIO_HAS_OUTPUT_ENABLE 0x0002 | ||
77 | #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 | ||
78 | |||
79 | static spinlock_t giu_lock; | ||
80 | static unsigned long giu_flags; | ||
81 | static unsigned int giu_nr_pins; | ||
82 | |||
83 | static void __iomem *giu_base; | ||
84 | |||
85 | #define giu_read(offset) readw(giu_base + (offset)) | ||
86 | #define giu_write(offset, value) writew((value), giu_base + (offset)) | ||
87 | |||
88 | #define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) | ||
89 | #define GIUINT_HIGH_OFFSET 16 | ||
90 | #define GIUINT_HIGH_MAX 32 | ||
91 | |||
92 | static inline uint16_t giu_set(uint16_t offset, uint16_t set) | ||
93 | { | ||
94 | uint16_t data; | ||
95 | |||
96 | data = giu_read(offset); | ||
97 | data |= set; | ||
98 | giu_write(offset, data); | ||
99 | |||
100 | return data; | ||
101 | } | ||
102 | |||
103 | static inline uint16_t giu_clear(uint16_t offset, uint16_t clear) | ||
104 | { | ||
105 | uint16_t data; | ||
106 | |||
107 | data = giu_read(offset); | ||
108 | data &= ~clear; | ||
109 | giu_write(offset, data); | ||
110 | |||
111 | return data; | ||
112 | } | ||
113 | |||
114 | static void ack_giuint_low(unsigned int irq) | ||
115 | { | ||
116 | giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
117 | } | ||
118 | |||
119 | static void mask_giuint_low(unsigned int irq) | ||
120 | { | ||
121 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
122 | } | ||
123 | |||
124 | static void mask_ack_giuint_low(unsigned int irq) | ||
125 | { | ||
126 | unsigned int pin; | ||
127 | |||
128 | pin = GPIO_PIN_OF_IRQ(irq); | ||
129 | giu_clear(GIUINTENL, 1 << pin); | ||
130 | giu_write(GIUINTSTATL, 1 << pin); | ||
131 | } | ||
132 | |||
133 | static void unmask_giuint_low(unsigned int irq) | ||
134 | { | ||
135 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
136 | } | ||
137 | |||
138 | static struct irq_chip giuint_low_irq_chip = { | ||
139 | .name = "GIUINTL", | ||
140 | .ack = ack_giuint_low, | ||
141 | .mask = mask_giuint_low, | ||
142 | .mask_ack = mask_ack_giuint_low, | ||
143 | .unmask = unmask_giuint_low, | ||
144 | }; | ||
145 | |||
146 | static void ack_giuint_high(unsigned int irq) | ||
147 | { | ||
148 | giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
149 | } | ||
150 | |||
151 | static void mask_giuint_high(unsigned int irq) | ||
152 | { | ||
153 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
154 | } | ||
155 | |||
156 | static void mask_ack_giuint_high(unsigned int irq) | ||
157 | { | ||
158 | unsigned int pin; | ||
159 | |||
160 | pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; | ||
161 | giu_clear(GIUINTENH, 1 << pin); | ||
162 | giu_write(GIUINTSTATH, 1 << pin); | ||
163 | } | ||
164 | |||
165 | static void unmask_giuint_high(unsigned int irq) | ||
166 | { | ||
167 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
168 | } | ||
169 | |||
170 | static struct irq_chip giuint_high_irq_chip = { | ||
171 | .name = "GIUINTH", | ||
172 | .ack = ack_giuint_high, | ||
173 | .mask = mask_giuint_high, | ||
174 | .mask_ack = mask_ack_giuint_high, | ||
175 | .unmask = unmask_giuint_high, | ||
176 | }; | ||
177 | |||
178 | static int giu_get_irq(unsigned int irq) | ||
179 | { | ||
180 | uint16_t pendl, pendh, maskl, maskh; | ||
181 | int i; | ||
182 | |||
183 | pendl = giu_read(GIUINTSTATL); | ||
184 | pendh = giu_read(GIUINTSTATH); | ||
185 | maskl = giu_read(GIUINTENL); | ||
186 | maskh = giu_read(GIUINTENH); | ||
187 | |||
188 | maskl &= pendl; | ||
189 | maskh &= pendh; | ||
190 | |||
191 | if (maskl) { | ||
192 | for (i = 0; i < 16; i++) { | ||
193 | if (maskl & (1 << i)) | ||
194 | return GIU_IRQ(i); | ||
195 | } | ||
196 | } else if (maskh) { | ||
197 | for (i = 0; i < 16; i++) { | ||
198 | if (maskh & (1 << i)) | ||
199 | return GIU_IRQ(i + GIUINT_HIGH_OFFSET); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", | ||
204 | maskl, pendl, maskh, pendh); | ||
205 | |||
206 | atomic_inc(&irq_err_count); | ||
207 | |||
208 | return -EINVAL; | ||
209 | } | ||
210 | |||
211 | void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal) | ||
212 | { | ||
213 | uint16_t mask; | ||
214 | |||
215 | if (pin < GIUINT_HIGH_OFFSET) { | ||
216 | mask = 1 << pin; | ||
217 | if (trigger != IRQ_TRIGGER_LEVEL) { | ||
218 | giu_set(GIUINTTYPL, mask); | ||
219 | if (signal == IRQ_SIGNAL_HOLD) | ||
220 | giu_set(GIUINTHTSELL, mask); | ||
221 | else | ||
222 | giu_clear(GIUINTHTSELL, mask); | ||
223 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | ||
224 | switch (trigger) { | ||
225 | case IRQ_TRIGGER_EDGE_FALLING: | ||
226 | giu_set(GIUFEDGEINHL, mask); | ||
227 | giu_clear(GIUREDGEINHL, mask); | ||
228 | break; | ||
229 | case IRQ_TRIGGER_EDGE_RISING: | ||
230 | giu_clear(GIUFEDGEINHL, mask); | ||
231 | giu_set(GIUREDGEINHL, mask); | ||
232 | break; | ||
233 | default: | ||
234 | giu_set(GIUFEDGEINHL, mask); | ||
235 | giu_set(GIUREDGEINHL, mask); | ||
236 | break; | ||
237 | } | ||
238 | } | ||
239 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
240 | &giuint_low_irq_chip, | ||
241 | handle_edge_irq); | ||
242 | } else { | ||
243 | giu_clear(GIUINTTYPL, mask); | ||
244 | giu_clear(GIUINTHTSELL, mask); | ||
245 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
246 | &giuint_low_irq_chip, | ||
247 | handle_level_irq); | ||
248 | } | ||
249 | giu_write(GIUINTSTATL, mask); | ||
250 | } else if (pin < GIUINT_HIGH_MAX) { | ||
251 | mask = 1 << (pin - GIUINT_HIGH_OFFSET); | ||
252 | if (trigger != IRQ_TRIGGER_LEVEL) { | ||
253 | giu_set(GIUINTTYPH, mask); | ||
254 | if (signal == IRQ_SIGNAL_HOLD) | ||
255 | giu_set(GIUINTHTSELH, mask); | ||
256 | else | ||
257 | giu_clear(GIUINTHTSELH, mask); | ||
258 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | ||
259 | switch (trigger) { | ||
260 | case IRQ_TRIGGER_EDGE_FALLING: | ||
261 | giu_set(GIUFEDGEINHH, mask); | ||
262 | giu_clear(GIUREDGEINHH, mask); | ||
263 | break; | ||
264 | case IRQ_TRIGGER_EDGE_RISING: | ||
265 | giu_clear(GIUFEDGEINHH, mask); | ||
266 | giu_set(GIUREDGEINHH, mask); | ||
267 | break; | ||
268 | default: | ||
269 | giu_set(GIUFEDGEINHH, mask); | ||
270 | giu_set(GIUREDGEINHH, mask); | ||
271 | break; | ||
272 | } | ||
273 | } | ||
274 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
275 | &giuint_high_irq_chip, | ||
276 | handle_edge_irq); | ||
277 | } else { | ||
278 | giu_clear(GIUINTTYPH, mask); | ||
279 | giu_clear(GIUINTHTSELH, mask); | ||
280 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
281 | &giuint_high_irq_chip, | ||
282 | handle_level_irq); | ||
283 | } | ||
284 | giu_write(GIUINTSTATH, mask); | ||
285 | } | ||
286 | } | ||
287 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); | ||
288 | |||
289 | void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) | ||
290 | { | ||
291 | uint16_t mask; | ||
292 | |||
293 | if (pin < GIUINT_HIGH_OFFSET) { | ||
294 | mask = 1 << pin; | ||
295 | if (level == IRQ_LEVEL_HIGH) | ||
296 | giu_set(GIUINTALSELL, mask); | ||
297 | else | ||
298 | giu_clear(GIUINTALSELL, mask); | ||
299 | giu_write(GIUINTSTATL, mask); | ||
300 | } else if (pin < GIUINT_HIGH_MAX) { | ||
301 | mask = 1 << (pin - GIUINT_HIGH_OFFSET); | ||
302 | if (level == IRQ_LEVEL_HIGH) | ||
303 | giu_set(GIUINTALSELH, mask); | ||
304 | else | ||
305 | giu_clear(GIUINTALSELH, mask); | ||
306 | giu_write(GIUINTSTATH, mask); | ||
307 | } | ||
308 | } | ||
309 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); | ||
310 | |||
311 | gpio_data_t vr41xx_gpio_get_pin(unsigned int pin) | ||
312 | { | ||
313 | uint16_t reg, mask; | ||
314 | |||
315 | if (pin >= giu_nr_pins) | ||
316 | return GPIO_DATA_INVAL; | ||
317 | |||
318 | if (pin < 16) { | ||
319 | reg = giu_read(GIUPIODL); | ||
320 | mask = (uint16_t)1 << pin; | ||
321 | } else if (pin < 32) { | ||
322 | reg = giu_read(GIUPIODH); | ||
323 | mask = (uint16_t)1 << (pin - 16); | ||
324 | } else if (pin < 48) { | ||
325 | reg = giu_read(GIUPODATL); | ||
326 | mask = (uint16_t)1 << (pin - 32); | ||
327 | } else { | ||
328 | reg = giu_read(GIUPODATH); | ||
329 | mask = (uint16_t)1 << (pin - 48); | ||
330 | } | ||
331 | |||
332 | if (reg & mask) | ||
333 | return GPIO_DATA_HIGH; | ||
334 | |||
335 | return GPIO_DATA_LOW; | ||
336 | } | ||
337 | EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin); | ||
338 | |||
339 | int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data) | ||
340 | { | ||
341 | uint16_t offset, mask, reg; | ||
342 | unsigned long flags; | ||
343 | |||
344 | if (pin >= giu_nr_pins) | ||
345 | return -EINVAL; | ||
346 | |||
347 | if (pin < 16) { | ||
348 | offset = GIUPIODL; | ||
349 | mask = (uint16_t)1 << pin; | ||
350 | } else if (pin < 32) { | ||
351 | offset = GIUPIODH; | ||
352 | mask = (uint16_t)1 << (pin - 16); | ||
353 | } else if (pin < 48) { | ||
354 | offset = GIUPODATL; | ||
355 | mask = (uint16_t)1 << (pin - 32); | ||
356 | } else { | ||
357 | offset = GIUPODATH; | ||
358 | mask = (uint16_t)1 << (pin - 48); | ||
359 | } | ||
360 | |||
361 | spin_lock_irqsave(&giu_lock, flags); | ||
362 | |||
363 | reg = giu_read(offset); | ||
364 | if (data == GPIO_DATA_HIGH) | ||
365 | reg |= mask; | ||
366 | else | ||
367 | reg &= ~mask; | ||
368 | giu_write(offset, reg); | ||
369 | |||
370 | spin_unlock_irqrestore(&giu_lock, flags); | ||
371 | |||
372 | return 0; | ||
373 | } | ||
374 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin); | ||
375 | |||
376 | int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir) | ||
377 | { | ||
378 | uint16_t offset, mask, reg; | ||
379 | unsigned long flags; | ||
380 | |||
381 | if (pin >= giu_nr_pins) | ||
382 | return -EINVAL; | ||
383 | |||
384 | if (pin < 16) { | ||
385 | offset = GIUIOSELL; | ||
386 | mask = (uint16_t)1 << pin; | ||
387 | } else if (pin < 32) { | ||
388 | offset = GIUIOSELH; | ||
389 | mask = (uint16_t)1 << (pin - 16); | ||
390 | } else { | ||
391 | if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { | ||
392 | offset = GIUPODATEN; | ||
393 | mask = (uint16_t)1 << (pin - 32); | ||
394 | } else { | ||
395 | switch (pin) { | ||
396 | case 48: | ||
397 | offset = GIUPODATH; | ||
398 | mask = PIOEN0; | ||
399 | break; | ||
400 | case 49: | ||
401 | offset = GIUPODATH; | ||
402 | mask = PIOEN1; | ||
403 | break; | ||
404 | default: | ||
405 | return -EINVAL; | ||
406 | } | ||
407 | } | ||
408 | } | ||
409 | |||
410 | spin_lock_irqsave(&giu_lock, flags); | ||
411 | |||
412 | reg = giu_read(offset); | ||
413 | if (dir == GPIO_OUTPUT) | ||
414 | reg |= mask; | ||
415 | else | ||
416 | reg &= ~mask; | ||
417 | giu_write(offset, reg); | ||
418 | |||
419 | spin_unlock_irqrestore(&giu_lock, flags); | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction); | ||
424 | |||
425 | int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) | ||
426 | { | ||
427 | uint16_t reg, mask; | ||
428 | unsigned long flags; | ||
429 | |||
430 | if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO) | ||
431 | return -EPERM; | ||
432 | |||
433 | if (pin >= 15) | ||
434 | return -EINVAL; | ||
435 | |||
436 | mask = (uint16_t)1 << pin; | ||
437 | |||
438 | spin_lock_irqsave(&giu_lock, flags); | ||
439 | |||
440 | if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) { | ||
441 | reg = giu_read(GIUTERMUPDN); | ||
442 | if (pull == GPIO_PULL_UP) | ||
443 | reg |= mask; | ||
444 | else | ||
445 | reg &= ~mask; | ||
446 | giu_write(GIUTERMUPDN, reg); | ||
447 | |||
448 | reg = giu_read(GIUUSEUPDN); | ||
449 | reg |= mask; | ||
450 | giu_write(GIUUSEUPDN, reg); | ||
451 | } else { | ||
452 | reg = giu_read(GIUUSEUPDN); | ||
453 | reg &= ~mask; | ||
454 | giu_write(GIUUSEUPDN, reg); | ||
455 | } | ||
456 | |||
457 | spin_unlock_irqrestore(&giu_lock, flags); | ||
458 | |||
459 | return 0; | ||
460 | } | ||
461 | EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); | ||
462 | |||
463 | static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, | ||
464 | loff_t *ppos) | ||
465 | { | ||
466 | unsigned int pin; | ||
467 | char value = '0'; | ||
468 | |||
469 | pin = iminor(file->f_path.dentry->d_inode); | ||
470 | if (pin >= giu_nr_pins) | ||
471 | return -EBADF; | ||
472 | |||
473 | if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH) | ||
474 | value = '1'; | ||
475 | |||
476 | if (len <= 0) | ||
477 | return -EFAULT; | ||
478 | |||
479 | if (put_user(value, buf)) | ||
480 | return -EFAULT; | ||
481 | |||
482 | return 1; | ||
483 | } | ||
484 | |||
485 | static ssize_t gpio_write(struct file *file, const char __user *data, | ||
486 | size_t len, loff_t *ppos) | ||
487 | { | ||
488 | unsigned int pin; | ||
489 | size_t i; | ||
490 | char c; | ||
491 | int retval = 0; | ||
492 | |||
493 | pin = iminor(file->f_path.dentry->d_inode); | ||
494 | if (pin >= giu_nr_pins) | ||
495 | return -EBADF; | ||
496 | |||
497 | for (i = 0; i < len; i++) { | ||
498 | if (get_user(c, data + i)) | ||
499 | return -EFAULT; | ||
500 | |||
501 | switch (c) { | ||
502 | case '0': | ||
503 | retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW); | ||
504 | break; | ||
505 | case '1': | ||
506 | retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH); | ||
507 | break; | ||
508 | case 'D': | ||
509 | printk(KERN_INFO "GPIO%d: pull down\n", pin); | ||
510 | retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN); | ||
511 | break; | ||
512 | case 'd': | ||
513 | printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin); | ||
514 | retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE); | ||
515 | break; | ||
516 | case 'I': | ||
517 | printk(KERN_INFO "GPIO%d: input\n", pin); | ||
518 | retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT); | ||
519 | break; | ||
520 | case 'O': | ||
521 | printk(KERN_INFO "GPIO%d: output\n", pin); | ||
522 | retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT); | ||
523 | break; | ||
524 | case 'o': | ||
525 | printk(KERN_INFO "GPIO%d: output disable\n", pin); | ||
526 | retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE); | ||
527 | break; | ||
528 | case 'P': | ||
529 | printk(KERN_INFO "GPIO%d: pull up\n", pin); | ||
530 | retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP); | ||
531 | break; | ||
532 | case 'p': | ||
533 | printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin); | ||
534 | retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE); | ||
535 | break; | ||
536 | default: | ||
537 | break; | ||
538 | } | ||
539 | |||
540 | if (retval < 0) | ||
541 | break; | ||
542 | } | ||
543 | |||
544 | return i; | ||
545 | } | ||
546 | |||
547 | static int gpio_open(struct inode *inode, struct file *file) | ||
548 | { | ||
549 | unsigned int pin; | ||
550 | |||
551 | cycle_kernel_lock(); | ||
552 | pin = iminor(inode); | ||
553 | if (pin >= giu_nr_pins) | ||
554 | return -EBADF; | ||
555 | |||
556 | return nonseekable_open(inode, file); | ||
557 | } | ||
558 | |||
559 | static int gpio_release(struct inode *inode, struct file *file) | ||
560 | { | ||
561 | unsigned int pin; | ||
562 | |||
563 | pin = iminor(inode); | ||
564 | if (pin >= giu_nr_pins) | ||
565 | return -EBADF; | ||
566 | |||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | static const struct file_operations gpio_fops = { | ||
571 | .owner = THIS_MODULE, | ||
572 | .read = gpio_read, | ||
573 | .write = gpio_write, | ||
574 | .open = gpio_open, | ||
575 | .release = gpio_release, | ||
576 | }; | ||
577 | |||
578 | static int __devinit giu_probe(struct platform_device *dev) | ||
579 | { | ||
580 | struct resource *res; | ||
581 | unsigned int trigger, i, pin; | ||
582 | struct irq_chip *chip; | ||
583 | int irq, retval; | ||
584 | |||
585 | switch (dev->id) { | ||
586 | case GPIO_50PINS_PULLUPDOWN: | ||
587 | giu_flags = GPIO_HAS_PULLUPDOWN_IO; | ||
588 | giu_nr_pins = 50; | ||
589 | break; | ||
590 | case GPIO_36PINS: | ||
591 | giu_nr_pins = 36; | ||
592 | break; | ||
593 | case GPIO_48PINS_EDGE_SELECT: | ||
594 | giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; | ||
595 | giu_nr_pins = 48; | ||
596 | break; | ||
597 | default: | ||
598 | printk(KERN_ERR "GIU: unknown ID %d\n", dev->id); | ||
599 | return -ENODEV; | ||
600 | } | ||
601 | |||
602 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
603 | if (!res) | ||
604 | return -EBUSY; | ||
605 | |||
606 | giu_base = ioremap(res->start, res->end - res->start + 1); | ||
607 | if (!giu_base) | ||
608 | return -ENOMEM; | ||
609 | |||
610 | retval = register_chrdev(major, "GIU", &gpio_fops); | ||
611 | if (retval < 0) { | ||
612 | iounmap(giu_base); | ||
613 | giu_base = NULL; | ||
614 | return retval; | ||
615 | } | ||
616 | |||
617 | if (major == 0) { | ||
618 | major = retval; | ||
619 | printk(KERN_INFO "GIU: major number %d\n", major); | ||
620 | } | ||
621 | |||
622 | spin_lock_init(&giu_lock); | ||
623 | |||
624 | giu_write(GIUINTENL, 0); | ||
625 | giu_write(GIUINTENH, 0); | ||
626 | |||
627 | trigger = giu_read(GIUINTTYPH) << 16; | ||
628 | trigger |= giu_read(GIUINTTYPL); | ||
629 | for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { | ||
630 | pin = GPIO_PIN_OF_IRQ(i); | ||
631 | if (pin < GIUINT_HIGH_OFFSET) | ||
632 | chip = &giuint_low_irq_chip; | ||
633 | else | ||
634 | chip = &giuint_high_irq_chip; | ||
635 | |||
636 | if (trigger & (1 << pin)) | ||
637 | set_irq_chip_and_handler(i, chip, handle_edge_irq); | ||
638 | else | ||
639 | set_irq_chip_and_handler(i, chip, handle_level_irq); | ||
640 | |||
641 | } | ||
642 | |||
643 | irq = platform_get_irq(dev, 0); | ||
644 | if (irq < 0 || irq >= nr_irqs) | ||
645 | return -EBUSY; | ||
646 | |||
647 | return cascade_irq(irq, giu_get_irq); | ||
648 | } | ||
649 | |||
650 | static int __devexit giu_remove(struct platform_device *dev) | ||
651 | { | ||
652 | if (giu_base) { | ||
653 | iounmap(giu_base); | ||
654 | giu_base = NULL; | ||
655 | } | ||
656 | |||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | static struct platform_driver giu_device_driver = { | ||
661 | .probe = giu_probe, | ||
662 | .remove = __devexit_p(giu_remove), | ||
663 | .driver = { | ||
664 | .name = "GIU", | ||
665 | .owner = THIS_MODULE, | ||
666 | }, | ||
667 | }; | ||
668 | |||
669 | static int __init vr41xx_giu_init(void) | ||
670 | { | ||
671 | return platform_driver_register(&giu_device_driver); | ||
672 | } | ||
673 | |||
674 | static void __exit vr41xx_giu_exit(void) | ||
675 | { | ||
676 | platform_driver_unregister(&giu_device_driver); | ||
677 | } | ||
678 | |||
679 | module_init(vr41xx_giu_init); | ||
680 | module_exit(vr41xx_giu_exit); | ||
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 9ffb05f4095d..93c2322feab7 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c | |||
@@ -161,7 +161,7 @@ static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta, | |||
161 | if (periodic) | 161 | if (periodic) |
162 | sh_tmu_write(p, TCOR, delta); | 162 | sh_tmu_write(p, TCOR, delta); |
163 | else | 163 | else |
164 | sh_tmu_write(p, TCOR, 0); | 164 | sh_tmu_write(p, TCOR, 0xffffffff); |
165 | 165 | ||
166 | sh_tmu_write(p, TCNT, delta); | 166 | sh_tmu_write(p, TCNT, delta); |
167 | 167 | ||
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index c36bf40568cf..858fe6037223 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -754,13 +754,13 @@ static void amd64_cpu_display_info(struct amd64_pvt *pvt) | |||
754 | static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt) | 754 | static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt) |
755 | { | 755 | { |
756 | int bit; | 756 | int bit; |
757 | enum dev_type edac_cap = EDAC_NONE; | 757 | enum dev_type edac_cap = EDAC_FLAG_NONE; |
758 | 758 | ||
759 | bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= OPTERON_CPU_REV_F) | 759 | bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= OPTERON_CPU_REV_F) |
760 | ? 19 | 760 | ? 19 |
761 | : 17; | 761 | : 17; |
762 | 762 | ||
763 | if (pvt->dclr0 >> BIT(bit)) | 763 | if (pvt->dclr0 & BIT(bit)) |
764 | edac_cap = EDAC_FLAG_SECDED; | 764 | edac_cap = EDAC_FLAG_SECDED; |
765 | 765 | ||
766 | return edac_cap; | 766 | return edac_cap; |
@@ -1269,7 +1269,7 @@ static int f10_early_channel_count(struct amd64_pvt *pvt) | |||
1269 | if (channels == 0) | 1269 | if (channels == 0) |
1270 | channels = 1; | 1270 | channels = 1; |
1271 | 1271 | ||
1272 | debugf0("DIMM count= %d\n", channels); | 1272 | debugf0("MCT channel count: %d\n", channels); |
1273 | 1273 | ||
1274 | return channels; | 1274 | return channels; |
1275 | 1275 | ||
@@ -2966,7 +2966,12 @@ static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) | |||
2966 | " Use of the override can cause " | 2966 | " Use of the override can cause " |
2967 | "unknown side effects.\n"); | 2967 | "unknown side effects.\n"); |
2968 | ret = -ENODEV; | 2968 | ret = -ENODEV; |
2969 | } | 2969 | } else |
2970 | /* | ||
2971 | * enable further driver loading if ECC enable is | ||
2972 | * overridden. | ||
2973 | */ | ||
2974 | ret = 0; | ||
2970 | } else { | 2975 | } else { |
2971 | amd64_printk(KERN_INFO, | 2976 | amd64_printk(KERN_INFO, |
2972 | "ECC is enabled by BIOS, Proceeding " | 2977 | "ECC is enabled by BIOS, Proceeding " |
@@ -3006,7 +3011,6 @@ static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci) | |||
3006 | 3011 | ||
3007 | mci->mtype_cap = MEM_FLAG_DDR2 | MEM_FLAG_RDDR2; | 3012 | mci->mtype_cap = MEM_FLAG_DDR2 | MEM_FLAG_RDDR2; |
3008 | mci->edac_ctl_cap = EDAC_FLAG_NONE; | 3013 | mci->edac_ctl_cap = EDAC_FLAG_NONE; |
3009 | mci->edac_cap = EDAC_FLAG_NONE; | ||
3010 | 3014 | ||
3011 | if (pvt->nbcap & K8_NBCAP_SECDED) | 3015 | if (pvt->nbcap & K8_NBCAP_SECDED) |
3012 | mci->edac_ctl_cap |= EDAC_FLAG_SECDED; | 3016 | mci->edac_ctl_cap |= EDAC_FLAG_SECDED; |
@@ -3052,7 +3056,7 @@ static int amd64_probe_one_instance(struct pci_dev *dram_f2_ctl, | |||
3052 | if (!pvt) | 3056 | if (!pvt) |
3053 | goto err_exit; | 3057 | goto err_exit; |
3054 | 3058 | ||
3055 | pvt->mc_node_id = get_mc_node_id_from_pdev(dram_f2_ctl); | 3059 | pvt->mc_node_id = get_node_id(dram_f2_ctl); |
3056 | 3060 | ||
3057 | pvt->dram_f2_ctl = dram_f2_ctl; | 3061 | pvt->dram_f2_ctl = dram_f2_ctl; |
3058 | pvt->ext_model = boot_cpu_data.x86_model >> 4; | 3062 | pvt->ext_model = boot_cpu_data.x86_model >> 4; |
@@ -3179,8 +3183,7 @@ static int __devinit amd64_init_one_instance(struct pci_dev *pdev, | |||
3179 | { | 3183 | { |
3180 | int ret = 0; | 3184 | int ret = 0; |
3181 | 3185 | ||
3182 | debugf0("(MC node=%d,mc_type='%s')\n", | 3186 | debugf0("(MC node=%d,mc_type='%s')\n", get_node_id(pdev), |
3183 | get_mc_node_id_from_pdev(pdev), | ||
3184 | get_amd_family_name(mc_type->driver_data)); | 3187 | get_amd_family_name(mc_type->driver_data)); |
3185 | 3188 | ||
3186 | ret = pci_enable_device(pdev); | 3189 | ret = pci_enable_device(pdev); |
@@ -3319,15 +3322,17 @@ static int __init amd64_edac_init(void) | |||
3319 | 3322 | ||
3320 | err = amd64_init_2nd_stage(pvt_lookup[nb]); | 3323 | err = amd64_init_2nd_stage(pvt_lookup[nb]); |
3321 | if (err) | 3324 | if (err) |
3322 | goto err_exit; | 3325 | goto err_2nd_stage; |
3323 | } | 3326 | } |
3324 | 3327 | ||
3325 | amd64_setup_pci_device(); | 3328 | amd64_setup_pci_device(); |
3326 | 3329 | ||
3327 | return 0; | 3330 | return 0; |
3328 | 3331 | ||
3332 | err_2nd_stage: | ||
3333 | debugf0("2nd stage failed\n"); | ||
3334 | |||
3329 | err_exit: | 3335 | err_exit: |
3330 | debugf0("'finish_setup' stage failed\n"); | ||
3331 | pci_unregister_driver(&amd64_pci_driver); | 3336 | pci_unregister_driver(&amd64_pci_driver); |
3332 | 3337 | ||
3333 | return err; | 3338 | return err; |
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index a159957e167b..ba73015af8e4 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
@@ -444,7 +444,7 @@ enum { | |||
444 | #define K8_MSR_MC4ADDR 0x0412 | 444 | #define K8_MSR_MC4ADDR 0x0412 |
445 | 445 | ||
446 | /* AMD sets the first MC device at device ID 0x18. */ | 446 | /* AMD sets the first MC device at device ID 0x18. */ |
447 | static inline int get_mc_node_id_from_pdev(struct pci_dev *pdev) | 447 | static inline int get_node_id(struct pci_dev *pdev) |
448 | { | 448 | { |
449 | return PCI_SLOT(pdev->devfn) - 0x18; | 449 | return PCI_SLOT(pdev->devfn) - 0x18; |
450 | } | 450 | } |
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 3493c6bdb820..871c13b4c148 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h | |||
@@ -150,6 +150,8 @@ enum mem_type { | |||
150 | MEM_FB_DDR2, /* fully buffered DDR2 */ | 150 | MEM_FB_DDR2, /* fully buffered DDR2 */ |
151 | MEM_RDDR2, /* Registered DDR2 RAM */ | 151 | MEM_RDDR2, /* Registered DDR2 RAM */ |
152 | MEM_XDR, /* Rambus XDR */ | 152 | MEM_XDR, /* Rambus XDR */ |
153 | MEM_DDR3, /* DDR3 RAM */ | ||
154 | MEM_RDDR3, /* Registered DDR3 RAM */ | ||
153 | }; | 155 | }; |
154 | 156 | ||
155 | #define MEM_FLAG_EMPTY BIT(MEM_EMPTY) | 157 | #define MEM_FLAG_EMPTY BIT(MEM_EMPTY) |
@@ -167,6 +169,8 @@ enum mem_type { | |||
167 | #define MEM_FLAG_FB_DDR2 BIT(MEM_FB_DDR2) | 169 | #define MEM_FLAG_FB_DDR2 BIT(MEM_FB_DDR2) |
168 | #define MEM_FLAG_RDDR2 BIT(MEM_RDDR2) | 170 | #define MEM_FLAG_RDDR2 BIT(MEM_RDDR2) |
169 | #define MEM_FLAG_XDR BIT(MEM_XDR) | 171 | #define MEM_FLAG_XDR BIT(MEM_XDR) |
172 | #define MEM_FLAG_DDR3 BIT(MEM_DDR3) | ||
173 | #define MEM_FLAG_RDDR3 BIT(MEM_RDDR3) | ||
170 | 174 | ||
171 | /* chipset Error Detection and Correction capabilities and mode */ | 175 | /* chipset Error Detection and Correction capabilities and mode */ |
172 | enum edac_type { | 176 | enum edac_type { |
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index ad218fe4942d..e1d4ce083481 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
@@ -94,7 +94,9 @@ static const char *mem_types[] = { | |||
94 | [MEM_DDR2] = "Unbuffered-DDR2", | 94 | [MEM_DDR2] = "Unbuffered-DDR2", |
95 | [MEM_FB_DDR2] = "FullyBuffered-DDR2", | 95 | [MEM_FB_DDR2] = "FullyBuffered-DDR2", |
96 | [MEM_RDDR2] = "Registered-DDR2", | 96 | [MEM_RDDR2] = "Registered-DDR2", |
97 | [MEM_XDR] = "XDR" | 97 | [MEM_XDR] = "XDR", |
98 | [MEM_DDR3] = "Unbuffered-DDR3", | ||
99 | [MEM_RDDR3] = "Registered-DDR3" | ||
98 | }; | 100 | }; |
99 | 101 | ||
100 | static const char *dev_types[] = { | 102 | static const char *dev_types[] = { |
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 7c8c2d72916f..3f2ccfc6407c 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c | |||
@@ -757,6 +757,9 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) | |||
757 | case DSC_SDTYPE_DDR2: | 757 | case DSC_SDTYPE_DDR2: |
758 | mtype = MEM_RDDR2; | 758 | mtype = MEM_RDDR2; |
759 | break; | 759 | break; |
760 | case DSC_SDTYPE_DDR3: | ||
761 | mtype = MEM_RDDR3; | ||
762 | break; | ||
760 | default: | 763 | default: |
761 | mtype = MEM_UNKNOWN; | 764 | mtype = MEM_UNKNOWN; |
762 | break; | 765 | break; |
@@ -769,6 +772,9 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) | |||
769 | case DSC_SDTYPE_DDR2: | 772 | case DSC_SDTYPE_DDR2: |
770 | mtype = MEM_DDR2; | 773 | mtype = MEM_DDR2; |
771 | break; | 774 | break; |
775 | case DSC_SDTYPE_DDR3: | ||
776 | mtype = MEM_DDR3; | ||
777 | break; | ||
772 | default: | 778 | default: |
773 | mtype = MEM_UNKNOWN; | 779 | mtype = MEM_UNKNOWN; |
774 | break; | 780 | break; |
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h index 135b3539a030..52432ee7c4b9 100644 --- a/drivers/edac/mpc85xx_edac.h +++ b/drivers/edac/mpc85xx_edac.h | |||
@@ -53,6 +53,7 @@ | |||
53 | 53 | ||
54 | #define DSC_SDTYPE_DDR 0x02000000 | 54 | #define DSC_SDTYPE_DDR 0x02000000 |
55 | #define DSC_SDTYPE_DDR2 0x03000000 | 55 | #define DSC_SDTYPE_DDR2 0x03000000 |
56 | #define DSC_SDTYPE_DDR3 0x07000000 | ||
56 | #define DSC_X32_EN 0x00000020 | 57 | #define DSC_X32_EN 0x00000020 |
57 | 58 | ||
58 | /* Err_Int_En */ | 59 | /* Err_Int_En */ |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3582c39f9725..96dda81c9228 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -79,6 +79,12 @@ config GPIO_XILINX | |||
79 | help | 79 | help |
80 | Say yes here to support the Xilinx FPGA GPIO device | 80 | Say yes here to support the Xilinx FPGA GPIO device |
81 | 81 | ||
82 | config GPIO_VR41XX | ||
83 | tristate "NEC VR4100 series General-purpose I/O Uint support" | ||
84 | depends on CPU_VR41XX | ||
85 | help | ||
86 | Say yes here to support the NEC VR4100 series General-purpose I/O Uint | ||
87 | |||
82 | comment "I2C GPIO expanders:" | 88 | comment "I2C GPIO expanders:" |
83 | 89 | ||
84 | config GPIO_MAX732X | 90 | config GPIO_MAX732X |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ef90203e8f3c..9244c6fcd8be 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -13,3 +13,4 @@ obj-$(CONFIG_GPIO_PL061) += pl061.o | |||
13 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o | 13 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o |
14 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o | 14 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o |
15 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o | 15 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o |
16 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o | ||
diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c index aa8e7cb020d9..4ee4c8367a3f 100644 --- a/drivers/gpio/pl061.c +++ b/drivers/gpio/pl061.c | |||
@@ -109,6 +109,16 @@ static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value) | |||
109 | writeb(!!value << offset, chip->base + (1 << (offset + 2))); | 109 | writeb(!!value << offset, chip->base + (1 << (offset + 2))); |
110 | } | 110 | } |
111 | 111 | ||
112 | static int pl061_to_irq(struct gpio_chip *gc, unsigned offset) | ||
113 | { | ||
114 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); | ||
115 | |||
116 | if (chip->irq_base == (unsigned) -1) | ||
117 | return -EINVAL; | ||
118 | |||
119 | return chip->irq_base + offset; | ||
120 | } | ||
121 | |||
112 | /* | 122 | /* |
113 | * PL061 GPIO IRQ | 123 | * PL061 GPIO IRQ |
114 | */ | 124 | */ |
@@ -200,7 +210,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
200 | desc->chip->ack(irq); | 210 | desc->chip->ack(irq); |
201 | list_for_each(ptr, chip_list) { | 211 | list_for_each(ptr, chip_list) { |
202 | unsigned long pending; | 212 | unsigned long pending; |
203 | int gpio; | 213 | int offset; |
204 | 214 | ||
205 | chip = list_entry(ptr, struct pl061_gpio, list); | 215 | chip = list_entry(ptr, struct pl061_gpio, list); |
206 | pending = readb(chip->base + GPIOMIS); | 216 | pending = readb(chip->base + GPIOMIS); |
@@ -209,8 +219,8 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
209 | if (pending == 0) | 219 | if (pending == 0) |
210 | continue; | 220 | continue; |
211 | 221 | ||
212 | for_each_bit(gpio, &pending, PL061_GPIO_NR) | 222 | for_each_bit(offset, &pending, PL061_GPIO_NR) |
213 | generic_handle_irq(gpio_to_irq(gpio)); | 223 | generic_handle_irq(pl061_to_irq(&chip->gc, offset)); |
214 | } | 224 | } |
215 | desc->chip->unmask(irq); | 225 | desc->chip->unmask(irq); |
216 | } | 226 | } |
@@ -221,7 +231,7 @@ static int __init pl061_probe(struct amba_device *dev, struct amba_id *id) | |||
221 | struct pl061_gpio *chip; | 231 | struct pl061_gpio *chip; |
222 | struct list_head *chip_list; | 232 | struct list_head *chip_list; |
223 | int ret, irq, i; | 233 | int ret, irq, i; |
224 | static unsigned long init_irq[BITS_TO_LONGS(NR_IRQS)]; | 234 | static DECLARE_BITMAP(init_irq, NR_IRQS); |
225 | 235 | ||
226 | pdata = dev->dev.platform_data; | 236 | pdata = dev->dev.platform_data; |
227 | if (pdata == NULL) | 237 | if (pdata == NULL) |
@@ -251,6 +261,7 @@ static int __init pl061_probe(struct amba_device *dev, struct amba_id *id) | |||
251 | chip->gc.direction_output = pl061_direction_output; | 261 | chip->gc.direction_output = pl061_direction_output; |
252 | chip->gc.get = pl061_get_value; | 262 | chip->gc.get = pl061_get_value; |
253 | chip->gc.set = pl061_set_value; | 263 | chip->gc.set = pl061_set_value; |
264 | chip->gc.to_irq = pl061_to_irq; | ||
254 | chip->gc.base = pdata->gpio_base; | 265 | chip->gc.base = pdata->gpio_base; |
255 | chip->gc.ngpio = PL061_GPIO_NR; | 266 | chip->gc.ngpio = PL061_GPIO_NR; |
256 | chip->gc.label = dev_name(&dev->dev); | 267 | chip->gc.label = dev_name(&dev->dev); |
@@ -280,6 +291,7 @@ static int __init pl061_probe(struct amba_device *dev, struct amba_id *id) | |||
280 | if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */ | 291 | if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */ |
281 | chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL); | 292 | chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL); |
282 | if (chip_list == NULL) { | 293 | if (chip_list == NULL) { |
294 | clear_bit(irq, init_irq); | ||
283 | ret = -ENOMEM; | 295 | ret = -ENOMEM; |
284 | goto iounmap; | 296 | goto iounmap; |
285 | } | 297 | } |
diff --git a/drivers/gpio/vr41xx_giu.c b/drivers/gpio/vr41xx_giu.c new file mode 100644 index 000000000000..b70e06133e78 --- /dev/null +++ b/drivers/gpio/vr41xx_giu.c | |||
@@ -0,0 +1,586 @@ | |||
1 | /* | ||
2 | * Driver for NEC VR4100 series General-purpose I/O Unit. | ||
3 | * | ||
4 | * Copyright (C) 2002 MontaVista Software Inc. | ||
5 | * Author: Yoichi Yuasa <source@mvista.com> | ||
6 | * Copyright (C) 2003-2009 Yoichi Yuasa <yuasa@linux-mips.org> | ||
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 as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <linux/gpio.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/irq.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/smp_lock.h> | ||
33 | #include <linux/spinlock.h> | ||
34 | #include <linux/types.h> | ||
35 | |||
36 | #include <asm/vr41xx/giu.h> | ||
37 | #include <asm/vr41xx/irq.h> | ||
38 | #include <asm/vr41xx/vr41xx.h> | ||
39 | |||
40 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); | ||
41 | MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); | ||
42 | MODULE_LICENSE("GPL"); | ||
43 | |||
44 | #define GIUIOSELL 0x00 | ||
45 | #define GIUIOSELH 0x02 | ||
46 | #define GIUPIODL 0x04 | ||
47 | #define GIUPIODH 0x06 | ||
48 | #define GIUINTSTATL 0x08 | ||
49 | #define GIUINTSTATH 0x0a | ||
50 | #define GIUINTENL 0x0c | ||
51 | #define GIUINTENH 0x0e | ||
52 | #define GIUINTTYPL 0x10 | ||
53 | #define GIUINTTYPH 0x12 | ||
54 | #define GIUINTALSELL 0x14 | ||
55 | #define GIUINTALSELH 0x16 | ||
56 | #define GIUINTHTSELL 0x18 | ||
57 | #define GIUINTHTSELH 0x1a | ||
58 | #define GIUPODATL 0x1c | ||
59 | #define GIUPODATEN 0x1c | ||
60 | #define GIUPODATH 0x1e | ||
61 | #define PIOEN0 0x0100 | ||
62 | #define PIOEN1 0x0200 | ||
63 | #define GIUPODAT 0x1e | ||
64 | #define GIUFEDGEINHL 0x20 | ||
65 | #define GIUFEDGEINHH 0x22 | ||
66 | #define GIUREDGEINHL 0x24 | ||
67 | #define GIUREDGEINHH 0x26 | ||
68 | |||
69 | #define GIUUSEUPDN 0x1e0 | ||
70 | #define GIUTERMUPDN 0x1e2 | ||
71 | |||
72 | #define GPIO_HAS_PULLUPDOWN_IO 0x0001 | ||
73 | #define GPIO_HAS_OUTPUT_ENABLE 0x0002 | ||
74 | #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 | ||
75 | |||
76 | enum { | ||
77 | GPIO_INPUT, | ||
78 | GPIO_OUTPUT, | ||
79 | }; | ||
80 | |||
81 | static DEFINE_SPINLOCK(giu_lock); | ||
82 | static unsigned long giu_flags; | ||
83 | |||
84 | static void __iomem *giu_base; | ||
85 | |||
86 | #define giu_read(offset) readw(giu_base + (offset)) | ||
87 | #define giu_write(offset, value) writew((value), giu_base + (offset)) | ||
88 | |||
89 | #define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) | ||
90 | #define GIUINT_HIGH_OFFSET 16 | ||
91 | #define GIUINT_HIGH_MAX 32 | ||
92 | |||
93 | static inline u16 giu_set(u16 offset, u16 set) | ||
94 | { | ||
95 | u16 data; | ||
96 | |||
97 | data = giu_read(offset); | ||
98 | data |= set; | ||
99 | giu_write(offset, data); | ||
100 | |||
101 | return data; | ||
102 | } | ||
103 | |||
104 | static inline u16 giu_clear(u16 offset, u16 clear) | ||
105 | { | ||
106 | u16 data; | ||
107 | |||
108 | data = giu_read(offset); | ||
109 | data &= ~clear; | ||
110 | giu_write(offset, data); | ||
111 | |||
112 | return data; | ||
113 | } | ||
114 | |||
115 | static void ack_giuint_low(unsigned int irq) | ||
116 | { | ||
117 | giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
118 | } | ||
119 | |||
120 | static void mask_giuint_low(unsigned int irq) | ||
121 | { | ||
122 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
123 | } | ||
124 | |||
125 | static void mask_ack_giuint_low(unsigned int irq) | ||
126 | { | ||
127 | unsigned int pin; | ||
128 | |||
129 | pin = GPIO_PIN_OF_IRQ(irq); | ||
130 | giu_clear(GIUINTENL, 1 << pin); | ||
131 | giu_write(GIUINTSTATL, 1 << pin); | ||
132 | } | ||
133 | |||
134 | static void unmask_giuint_low(unsigned int irq) | ||
135 | { | ||
136 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
137 | } | ||
138 | |||
139 | static struct irq_chip giuint_low_irq_chip = { | ||
140 | .name = "GIUINTL", | ||
141 | .ack = ack_giuint_low, | ||
142 | .mask = mask_giuint_low, | ||
143 | .mask_ack = mask_ack_giuint_low, | ||
144 | .unmask = unmask_giuint_low, | ||
145 | }; | ||
146 | |||
147 | static void ack_giuint_high(unsigned int irq) | ||
148 | { | ||
149 | giu_write(GIUINTSTATH, | ||
150 | 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
151 | } | ||
152 | |||
153 | static void mask_giuint_high(unsigned int irq) | ||
154 | { | ||
155 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
156 | } | ||
157 | |||
158 | static void mask_ack_giuint_high(unsigned int irq) | ||
159 | { | ||
160 | unsigned int pin; | ||
161 | |||
162 | pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; | ||
163 | giu_clear(GIUINTENH, 1 << pin); | ||
164 | giu_write(GIUINTSTATH, 1 << pin); | ||
165 | } | ||
166 | |||
167 | static void unmask_giuint_high(unsigned int irq) | ||
168 | { | ||
169 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
170 | } | ||
171 | |||
172 | static struct irq_chip giuint_high_irq_chip = { | ||
173 | .name = "GIUINTH", | ||
174 | .ack = ack_giuint_high, | ||
175 | .mask = mask_giuint_high, | ||
176 | .mask_ack = mask_ack_giuint_high, | ||
177 | .unmask = unmask_giuint_high, | ||
178 | }; | ||
179 | |||
180 | static int giu_get_irq(unsigned int irq) | ||
181 | { | ||
182 | u16 pendl, pendh, maskl, maskh; | ||
183 | int i; | ||
184 | |||
185 | pendl = giu_read(GIUINTSTATL); | ||
186 | pendh = giu_read(GIUINTSTATH); | ||
187 | maskl = giu_read(GIUINTENL); | ||
188 | maskh = giu_read(GIUINTENH); | ||
189 | |||
190 | maskl &= pendl; | ||
191 | maskh &= pendh; | ||
192 | |||
193 | if (maskl) { | ||
194 | for (i = 0; i < 16; i++) { | ||
195 | if (maskl & (1 << i)) | ||
196 | return GIU_IRQ(i); | ||
197 | } | ||
198 | } else if (maskh) { | ||
199 | for (i = 0; i < 16; i++) { | ||
200 | if (maskh & (1 << i)) | ||
201 | return GIU_IRQ(i + GIUINT_HIGH_OFFSET); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", | ||
206 | maskl, pendl, maskh, pendh); | ||
207 | |||
208 | atomic_inc(&irq_err_count); | ||
209 | |||
210 | return -EINVAL; | ||
211 | } | ||
212 | |||
213 | void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, | ||
214 | irq_signal_t signal) | ||
215 | { | ||
216 | u16 mask; | ||
217 | |||
218 | if (pin < GIUINT_HIGH_OFFSET) { | ||
219 | mask = 1 << pin; | ||
220 | if (trigger != IRQ_TRIGGER_LEVEL) { | ||
221 | giu_set(GIUINTTYPL, mask); | ||
222 | if (signal == IRQ_SIGNAL_HOLD) | ||
223 | giu_set(GIUINTHTSELL, mask); | ||
224 | else | ||
225 | giu_clear(GIUINTHTSELL, mask); | ||
226 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | ||
227 | switch (trigger) { | ||
228 | case IRQ_TRIGGER_EDGE_FALLING: | ||
229 | giu_set(GIUFEDGEINHL, mask); | ||
230 | giu_clear(GIUREDGEINHL, mask); | ||
231 | break; | ||
232 | case IRQ_TRIGGER_EDGE_RISING: | ||
233 | giu_clear(GIUFEDGEINHL, mask); | ||
234 | giu_set(GIUREDGEINHL, mask); | ||
235 | break; | ||
236 | default: | ||
237 | giu_set(GIUFEDGEINHL, mask); | ||
238 | giu_set(GIUREDGEINHL, mask); | ||
239 | break; | ||
240 | } | ||
241 | } | ||
242 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
243 | &giuint_low_irq_chip, | ||
244 | handle_edge_irq); | ||
245 | } else { | ||
246 | giu_clear(GIUINTTYPL, mask); | ||
247 | giu_clear(GIUINTHTSELL, mask); | ||
248 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
249 | &giuint_low_irq_chip, | ||
250 | handle_level_irq); | ||
251 | } | ||
252 | giu_write(GIUINTSTATL, mask); | ||
253 | } else if (pin < GIUINT_HIGH_MAX) { | ||
254 | mask = 1 << (pin - GIUINT_HIGH_OFFSET); | ||
255 | if (trigger != IRQ_TRIGGER_LEVEL) { | ||
256 | giu_set(GIUINTTYPH, mask); | ||
257 | if (signal == IRQ_SIGNAL_HOLD) | ||
258 | giu_set(GIUINTHTSELH, mask); | ||
259 | else | ||
260 | giu_clear(GIUINTHTSELH, mask); | ||
261 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | ||
262 | switch (trigger) { | ||
263 | case IRQ_TRIGGER_EDGE_FALLING: | ||
264 | giu_set(GIUFEDGEINHH, mask); | ||
265 | giu_clear(GIUREDGEINHH, mask); | ||
266 | break; | ||
267 | case IRQ_TRIGGER_EDGE_RISING: | ||
268 | giu_clear(GIUFEDGEINHH, mask); | ||
269 | giu_set(GIUREDGEINHH, mask); | ||
270 | break; | ||
271 | default: | ||
272 | giu_set(GIUFEDGEINHH, mask); | ||
273 | giu_set(GIUREDGEINHH, mask); | ||
274 | break; | ||
275 | } | ||
276 | } | ||
277 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
278 | &giuint_high_irq_chip, | ||
279 | handle_edge_irq); | ||
280 | } else { | ||
281 | giu_clear(GIUINTTYPH, mask); | ||
282 | giu_clear(GIUINTHTSELH, mask); | ||
283 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
284 | &giuint_high_irq_chip, | ||
285 | handle_level_irq); | ||
286 | } | ||
287 | giu_write(GIUINTSTATH, mask); | ||
288 | } | ||
289 | } | ||
290 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); | ||
291 | |||
292 | void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) | ||
293 | { | ||
294 | u16 mask; | ||
295 | |||
296 | if (pin < GIUINT_HIGH_OFFSET) { | ||
297 | mask = 1 << pin; | ||
298 | if (level == IRQ_LEVEL_HIGH) | ||
299 | giu_set(GIUINTALSELL, mask); | ||
300 | else | ||
301 | giu_clear(GIUINTALSELL, mask); | ||
302 | giu_write(GIUINTSTATL, mask); | ||
303 | } else if (pin < GIUINT_HIGH_MAX) { | ||
304 | mask = 1 << (pin - GIUINT_HIGH_OFFSET); | ||
305 | if (level == IRQ_LEVEL_HIGH) | ||
306 | giu_set(GIUINTALSELH, mask); | ||
307 | else | ||
308 | giu_clear(GIUINTALSELH, mask); | ||
309 | giu_write(GIUINTSTATH, mask); | ||
310 | } | ||
311 | } | ||
312 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); | ||
313 | |||
314 | static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir) | ||
315 | { | ||
316 | u16 offset, mask, reg; | ||
317 | unsigned long flags; | ||
318 | |||
319 | if (pin >= chip->ngpio) | ||
320 | return -EINVAL; | ||
321 | |||
322 | if (pin < 16) { | ||
323 | offset = GIUIOSELL; | ||
324 | mask = 1 << pin; | ||
325 | } else if (pin < 32) { | ||
326 | offset = GIUIOSELH; | ||
327 | mask = 1 << (pin - 16); | ||
328 | } else { | ||
329 | if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { | ||
330 | offset = GIUPODATEN; | ||
331 | mask = 1 << (pin - 32); | ||
332 | } else { | ||
333 | switch (pin) { | ||
334 | case 48: | ||
335 | offset = GIUPODATH; | ||
336 | mask = PIOEN0; | ||
337 | break; | ||
338 | case 49: | ||
339 | offset = GIUPODATH; | ||
340 | mask = PIOEN1; | ||
341 | break; | ||
342 | default: | ||
343 | return -EINVAL; | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | |||
348 | spin_lock_irqsave(&giu_lock, flags); | ||
349 | |||
350 | reg = giu_read(offset); | ||
351 | if (dir == GPIO_OUTPUT) | ||
352 | reg |= mask; | ||
353 | else | ||
354 | reg &= ~mask; | ||
355 | giu_write(offset, reg); | ||
356 | |||
357 | spin_unlock_irqrestore(&giu_lock, flags); | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) | ||
363 | { | ||
364 | u16 reg, mask; | ||
365 | unsigned long flags; | ||
366 | |||
367 | if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO) | ||
368 | return -EPERM; | ||
369 | |||
370 | if (pin >= 15) | ||
371 | return -EINVAL; | ||
372 | |||
373 | mask = 1 << pin; | ||
374 | |||
375 | spin_lock_irqsave(&giu_lock, flags); | ||
376 | |||
377 | if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) { | ||
378 | reg = giu_read(GIUTERMUPDN); | ||
379 | if (pull == GPIO_PULL_UP) | ||
380 | reg |= mask; | ||
381 | else | ||
382 | reg &= ~mask; | ||
383 | giu_write(GIUTERMUPDN, reg); | ||
384 | |||
385 | reg = giu_read(GIUUSEUPDN); | ||
386 | reg |= mask; | ||
387 | giu_write(GIUUSEUPDN, reg); | ||
388 | } else { | ||
389 | reg = giu_read(GIUUSEUPDN); | ||
390 | reg &= ~mask; | ||
391 | giu_write(GIUUSEUPDN, reg); | ||
392 | } | ||
393 | |||
394 | spin_unlock_irqrestore(&giu_lock, flags); | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); | ||
399 | |||
400 | static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin) | ||
401 | { | ||
402 | u16 reg, mask; | ||
403 | |||
404 | if (pin >= chip->ngpio) | ||
405 | return -EINVAL; | ||
406 | |||
407 | if (pin < 16) { | ||
408 | reg = giu_read(GIUPIODL); | ||
409 | mask = 1 << pin; | ||
410 | } else if (pin < 32) { | ||
411 | reg = giu_read(GIUPIODH); | ||
412 | mask = 1 << (pin - 16); | ||
413 | } else if (pin < 48) { | ||
414 | reg = giu_read(GIUPODATL); | ||
415 | mask = 1 << (pin - 32); | ||
416 | } else { | ||
417 | reg = giu_read(GIUPODATH); | ||
418 | mask = 1 << (pin - 48); | ||
419 | } | ||
420 | |||
421 | if (reg & mask) | ||
422 | return 1; | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin, | ||
428 | int value) | ||
429 | { | ||
430 | u16 offset, mask, reg; | ||
431 | unsigned long flags; | ||
432 | |||
433 | if (pin >= chip->ngpio) | ||
434 | return; | ||
435 | |||
436 | if (pin < 16) { | ||
437 | offset = GIUPIODL; | ||
438 | mask = 1 << pin; | ||
439 | } else if (pin < 32) { | ||
440 | offset = GIUPIODH; | ||
441 | mask = 1 << (pin - 16); | ||
442 | } else if (pin < 48) { | ||
443 | offset = GIUPODATL; | ||
444 | mask = 1 << (pin - 32); | ||
445 | } else { | ||
446 | offset = GIUPODATH; | ||
447 | mask = 1 << (pin - 48); | ||
448 | } | ||
449 | |||
450 | spin_lock_irqsave(&giu_lock, flags); | ||
451 | |||
452 | reg = giu_read(offset); | ||
453 | if (value) | ||
454 | reg |= mask; | ||
455 | else | ||
456 | reg &= ~mask; | ||
457 | giu_write(offset, reg); | ||
458 | |||
459 | spin_unlock_irqrestore(&giu_lock, flags); | ||
460 | } | ||
461 | |||
462 | |||
463 | static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
464 | { | ||
465 | return giu_set_direction(chip, offset, GPIO_INPUT); | ||
466 | } | ||
467 | |||
468 | static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | ||
469 | int value) | ||
470 | { | ||
471 | vr41xx_gpio_set(chip, offset, value); | ||
472 | |||
473 | return giu_set_direction(chip, offset, GPIO_OUTPUT); | ||
474 | } | ||
475 | |||
476 | static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
477 | { | ||
478 | if (offset >= chip->ngpio) | ||
479 | return -EINVAL; | ||
480 | |||
481 | return GIU_IRQ_BASE + offset; | ||
482 | } | ||
483 | |||
484 | static struct gpio_chip vr41xx_gpio_chip = { | ||
485 | .label = "vr41xx", | ||
486 | .owner = THIS_MODULE, | ||
487 | .direction_input = vr41xx_gpio_direction_input, | ||
488 | .get = vr41xx_gpio_get, | ||
489 | .direction_output = vr41xx_gpio_direction_output, | ||
490 | .set = vr41xx_gpio_set, | ||
491 | .to_irq = vr41xx_gpio_to_irq, | ||
492 | }; | ||
493 | |||
494 | static int __devinit giu_probe(struct platform_device *pdev) | ||
495 | { | ||
496 | struct resource *res; | ||
497 | unsigned int trigger, i, pin; | ||
498 | struct irq_chip *chip; | ||
499 | int irq, retval; | ||
500 | |||
501 | switch (pdev->id) { | ||
502 | case GPIO_50PINS_PULLUPDOWN: | ||
503 | giu_flags = GPIO_HAS_PULLUPDOWN_IO; | ||
504 | vr41xx_gpio_chip.ngpio = 50; | ||
505 | break; | ||
506 | case GPIO_36PINS: | ||
507 | vr41xx_gpio_chip.ngpio = 36; | ||
508 | break; | ||
509 | case GPIO_48PINS_EDGE_SELECT: | ||
510 | giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; | ||
511 | vr41xx_gpio_chip.ngpio = 48; | ||
512 | break; | ||
513 | default: | ||
514 | dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id); | ||
515 | return -ENODEV; | ||
516 | } | ||
517 | |||
518 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
519 | if (!res) | ||
520 | return -EBUSY; | ||
521 | |||
522 | giu_base = ioremap(res->start, res->end - res->start + 1); | ||
523 | if (!giu_base) | ||
524 | return -ENOMEM; | ||
525 | |||
526 | vr41xx_gpio_chip.dev = &pdev->dev; | ||
527 | |||
528 | retval = gpiochip_add(&vr41xx_gpio_chip); | ||
529 | |||
530 | giu_write(GIUINTENL, 0); | ||
531 | giu_write(GIUINTENH, 0); | ||
532 | |||
533 | trigger = giu_read(GIUINTTYPH) << 16; | ||
534 | trigger |= giu_read(GIUINTTYPL); | ||
535 | for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { | ||
536 | pin = GPIO_PIN_OF_IRQ(i); | ||
537 | if (pin < GIUINT_HIGH_OFFSET) | ||
538 | chip = &giuint_low_irq_chip; | ||
539 | else | ||
540 | chip = &giuint_high_irq_chip; | ||
541 | |||
542 | if (trigger & (1 << pin)) | ||
543 | set_irq_chip_and_handler(i, chip, handle_edge_irq); | ||
544 | else | ||
545 | set_irq_chip_and_handler(i, chip, handle_level_irq); | ||
546 | |||
547 | } | ||
548 | |||
549 | irq = platform_get_irq(pdev, 0); | ||
550 | if (irq < 0 || irq >= nr_irqs) | ||
551 | return -EBUSY; | ||
552 | |||
553 | return cascade_irq(irq, giu_get_irq); | ||
554 | } | ||
555 | |||
556 | static int __devexit giu_remove(struct platform_device *pdev) | ||
557 | { | ||
558 | if (giu_base) { | ||
559 | iounmap(giu_base); | ||
560 | giu_base = NULL; | ||
561 | } | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static struct platform_driver giu_device_driver = { | ||
567 | .probe = giu_probe, | ||
568 | .remove = __devexit_p(giu_remove), | ||
569 | .driver = { | ||
570 | .name = "GIU", | ||
571 | .owner = THIS_MODULE, | ||
572 | }, | ||
573 | }; | ||
574 | |||
575 | static int __init vr41xx_giu_init(void) | ||
576 | { | ||
577 | return platform_driver_register(&giu_device_driver); | ||
578 | } | ||
579 | |||
580 | static void __exit vr41xx_giu_exit(void) | ||
581 | { | ||
582 | platform_driver_unregister(&giu_device_driver); | ||
583 | } | ||
584 | |||
585 | module_init(vr41xx_giu_init); | ||
586 | module_exit(vr41xx_giu_exit); | ||
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index c961fe415aef..39b393d38bb3 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
@@ -81,6 +81,7 @@ config DRM_I830 | |||
81 | 81 | ||
82 | config DRM_I915 | 82 | config DRM_I915 |
83 | tristate "i915 driver" | 83 | tristate "i915 driver" |
84 | depends on AGP_INTEL | ||
84 | select FB_CFB_FILLRECT | 85 | select FB_CFB_FILLRECT |
85 | select FB_CFB_COPYAREA | 86 | select FB_CFB_COPYAREA |
86 | select FB_CFB_IMAGEBLIT | 87 | select FB_CFB_IMAGEBLIT |
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 4e89ab08b7b8..fe23f29f7cba 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
@@ -16,6 +16,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ | |||
16 | drm-$(CONFIG_COMPAT) += drm_ioc32.o | 16 | drm-$(CONFIG_COMPAT) += drm_ioc32.o |
17 | 17 | ||
18 | obj-$(CONFIG_DRM) += drm.o | 18 | obj-$(CONFIG_DRM) += drm.o |
19 | obj-$(CONFIG_DRM_TTM) += ttm/ | ||
19 | obj-$(CONFIG_DRM_TDFX) += tdfx/ | 20 | obj-$(CONFIG_DRM_TDFX) += tdfx/ |
20 | obj-$(CONFIG_DRM_R128) += r128/ | 21 | obj-$(CONFIG_DRM_R128) += r128/ |
21 | obj-$(CONFIG_DRM_RADEON)+= radeon/ | 22 | obj-$(CONFIG_DRM_RADEON)+= radeon/ |
@@ -26,4 +27,3 @@ obj-$(CONFIG_DRM_I915) += i915/ | |||
26 | obj-$(CONFIG_DRM_SIS) += sis/ | 27 | obj-$(CONFIG_DRM_SIS) += sis/ |
27 | obj-$(CONFIG_DRM_SAVAGE)+= savage/ | 28 | obj-$(CONFIG_DRM_SAVAGE)+= savage/ |
28 | obj-$(CONFIG_DRM_VIA) +=via/ | 29 | obj-$(CONFIG_DRM_VIA) +=via/ |
29 | obj-$(CONFIG_DRM_TTM) += ttm/ | ||
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 7d0835226f6e..80cc6d06d61b 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -294,10 +294,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
294 | unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo; | 294 | unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo; |
295 | unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo; | 295 | unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo; |
296 | unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo; | 296 | unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo; |
297 | unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 8 | pt->hsync_offset_lo; | 297 | unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo; |
298 | unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 6 | pt->hsync_pulse_width_lo; | 298 | unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo; |
299 | unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) | (pt->vsync_offset_pulse_width_lo & 0xf); | 299 | unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4; |
300 | unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) >> 2 | pt->vsync_offset_pulse_width_lo >> 4; | 300 | unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf); |
301 | 301 | ||
302 | /* ignore tiny modes */ | 302 | /* ignore tiny modes */ |
303 | if (hactive < 64 || vactive < 64) | 303 | if (hactive < 64 || vactive < 64) |
@@ -347,8 +347,8 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
347 | mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? | 347 | mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? |
348 | DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; | 348 | DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; |
349 | 349 | ||
350 | mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; | 350 | mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; |
351 | mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; | 351 | mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; |
352 | 352 | ||
353 | if (quirks & EDID_QUIRK_DETAILED_IN_CM) { | 353 | if (quirks & EDID_QUIRK_DETAILED_IN_CM) { |
354 | mode->width_mm *= 10; | 354 | mode->width_mm *= 10; |
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 51c5a050aa73..30d6b99fb302 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
@@ -13,6 +13,8 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ | |||
13 | intel_crt.o \ | 13 | intel_crt.o \ |
14 | intel_lvds.o \ | 14 | intel_lvds.o \ |
15 | intel_bios.o \ | 15 | intel_bios.o \ |
16 | intel_dp.o \ | ||
17 | intel_dp_i2c.o \ | ||
16 | intel_hdmi.o \ | 18 | intel_hdmi.o \ |
17 | intel_sdvo.o \ | 19 | intel_sdvo.o \ |
18 | intel_modes.o \ | 20 | intel_modes.o \ |
diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h index e747ac42fe3a..288fc50627e2 100644 --- a/drivers/gpu/drm/i915/dvo.h +++ b/drivers/gpu/drm/i915/dvo.h | |||
@@ -37,7 +37,7 @@ struct intel_dvo_device { | |||
37 | /* GPIO register used for i2c bus to control this device */ | 37 | /* GPIO register used for i2c bus to control this device */ |
38 | u32 gpio; | 38 | u32 gpio; |
39 | int slave_addr; | 39 | int slave_addr; |
40 | struct intel_i2c_chan *i2c_bus; | 40 | struct i2c_adapter *i2c_bus; |
41 | 41 | ||
42 | const struct intel_dvo_dev_ops *dev_ops; | 42 | const struct intel_dvo_dev_ops *dev_ops; |
43 | void *dev_priv; | 43 | void *dev_priv; |
@@ -52,7 +52,7 @@ struct intel_dvo_dev_ops { | |||
52 | * Returns NULL if the device does not exist. | 52 | * Returns NULL if the device does not exist. |
53 | */ | 53 | */ |
54 | bool (*init)(struct intel_dvo_device *dvo, | 54 | bool (*init)(struct intel_dvo_device *dvo, |
55 | struct intel_i2c_chan *i2cbus); | 55 | struct i2c_adapter *i2cbus); |
56 | 56 | ||
57 | /* | 57 | /* |
58 | * Called to allow the output a chance to create properties after the | 58 | * Called to allow the output a chance to create properties after the |
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c index 03d4b4973b02..621815b531db 100644 --- a/drivers/gpu/drm/i915/dvo_ch7017.c +++ b/drivers/gpu/drm/i915/dvo_ch7017.c | |||
@@ -176,19 +176,20 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode); | |||
176 | 176 | ||
177 | static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) | 177 | static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) |
178 | { | 178 | { |
179 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 179 | struct i2c_adapter *adapter = dvo->i2c_bus; |
180 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
180 | u8 out_buf[2]; | 181 | u8 out_buf[2]; |
181 | u8 in_buf[2]; | 182 | u8 in_buf[2]; |
182 | 183 | ||
183 | struct i2c_msg msgs[] = { | 184 | struct i2c_msg msgs[] = { |
184 | { | 185 | { |
185 | .addr = i2cbus->slave_addr, | 186 | .addr = dvo->slave_addr, |
186 | .flags = 0, | 187 | .flags = 0, |
187 | .len = 1, | 188 | .len = 1, |
188 | .buf = out_buf, | 189 | .buf = out_buf, |
189 | }, | 190 | }, |
190 | { | 191 | { |
191 | .addr = i2cbus->slave_addr, | 192 | .addr = dvo->slave_addr, |
192 | .flags = I2C_M_RD, | 193 | .flags = I2C_M_RD, |
193 | .len = 1, | 194 | .len = 1, |
194 | .buf = in_buf, | 195 | .buf = in_buf, |
@@ -208,10 +209,11 @@ static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) | |||
208 | 209 | ||
209 | static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) | 210 | static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) |
210 | { | 211 | { |
211 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 212 | struct i2c_adapter *adapter = dvo->i2c_bus; |
213 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
212 | uint8_t out_buf[2]; | 214 | uint8_t out_buf[2]; |
213 | struct i2c_msg msg = { | 215 | struct i2c_msg msg = { |
214 | .addr = i2cbus->slave_addr, | 216 | .addr = dvo->slave_addr, |
215 | .flags = 0, | 217 | .flags = 0, |
216 | .len = 2, | 218 | .len = 2, |
217 | .buf = out_buf, | 219 | .buf = out_buf, |
@@ -228,8 +230,9 @@ static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) | |||
228 | 230 | ||
229 | /** Probes for a CH7017 on the given bus and slave address. */ | 231 | /** Probes for a CH7017 on the given bus and slave address. */ |
230 | static bool ch7017_init(struct intel_dvo_device *dvo, | 232 | static bool ch7017_init(struct intel_dvo_device *dvo, |
231 | struct intel_i2c_chan *i2cbus) | 233 | struct i2c_adapter *adapter) |
232 | { | 234 | { |
235 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
233 | struct ch7017_priv *priv; | 236 | struct ch7017_priv *priv; |
234 | uint8_t val; | 237 | uint8_t val; |
235 | 238 | ||
@@ -237,8 +240,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo, | |||
237 | if (priv == NULL) | 240 | if (priv == NULL) |
238 | return false; | 241 | return false; |
239 | 242 | ||
240 | dvo->i2c_bus = i2cbus; | 243 | dvo->i2c_bus = adapter; |
241 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
242 | dvo->dev_priv = priv; | 244 | dvo->dev_priv = priv; |
243 | 245 | ||
244 | if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val)) | 246 | if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val)) |
@@ -248,7 +250,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo, | |||
248 | val != CH7018_DEVICE_ID_VALUE && | 250 | val != CH7018_DEVICE_ID_VALUE && |
249 | val != CH7019_DEVICE_ID_VALUE) { | 251 | val != CH7019_DEVICE_ID_VALUE) { |
250 | DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n", | 252 | DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n", |
251 | val, i2cbus->adapter.name,i2cbus->slave_addr); | 253 | val, i2cbus->adapter.name,dvo->slave_addr); |
252 | goto fail; | 254 | goto fail; |
253 | } | 255 | } |
254 | 256 | ||
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c index d2fd95dbd034..a9b896289680 100644 --- a/drivers/gpu/drm/i915/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c | |||
@@ -123,19 +123,20 @@ static char *ch7xxx_get_id(uint8_t vid) | |||
123 | static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | 123 | static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) |
124 | { | 124 | { |
125 | struct ch7xxx_priv *ch7xxx= dvo->dev_priv; | 125 | struct ch7xxx_priv *ch7xxx= dvo->dev_priv; |
126 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 126 | struct i2c_adapter *adapter = dvo->i2c_bus; |
127 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
127 | u8 out_buf[2]; | 128 | u8 out_buf[2]; |
128 | u8 in_buf[2]; | 129 | u8 in_buf[2]; |
129 | 130 | ||
130 | struct i2c_msg msgs[] = { | 131 | struct i2c_msg msgs[] = { |
131 | { | 132 | { |
132 | .addr = i2cbus->slave_addr, | 133 | .addr = dvo->slave_addr, |
133 | .flags = 0, | 134 | .flags = 0, |
134 | .len = 1, | 135 | .len = 1, |
135 | .buf = out_buf, | 136 | .buf = out_buf, |
136 | }, | 137 | }, |
137 | { | 138 | { |
138 | .addr = i2cbus->slave_addr, | 139 | .addr = dvo->slave_addr, |
139 | .flags = I2C_M_RD, | 140 | .flags = I2C_M_RD, |
140 | .len = 1, | 141 | .len = 1, |
141 | .buf = in_buf, | 142 | .buf = in_buf, |
@@ -152,7 +153,7 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
152 | 153 | ||
153 | if (!ch7xxx->quiet) { | 154 | if (!ch7xxx->quiet) { |
154 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", | 155 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", |
155 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 156 | addr, i2cbus->adapter.name, dvo->slave_addr); |
156 | } | 157 | } |
157 | return false; | 158 | return false; |
158 | } | 159 | } |
@@ -161,10 +162,11 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
161 | static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | 162 | static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) |
162 | { | 163 | { |
163 | struct ch7xxx_priv *ch7xxx = dvo->dev_priv; | 164 | struct ch7xxx_priv *ch7xxx = dvo->dev_priv; |
164 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 165 | struct i2c_adapter *adapter = dvo->i2c_bus; |
166 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
165 | uint8_t out_buf[2]; | 167 | uint8_t out_buf[2]; |
166 | struct i2c_msg msg = { | 168 | struct i2c_msg msg = { |
167 | .addr = i2cbus->slave_addr, | 169 | .addr = dvo->slave_addr, |
168 | .flags = 0, | 170 | .flags = 0, |
169 | .len = 2, | 171 | .len = 2, |
170 | .buf = out_buf, | 172 | .buf = out_buf, |
@@ -178,14 +180,14 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
178 | 180 | ||
179 | if (!ch7xxx->quiet) { | 181 | if (!ch7xxx->quiet) { |
180 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", | 182 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", |
181 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 183 | addr, i2cbus->adapter.name, dvo->slave_addr); |
182 | } | 184 | } |
183 | 185 | ||
184 | return false; | 186 | return false; |
185 | } | 187 | } |
186 | 188 | ||
187 | static bool ch7xxx_init(struct intel_dvo_device *dvo, | 189 | static bool ch7xxx_init(struct intel_dvo_device *dvo, |
188 | struct intel_i2c_chan *i2cbus) | 190 | struct i2c_adapter *adapter) |
189 | { | 191 | { |
190 | /* this will detect the CH7xxx chip on the specified i2c bus */ | 192 | /* this will detect the CH7xxx chip on the specified i2c bus */ |
191 | struct ch7xxx_priv *ch7xxx; | 193 | struct ch7xxx_priv *ch7xxx; |
@@ -196,8 +198,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, | |||
196 | if (ch7xxx == NULL) | 198 | if (ch7xxx == NULL) |
197 | return false; | 199 | return false; |
198 | 200 | ||
199 | dvo->i2c_bus = i2cbus; | 201 | dvo->i2c_bus = adapter; |
200 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
201 | dvo->dev_priv = ch7xxx; | 202 | dvo->dev_priv = ch7xxx; |
202 | ch7xxx->quiet = true; | 203 | ch7xxx->quiet = true; |
203 | 204 | ||
@@ -207,7 +208,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, | |||
207 | name = ch7xxx_get_id(vendor); | 208 | name = ch7xxx_get_id(vendor); |
208 | if (!name) { | 209 | if (!name) { |
209 | DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", | 210 | DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", |
210 | vendor, i2cbus->adapter.name, i2cbus->slave_addr); | 211 | vendor, adapter->name, dvo->slave_addr); |
211 | goto out; | 212 | goto out; |
212 | } | 213 | } |
213 | 214 | ||
@@ -217,7 +218,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, | |||
217 | 218 | ||
218 | if (device != CH7xxx_DID) { | 219 | if (device != CH7xxx_DID) { |
219 | DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", | 220 | DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", |
220 | vendor, i2cbus->adapter.name, i2cbus->slave_addr); | 221 | vendor, adapter->name, dvo->slave_addr); |
221 | goto out; | 222 | goto out; |
222 | } | 223 | } |
223 | 224 | ||
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c index 0c8d375e8e37..aa176f9921fe 100644 --- a/drivers/gpu/drm/i915/dvo_ivch.c +++ b/drivers/gpu/drm/i915/dvo_ivch.c | |||
@@ -169,13 +169,14 @@ static void ivch_dump_regs(struct intel_dvo_device *dvo); | |||
169 | static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | 169 | static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) |
170 | { | 170 | { |
171 | struct ivch_priv *priv = dvo->dev_priv; | 171 | struct ivch_priv *priv = dvo->dev_priv; |
172 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 172 | struct i2c_adapter *adapter = dvo->i2c_bus; |
173 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
173 | u8 out_buf[1]; | 174 | u8 out_buf[1]; |
174 | u8 in_buf[2]; | 175 | u8 in_buf[2]; |
175 | 176 | ||
176 | struct i2c_msg msgs[] = { | 177 | struct i2c_msg msgs[] = { |
177 | { | 178 | { |
178 | .addr = i2cbus->slave_addr, | 179 | .addr = dvo->slave_addr, |
179 | .flags = I2C_M_RD, | 180 | .flags = I2C_M_RD, |
180 | .len = 0, | 181 | .len = 0, |
181 | }, | 182 | }, |
@@ -186,7 +187,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | |||
186 | .buf = out_buf, | 187 | .buf = out_buf, |
187 | }, | 188 | }, |
188 | { | 189 | { |
189 | .addr = i2cbus->slave_addr, | 190 | .addr = dvo->slave_addr, |
190 | .flags = I2C_M_RD | I2C_M_NOSTART, | 191 | .flags = I2C_M_RD | I2C_M_NOSTART, |
191 | .len = 2, | 192 | .len = 2, |
192 | .buf = in_buf, | 193 | .buf = in_buf, |
@@ -202,7 +203,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | |||
202 | 203 | ||
203 | if (!priv->quiet) { | 204 | if (!priv->quiet) { |
204 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", | 205 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", |
205 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 206 | addr, i2cbus->adapter.name, dvo->slave_addr); |
206 | } | 207 | } |
207 | return false; | 208 | return false; |
208 | } | 209 | } |
@@ -211,10 +212,11 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | |||
211 | static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) | 212 | static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) |
212 | { | 213 | { |
213 | struct ivch_priv *priv = dvo->dev_priv; | 214 | struct ivch_priv *priv = dvo->dev_priv; |
214 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 215 | struct i2c_adapter *adapter = dvo->i2c_bus; |
216 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
215 | u8 out_buf[3]; | 217 | u8 out_buf[3]; |
216 | struct i2c_msg msg = { | 218 | struct i2c_msg msg = { |
217 | .addr = i2cbus->slave_addr, | 219 | .addr = dvo->slave_addr, |
218 | .flags = 0, | 220 | .flags = 0, |
219 | .len = 3, | 221 | .len = 3, |
220 | .buf = out_buf, | 222 | .buf = out_buf, |
@@ -229,7 +231,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) | |||
229 | 231 | ||
230 | if (!priv->quiet) { | 232 | if (!priv->quiet) { |
231 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", | 233 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", |
232 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 234 | addr, i2cbus->adapter.name, dvo->slave_addr); |
233 | } | 235 | } |
234 | 236 | ||
235 | return false; | 237 | return false; |
@@ -237,7 +239,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) | |||
237 | 239 | ||
238 | /** Probes the given bus and slave address for an ivch */ | 240 | /** Probes the given bus and slave address for an ivch */ |
239 | static bool ivch_init(struct intel_dvo_device *dvo, | 241 | static bool ivch_init(struct intel_dvo_device *dvo, |
240 | struct intel_i2c_chan *i2cbus) | 242 | struct i2c_adapter *adapter) |
241 | { | 243 | { |
242 | struct ivch_priv *priv; | 244 | struct ivch_priv *priv; |
243 | uint16_t temp; | 245 | uint16_t temp; |
@@ -246,8 +248,7 @@ static bool ivch_init(struct intel_dvo_device *dvo, | |||
246 | if (priv == NULL) | 248 | if (priv == NULL) |
247 | return false; | 249 | return false; |
248 | 250 | ||
249 | dvo->i2c_bus = i2cbus; | 251 | dvo->i2c_bus = adapter; |
250 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
251 | dvo->dev_priv = priv; | 252 | dvo->dev_priv = priv; |
252 | priv->quiet = true; | 253 | priv->quiet = true; |
253 | 254 | ||
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c index 033a4bb070b2..e1c1f7341e5c 100644 --- a/drivers/gpu/drm/i915/dvo_sil164.c +++ b/drivers/gpu/drm/i915/dvo_sil164.c | |||
@@ -76,19 +76,20 @@ struct sil164_priv { | |||
76 | static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | 76 | static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) |
77 | { | 77 | { |
78 | struct sil164_priv *sil = dvo->dev_priv; | 78 | struct sil164_priv *sil = dvo->dev_priv; |
79 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 79 | struct i2c_adapter *adapter = dvo->i2c_bus; |
80 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
80 | u8 out_buf[2]; | 81 | u8 out_buf[2]; |
81 | u8 in_buf[2]; | 82 | u8 in_buf[2]; |
82 | 83 | ||
83 | struct i2c_msg msgs[] = { | 84 | struct i2c_msg msgs[] = { |
84 | { | 85 | { |
85 | .addr = i2cbus->slave_addr, | 86 | .addr = dvo->slave_addr, |
86 | .flags = 0, | 87 | .flags = 0, |
87 | .len = 1, | 88 | .len = 1, |
88 | .buf = out_buf, | 89 | .buf = out_buf, |
89 | }, | 90 | }, |
90 | { | 91 | { |
91 | .addr = i2cbus->slave_addr, | 92 | .addr = dvo->slave_addr, |
92 | .flags = I2C_M_RD, | 93 | .flags = I2C_M_RD, |
93 | .len = 1, | 94 | .len = 1, |
94 | .buf = in_buf, | 95 | .buf = in_buf, |
@@ -105,7 +106,7 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
105 | 106 | ||
106 | if (!sil->quiet) { | 107 | if (!sil->quiet) { |
107 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", | 108 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", |
108 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 109 | addr, i2cbus->adapter.name, dvo->slave_addr); |
109 | } | 110 | } |
110 | return false; | 111 | return false; |
111 | } | 112 | } |
@@ -113,10 +114,11 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
113 | static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | 114 | static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) |
114 | { | 115 | { |
115 | struct sil164_priv *sil= dvo->dev_priv; | 116 | struct sil164_priv *sil= dvo->dev_priv; |
116 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 117 | struct i2c_adapter *adapter = dvo->i2c_bus; |
118 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
117 | uint8_t out_buf[2]; | 119 | uint8_t out_buf[2]; |
118 | struct i2c_msg msg = { | 120 | struct i2c_msg msg = { |
119 | .addr = i2cbus->slave_addr, | 121 | .addr = dvo->slave_addr, |
120 | .flags = 0, | 122 | .flags = 0, |
121 | .len = 2, | 123 | .len = 2, |
122 | .buf = out_buf, | 124 | .buf = out_buf, |
@@ -130,7 +132,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
130 | 132 | ||
131 | if (!sil->quiet) { | 133 | if (!sil->quiet) { |
132 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", | 134 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", |
133 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 135 | addr, i2cbus->adapter.name, dvo->slave_addr); |
134 | } | 136 | } |
135 | 137 | ||
136 | return false; | 138 | return false; |
@@ -138,7 +140,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
138 | 140 | ||
139 | /* Silicon Image 164 driver for chip on i2c bus */ | 141 | /* Silicon Image 164 driver for chip on i2c bus */ |
140 | static bool sil164_init(struct intel_dvo_device *dvo, | 142 | static bool sil164_init(struct intel_dvo_device *dvo, |
141 | struct intel_i2c_chan *i2cbus) | 143 | struct i2c_adapter *adapter) |
142 | { | 144 | { |
143 | /* this will detect the SIL164 chip on the specified i2c bus */ | 145 | /* this will detect the SIL164 chip on the specified i2c bus */ |
144 | struct sil164_priv *sil; | 146 | struct sil164_priv *sil; |
@@ -148,8 +150,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, | |||
148 | if (sil == NULL) | 150 | if (sil == NULL) |
149 | return false; | 151 | return false; |
150 | 152 | ||
151 | dvo->i2c_bus = i2cbus; | 153 | dvo->i2c_bus = adapter; |
152 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
153 | dvo->dev_priv = sil; | 154 | dvo->dev_priv = sil; |
154 | sil->quiet = true; | 155 | sil->quiet = true; |
155 | 156 | ||
@@ -158,7 +159,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, | |||
158 | 159 | ||
159 | if (ch != (SIL164_VID & 0xff)) { | 160 | if (ch != (SIL164_VID & 0xff)) { |
160 | DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", | 161 | DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", |
161 | ch, i2cbus->adapter.name, i2cbus->slave_addr); | 162 | ch, adapter->name, dvo->slave_addr); |
162 | goto out; | 163 | goto out; |
163 | } | 164 | } |
164 | 165 | ||
@@ -167,7 +168,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, | |||
167 | 168 | ||
168 | if (ch != (SIL164_DID & 0xff)) { | 169 | if (ch != (SIL164_DID & 0xff)) { |
169 | DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", | 170 | DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", |
170 | ch, i2cbus->adapter.name, i2cbus->slave_addr); | 171 | ch, adapter->name, dvo->slave_addr); |
171 | goto out; | 172 | goto out; |
172 | } | 173 | } |
173 | sil->quiet = false; | 174 | sil->quiet = false; |
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c index 207fda806ebf..9ecc907384ec 100644 --- a/drivers/gpu/drm/i915/dvo_tfp410.c +++ b/drivers/gpu/drm/i915/dvo_tfp410.c | |||
@@ -101,19 +101,20 @@ struct tfp410_priv { | |||
101 | static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | 101 | static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) |
102 | { | 102 | { |
103 | struct tfp410_priv *tfp = dvo->dev_priv; | 103 | struct tfp410_priv *tfp = dvo->dev_priv; |
104 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 104 | struct i2c_adapter *adapter = dvo->i2c_bus; |
105 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
105 | u8 out_buf[2]; | 106 | u8 out_buf[2]; |
106 | u8 in_buf[2]; | 107 | u8 in_buf[2]; |
107 | 108 | ||
108 | struct i2c_msg msgs[] = { | 109 | struct i2c_msg msgs[] = { |
109 | { | 110 | { |
110 | .addr = i2cbus->slave_addr, | 111 | .addr = dvo->slave_addr, |
111 | .flags = 0, | 112 | .flags = 0, |
112 | .len = 1, | 113 | .len = 1, |
113 | .buf = out_buf, | 114 | .buf = out_buf, |
114 | }, | 115 | }, |
115 | { | 116 | { |
116 | .addr = i2cbus->slave_addr, | 117 | .addr = dvo->slave_addr, |
117 | .flags = I2C_M_RD, | 118 | .flags = I2C_M_RD, |
118 | .len = 1, | 119 | .len = 1, |
119 | .buf = in_buf, | 120 | .buf = in_buf, |
@@ -130,7 +131,7 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
130 | 131 | ||
131 | if (!tfp->quiet) { | 132 | if (!tfp->quiet) { |
132 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", | 133 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", |
133 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 134 | addr, i2cbus->adapter.name, dvo->slave_addr); |
134 | } | 135 | } |
135 | return false; | 136 | return false; |
136 | } | 137 | } |
@@ -138,10 +139,11 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
138 | static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | 139 | static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) |
139 | { | 140 | { |
140 | struct tfp410_priv *tfp = dvo->dev_priv; | 141 | struct tfp410_priv *tfp = dvo->dev_priv; |
141 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 142 | struct i2c_adapter *adapter = dvo->i2c_bus; |
143 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
142 | uint8_t out_buf[2]; | 144 | uint8_t out_buf[2]; |
143 | struct i2c_msg msg = { | 145 | struct i2c_msg msg = { |
144 | .addr = i2cbus->slave_addr, | 146 | .addr = dvo->slave_addr, |
145 | .flags = 0, | 147 | .flags = 0, |
146 | .len = 2, | 148 | .len = 2, |
147 | .buf = out_buf, | 149 | .buf = out_buf, |
@@ -155,7 +157,7 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
155 | 157 | ||
156 | if (!tfp->quiet) { | 158 | if (!tfp->quiet) { |
157 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", | 159 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", |
158 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 160 | addr, i2cbus->adapter.name, dvo->slave_addr); |
159 | } | 161 | } |
160 | 162 | ||
161 | return false; | 163 | return false; |
@@ -174,7 +176,7 @@ static int tfp410_getid(struct intel_dvo_device *dvo, int addr) | |||
174 | 176 | ||
175 | /* Ti TFP410 driver for chip on i2c bus */ | 177 | /* Ti TFP410 driver for chip on i2c bus */ |
176 | static bool tfp410_init(struct intel_dvo_device *dvo, | 178 | static bool tfp410_init(struct intel_dvo_device *dvo, |
177 | struct intel_i2c_chan *i2cbus) | 179 | struct i2c_adapter *adapter) |
178 | { | 180 | { |
179 | /* this will detect the tfp410 chip on the specified i2c bus */ | 181 | /* this will detect the tfp410 chip on the specified i2c bus */ |
180 | struct tfp410_priv *tfp; | 182 | struct tfp410_priv *tfp; |
@@ -184,20 +186,19 @@ static bool tfp410_init(struct intel_dvo_device *dvo, | |||
184 | if (tfp == NULL) | 186 | if (tfp == NULL) |
185 | return false; | 187 | return false; |
186 | 188 | ||
187 | dvo->i2c_bus = i2cbus; | 189 | dvo->i2c_bus = adapter; |
188 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
189 | dvo->dev_priv = tfp; | 190 | dvo->dev_priv = tfp; |
190 | tfp->quiet = true; | 191 | tfp->quiet = true; |
191 | 192 | ||
192 | if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) { | 193 | if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) { |
193 | DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n", | 194 | DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n", |
194 | id, i2cbus->adapter.name, i2cbus->slave_addr); | 195 | id, adapter->name, dvo->slave_addr); |
195 | goto out; | 196 | goto out; |
196 | } | 197 | } |
197 | 198 | ||
198 | if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) { | 199 | if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) { |
199 | DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n", | 200 | DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n", |
200 | id, i2cbus->adapter.name, i2cbus->slave_addr); | 201 | id, adapter->name, dvo->slave_addr); |
201 | goto out; | 202 | goto out; |
202 | } | 203 | } |
203 | tfp->quiet = false; | 204 | tfp->quiet = false; |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 98560e1e899a..e3cb4025e323 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -67,8 +67,6 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
67 | 67 | ||
68 | pci_save_state(dev->pdev); | 68 | pci_save_state(dev->pdev); |
69 | 69 | ||
70 | i915_save_state(dev); | ||
71 | |||
72 | /* If KMS is active, we do the leavevt stuff here */ | 70 | /* If KMS is active, we do the leavevt stuff here */ |
73 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 71 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
74 | if (i915_gem_idle(dev)) | 72 | if (i915_gem_idle(dev)) |
@@ -77,6 +75,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
77 | drm_irq_uninstall(dev); | 75 | drm_irq_uninstall(dev); |
78 | } | 76 | } |
79 | 77 | ||
78 | i915_save_state(dev); | ||
79 | |||
80 | intel_opregion_free(dev, 1); | 80 | intel_opregion_free(dev, 1); |
81 | 81 | ||
82 | if (state.event == PM_EVENT_SUSPEND) { | 82 | if (state.event == PM_EVENT_SUSPEND) { |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7a84f04e8439..bb4c2d387b6c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -306,6 +306,17 @@ typedef struct drm_i915_private { | |||
306 | u32 saveCURBPOS; | 306 | u32 saveCURBPOS; |
307 | u32 saveCURBBASE; | 307 | u32 saveCURBBASE; |
308 | u32 saveCURSIZE; | 308 | u32 saveCURSIZE; |
309 | u32 saveDP_B; | ||
310 | u32 saveDP_C; | ||
311 | u32 saveDP_D; | ||
312 | u32 savePIPEA_GMCH_DATA_M; | ||
313 | u32 savePIPEB_GMCH_DATA_M; | ||
314 | u32 savePIPEA_GMCH_DATA_N; | ||
315 | u32 savePIPEB_GMCH_DATA_N; | ||
316 | u32 savePIPEA_DP_LINK_M; | ||
317 | u32 savePIPEB_DP_LINK_M; | ||
318 | u32 savePIPEA_DP_LINK_N; | ||
319 | u32 savePIPEB_DP_LINK_N; | ||
309 | 320 | ||
310 | struct { | 321 | struct { |
311 | struct drm_mm gtt_space; | 322 | struct drm_mm gtt_space; |
@@ -857,6 +868,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); | |||
857 | #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ | 868 | #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ |
858 | IS_I915GM(dev))) | 869 | IS_I915GM(dev))) |
859 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) | 870 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) |
871 | #define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev)) | ||
860 | #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) | 872 | #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) |
861 | 873 | ||
862 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) | 874 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fd2b8bdffe3f..876b65cb7629 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1006,7 +1006,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
1006 | 1006 | ||
1007 | mutex_lock(&dev->struct_mutex); | 1007 | mutex_lock(&dev->struct_mutex); |
1008 | #if WATCH_BUF | 1008 | #if WATCH_BUF |
1009 | DRM_INFO("set_domain_ioctl %p(%d), %08x %08x\n", | 1009 | DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n", |
1010 | obj, obj->size, read_domains, write_domain); | 1010 | obj, obj->size, read_domains, write_domain); |
1011 | #endif | 1011 | #endif |
1012 | if (read_domains & I915_GEM_DOMAIN_GTT) { | 1012 | if (read_domains & I915_GEM_DOMAIN_GTT) { |
@@ -1050,7 +1050,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, | |||
1050 | } | 1050 | } |
1051 | 1051 | ||
1052 | #if WATCH_BUF | 1052 | #if WATCH_BUF |
1053 | DRM_INFO("%s: sw_finish %d (%p %d)\n", | 1053 | DRM_INFO("%s: sw_finish %d (%p %zd)\n", |
1054 | __func__, args->handle, obj, obj->size); | 1054 | __func__, args->handle, obj, obj->size); |
1055 | #endif | 1055 | #endif |
1056 | obj_priv = obj->driver_private; | 1056 | obj_priv = obj->driver_private; |
@@ -2423,7 +2423,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2423 | } | 2423 | } |
2424 | 2424 | ||
2425 | #if WATCH_BUF | 2425 | #if WATCH_BUF |
2426 | DRM_INFO("Binding object of size %d at 0x%08x\n", | 2426 | DRM_INFO("Binding object of size %zd at 0x%08x\n", |
2427 | obj->size, obj_priv->gtt_offset); | 2427 | obj->size, obj_priv->gtt_offset); |
2428 | #endif | 2428 | #endif |
2429 | ret = i915_gem_object_get_pages(obj); | 2429 | ret = i915_gem_object_get_pages(obj); |
@@ -4227,6 +4227,7 @@ i915_gem_lastclose(struct drm_device *dev) | |||
4227 | void | 4227 | void |
4228 | i915_gem_load(struct drm_device *dev) | 4228 | i915_gem_load(struct drm_device *dev) |
4229 | { | 4229 | { |
4230 | int i; | ||
4230 | drm_i915_private_t *dev_priv = dev->dev_private; | 4231 | drm_i915_private_t *dev_priv = dev->dev_private; |
4231 | 4232 | ||
4232 | spin_lock_init(&dev_priv->mm.active_list_lock); | 4233 | spin_lock_init(&dev_priv->mm.active_list_lock); |
@@ -4246,6 +4247,18 @@ i915_gem_load(struct drm_device *dev) | |||
4246 | else | 4247 | else |
4247 | dev_priv->num_fence_regs = 8; | 4248 | dev_priv->num_fence_regs = 8; |
4248 | 4249 | ||
4250 | /* Initialize fence registers to zero */ | ||
4251 | if (IS_I965G(dev)) { | ||
4252 | for (i = 0; i < 16; i++) | ||
4253 | I915_WRITE64(FENCE_REG_965_0 + (i * 8), 0); | ||
4254 | } else { | ||
4255 | for (i = 0; i < 8; i++) | ||
4256 | I915_WRITE(FENCE_REG_830_0 + (i * 4), 0); | ||
4257 | if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) | ||
4258 | for (i = 0; i < 8; i++) | ||
4259 | I915_WRITE(FENCE_REG_945_8 + (i * 4), 0); | ||
4260 | } | ||
4261 | |||
4249 | i915_gem_detect_bit_6_swizzle(dev); | 4262 | i915_gem_detect_bit_6_swizzle(dev); |
4250 | } | 4263 | } |
4251 | 4264 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index 8d0b943e2c5a..e602614bd3f8 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c | |||
@@ -87,7 +87,7 @@ i915_gem_dump_object(struct drm_gem_object *obj, int len, | |||
87 | chunk_len = page_len - chunk; | 87 | chunk_len = page_len - chunk; |
88 | if (chunk_len > 128) | 88 | if (chunk_len > 128) |
89 | chunk_len = 128; | 89 | chunk_len = 128; |
90 | i915_gem_dump_page(obj_priv->page_list[page], | 90 | i915_gem_dump_page(obj_priv->pages[page], |
91 | chunk, chunk + chunk_len, | 91 | chunk, chunk + chunk_len, |
92 | obj_priv->gtt_offset + | 92 | obj_priv->gtt_offset + |
93 | page * PAGE_SIZE, | 93 | page * PAGE_SIZE, |
@@ -143,7 +143,7 @@ i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle) | |||
143 | uint32_t *backing_map = NULL; | 143 | uint32_t *backing_map = NULL; |
144 | int bad_count = 0; | 144 | int bad_count = 0; |
145 | 145 | ||
146 | DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %dkb):\n", | 146 | DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %zdkb):\n", |
147 | __func__, obj, obj_priv->gtt_offset, handle, | 147 | __func__, obj, obj_priv->gtt_offset, handle, |
148 | obj->size / 1024); | 148 | obj->size / 1024); |
149 | 149 | ||
@@ -157,7 +157,7 @@ i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle) | |||
157 | for (page = 0; page < obj->size / PAGE_SIZE; page++) { | 157 | for (page = 0; page < obj->size / PAGE_SIZE; page++) { |
158 | int i; | 158 | int i; |
159 | 159 | ||
160 | backing_map = kmap_atomic(obj_priv->page_list[page], KM_USER0); | 160 | backing_map = kmap_atomic(obj_priv->pages[page], KM_USER0); |
161 | 161 | ||
162 | if (backing_map == NULL) { | 162 | if (backing_map == NULL) { |
163 | DRM_ERROR("failed to map backing page\n"); | 163 | DRM_ERROR("failed to map backing page\n"); |
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 5c1ceec49f5b..daeae62e1c28 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
@@ -114,11 +114,13 @@ intel_alloc_mchbar_resource(struct drm_device *dev) | |||
114 | mchbar_addr = ((u64)temp_hi << 32) | temp_lo; | 114 | mchbar_addr = ((u64)temp_hi << 32) | temp_lo; |
115 | 115 | ||
116 | /* If ACPI doesn't have it, assume we need to allocate it ourselves */ | 116 | /* If ACPI doesn't have it, assume we need to allocate it ourselves */ |
117 | #ifdef CONFIG_PNP | ||
117 | if (mchbar_addr && | 118 | if (mchbar_addr && |
118 | pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) { | 119 | pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) { |
119 | ret = 0; | 120 | ret = 0; |
120 | goto out_put; | 121 | goto out_put; |
121 | } | 122 | } |
123 | #endif | ||
122 | 124 | ||
123 | /* Get some space for it */ | 125 | /* Get some space for it */ |
124 | ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res, | 126 | ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res, |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b86b7b7130c6..228546f6eaa4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -232,7 +232,17 @@ static void i915_hotplug_work_func(struct work_struct *work) | |||
232 | drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, | 232 | drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, |
233 | hotplug_work); | 233 | hotplug_work); |
234 | struct drm_device *dev = dev_priv->dev; | 234 | struct drm_device *dev = dev_priv->dev; |
235 | 235 | struct drm_mode_config *mode_config = &dev->mode_config; | |
236 | struct drm_connector *connector; | ||
237 | |||
238 | if (mode_config->num_connector) { | ||
239 | list_for_each_entry(connector, &mode_config->connector_list, head) { | ||
240 | struct intel_output *intel_output = to_intel_output(connector); | ||
241 | |||
242 | if (intel_output->hot_plug) | ||
243 | (*intel_output->hot_plug) (intel_output); | ||
244 | } | ||
245 | } | ||
236 | /* Just fire off a uevent and let userspace tell us what to do */ | 246 | /* Just fire off a uevent and let userspace tell us what to do */ |
237 | drm_sysfs_hotplug_event(dev); | 247 | drm_sysfs_hotplug_event(dev); |
238 | } | 248 | } |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f6237a0b1133..88bf7521405f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -569,6 +569,19 @@ | |||
569 | #define C0DRB3 0x10206 | 569 | #define C0DRB3 0x10206 |
570 | #define C1DRB3 0x10606 | 570 | #define C1DRB3 0x10606 |
571 | 571 | ||
572 | /* Clocking configuration register */ | ||
573 | #define CLKCFG 0x10c00 | ||
574 | #define CLKCFG_FSB_400 (0 << 0) /* hrawclk 100 */ | ||
575 | #define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */ | ||
576 | #define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */ | ||
577 | #define CLKCFG_FSB_800 (2 << 0) /* hrawclk 200 */ | ||
578 | #define CLKCFG_FSB_1067 (6 << 0) /* hrawclk 266 */ | ||
579 | #define CLKCFG_FSB_1333 (7 << 0) /* hrawclk 333 */ | ||
580 | /* this is a guess, could be 5 as well */ | ||
581 | #define CLKCFG_FSB_1600 (4 << 0) /* hrawclk 400 */ | ||
582 | #define CLKCFG_FSB_1600_ALT (5 << 0) /* hrawclk 400 */ | ||
583 | #define CLKCFG_FSB_MASK (7 << 0) | ||
584 | |||
572 | /** GM965 GM45 render standby register */ | 585 | /** GM965 GM45 render standby register */ |
573 | #define MCHBAR_RENDER_STANDBY 0x111B8 | 586 | #define MCHBAR_RENDER_STANDBY 0x111B8 |
574 | 587 | ||
@@ -834,9 +847,25 @@ | |||
834 | #define HORIZ_INTERP_MASK (3 << 6) | 847 | #define HORIZ_INTERP_MASK (3 << 6) |
835 | #define HORIZ_AUTO_SCALE (1 << 5) | 848 | #define HORIZ_AUTO_SCALE (1 << 5) |
836 | #define PANEL_8TO6_DITHER_ENABLE (1 << 3) | 849 | #define PANEL_8TO6_DITHER_ENABLE (1 << 3) |
850 | #define PFIT_FILTER_FUZZY (0 << 24) | ||
851 | #define PFIT_SCALING_AUTO (0 << 26) | ||
852 | #define PFIT_SCALING_PROGRAMMED (1 << 26) | ||
853 | #define PFIT_SCALING_PILLAR (2 << 26) | ||
854 | #define PFIT_SCALING_LETTER (3 << 26) | ||
837 | #define PFIT_PGM_RATIOS 0x61234 | 855 | #define PFIT_PGM_RATIOS 0x61234 |
838 | #define PFIT_VERT_SCALE_MASK 0xfff00000 | 856 | #define PFIT_VERT_SCALE_MASK 0xfff00000 |
839 | #define PFIT_HORIZ_SCALE_MASK 0x0000fff0 | 857 | #define PFIT_HORIZ_SCALE_MASK 0x0000fff0 |
858 | /* Pre-965 */ | ||
859 | #define PFIT_VERT_SCALE_SHIFT 20 | ||
860 | #define PFIT_VERT_SCALE_MASK 0xfff00000 | ||
861 | #define PFIT_HORIZ_SCALE_SHIFT 4 | ||
862 | #define PFIT_HORIZ_SCALE_MASK 0x0000fff0 | ||
863 | /* 965+ */ | ||
864 | #define PFIT_VERT_SCALE_SHIFT_965 16 | ||
865 | #define PFIT_VERT_SCALE_MASK_965 0x1fff0000 | ||
866 | #define PFIT_HORIZ_SCALE_SHIFT_965 0 | ||
867 | #define PFIT_HORIZ_SCALE_MASK_965 0x00001fff | ||
868 | |||
840 | #define PFIT_AUTO_RATIOS 0x61238 | 869 | #define PFIT_AUTO_RATIOS 0x61238 |
841 | 870 | ||
842 | /* Backlight control */ | 871 | /* Backlight control */ |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index a98e2831ed31..8d8e083d14ab 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
@@ -322,6 +322,20 @@ int i915_save_state(struct drm_device *dev) | |||
322 | dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); | 322 | dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); |
323 | dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); | 323 | dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); |
324 | 324 | ||
325 | /* Display Port state */ | ||
326 | if (SUPPORTS_INTEGRATED_DP(dev)) { | ||
327 | dev_priv->saveDP_B = I915_READ(DP_B); | ||
328 | dev_priv->saveDP_C = I915_READ(DP_C); | ||
329 | dev_priv->saveDP_D = I915_READ(DP_D); | ||
330 | dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(PIPEA_GMCH_DATA_M); | ||
331 | dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(PIPEB_GMCH_DATA_M); | ||
332 | dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(PIPEA_GMCH_DATA_N); | ||
333 | dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(PIPEB_GMCH_DATA_N); | ||
334 | dev_priv->savePIPEA_DP_LINK_M = I915_READ(PIPEA_DP_LINK_M); | ||
335 | dev_priv->savePIPEB_DP_LINK_M = I915_READ(PIPEB_DP_LINK_M); | ||
336 | dev_priv->savePIPEA_DP_LINK_N = I915_READ(PIPEA_DP_LINK_N); | ||
337 | dev_priv->savePIPEB_DP_LINK_N = I915_READ(PIPEB_DP_LINK_N); | ||
338 | } | ||
325 | /* FIXME: save TV & SDVO state */ | 339 | /* FIXME: save TV & SDVO state */ |
326 | 340 | ||
327 | /* FBC state */ | 341 | /* FBC state */ |
@@ -404,7 +418,19 @@ int i915_restore_state(struct drm_device *dev) | |||
404 | for (i = 0; i < 8; i++) | 418 | for (i = 0; i < 8; i++) |
405 | I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]); | 419 | I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]); |
406 | } | 420 | } |
407 | 421 | ||
422 | /* Display port ratios (must be done before clock is set) */ | ||
423 | if (SUPPORTS_INTEGRATED_DP(dev)) { | ||
424 | I915_WRITE(PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M); | ||
425 | I915_WRITE(PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M); | ||
426 | I915_WRITE(PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N); | ||
427 | I915_WRITE(PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N); | ||
428 | I915_WRITE(PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M); | ||
429 | I915_WRITE(PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M); | ||
430 | I915_WRITE(PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N); | ||
431 | I915_WRITE(PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N); | ||
432 | } | ||
433 | |||
408 | /* Pipe & plane A info */ | 434 | /* Pipe & plane A info */ |
409 | /* Prime the clock */ | 435 | /* Prime the clock */ |
410 | if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { | 436 | if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { |
@@ -518,6 +544,12 @@ int i915_restore_state(struct drm_device *dev) | |||
518 | I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); | 544 | I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); |
519 | I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); | 545 | I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); |
520 | 546 | ||
547 | /* Display Port state */ | ||
548 | if (SUPPORTS_INTEGRATED_DP(dev)) { | ||
549 | I915_WRITE(DP_B, dev_priv->saveDP_B); | ||
550 | I915_WRITE(DP_C, dev_priv->saveDP_C); | ||
551 | I915_WRITE(DP_D, dev_priv->saveDP_D); | ||
552 | } | ||
521 | /* FIXME: restore TV & SDVO state */ | 553 | /* FIXME: restore TV & SDVO state */ |
522 | 554 | ||
523 | /* FBC info */ | 555 | /* FBC info */ |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index cdd126d068a7..716409a57244 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -99,9 +99,11 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
99 | { | 99 | { |
100 | struct bdb_lvds_options *lvds_options; | 100 | struct bdb_lvds_options *lvds_options; |
101 | struct bdb_lvds_lfp_data *lvds_lfp_data; | 101 | struct bdb_lvds_lfp_data *lvds_lfp_data; |
102 | struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; | ||
102 | struct bdb_lvds_lfp_data_entry *entry; | 103 | struct bdb_lvds_lfp_data_entry *entry; |
103 | struct lvds_dvo_timing *dvo_timing; | 104 | struct lvds_dvo_timing *dvo_timing; |
104 | struct drm_display_mode *panel_fixed_mode; | 105 | struct drm_display_mode *panel_fixed_mode; |
106 | int lfp_data_size; | ||
105 | 107 | ||
106 | /* Defaults if we can't find VBT info */ | 108 | /* Defaults if we can't find VBT info */ |
107 | dev_priv->lvds_dither = 0; | 109 | dev_priv->lvds_dither = 0; |
@@ -119,9 +121,17 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
119 | if (!lvds_lfp_data) | 121 | if (!lvds_lfp_data) |
120 | return; | 122 | return; |
121 | 123 | ||
124 | lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS); | ||
125 | if (!lvds_lfp_data_ptrs) | ||
126 | return; | ||
127 | |||
122 | dev_priv->lvds_vbt = 1; | 128 | dev_priv->lvds_vbt = 1; |
123 | 129 | ||
124 | entry = &lvds_lfp_data->data[lvds_options->panel_type]; | 130 | lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset - |
131 | lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset; | ||
132 | entry = (struct bdb_lvds_lfp_data_entry *) | ||
133 | ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * | ||
134 | lvds_options->panel_type)); | ||
125 | dvo_timing = &entry->dvo_timing; | 135 | dvo_timing = &entry->dvo_timing; |
126 | 136 | ||
127 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); | 137 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3e1c78162119..73e7b9cecac8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "intel_drv.h" | 29 | #include "intel_drv.h" |
30 | #include "i915_drm.h" | 30 | #include "i915_drm.h" |
31 | #include "i915_drv.h" | 31 | #include "i915_drv.h" |
32 | #include "intel_dp.h" | ||
32 | 33 | ||
33 | #include "drm_crtc_helper.h" | 34 | #include "drm_crtc_helper.h" |
34 | 35 | ||
@@ -127,19 +128,6 @@ struct intel_limit { | |||
127 | #define I9XX_P2_LVDS_FAST 7 | 128 | #define I9XX_P2_LVDS_FAST 7 |
128 | #define I9XX_P2_LVDS_SLOW_LIMIT 112000 | 129 | #define I9XX_P2_LVDS_SLOW_LIMIT 112000 |
129 | 130 | ||
130 | #define INTEL_LIMIT_I8XX_DVO_DAC 0 | ||
131 | #define INTEL_LIMIT_I8XX_LVDS 1 | ||
132 | #define INTEL_LIMIT_I9XX_SDVO_DAC 2 | ||
133 | #define INTEL_LIMIT_I9XX_LVDS 3 | ||
134 | #define INTEL_LIMIT_G4X_SDVO 4 | ||
135 | #define INTEL_LIMIT_G4X_HDMI_DAC 5 | ||
136 | #define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS 6 | ||
137 | #define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7 | ||
138 | #define INTEL_LIMIT_IGD_SDVO_DAC 8 | ||
139 | #define INTEL_LIMIT_IGD_LVDS 9 | ||
140 | #define INTEL_LIMIT_IGDNG_SDVO_DAC 10 | ||
141 | #define INTEL_LIMIT_IGDNG_LVDS 11 | ||
142 | |||
143 | /*The parameter is for SDVO on G4x platform*/ | 131 | /*The parameter is for SDVO on G4x platform*/ |
144 | #define G4X_DOT_SDVO_MIN 25000 | 132 | #define G4X_DOT_SDVO_MIN 25000 |
145 | #define G4X_DOT_SDVO_MAX 270000 | 133 | #define G4X_DOT_SDVO_MAX 270000 |
@@ -218,6 +206,25 @@ struct intel_limit { | |||
218 | #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 | 206 | #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 |
219 | #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 | 207 | #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 |
220 | 208 | ||
209 | /*The parameter is for DISPLAY PORT on G4x platform*/ | ||
210 | #define G4X_DOT_DISPLAY_PORT_MIN 161670 | ||
211 | #define G4X_DOT_DISPLAY_PORT_MAX 227000 | ||
212 | #define G4X_N_DISPLAY_PORT_MIN 1 | ||
213 | #define G4X_N_DISPLAY_PORT_MAX 2 | ||
214 | #define G4X_M_DISPLAY_PORT_MIN 97 | ||
215 | #define G4X_M_DISPLAY_PORT_MAX 108 | ||
216 | #define G4X_M1_DISPLAY_PORT_MIN 0x10 | ||
217 | #define G4X_M1_DISPLAY_PORT_MAX 0x12 | ||
218 | #define G4X_M2_DISPLAY_PORT_MIN 0x05 | ||
219 | #define G4X_M2_DISPLAY_PORT_MAX 0x06 | ||
220 | #define G4X_P_DISPLAY_PORT_MIN 10 | ||
221 | #define G4X_P_DISPLAY_PORT_MAX 20 | ||
222 | #define G4X_P1_DISPLAY_PORT_MIN 1 | ||
223 | #define G4X_P1_DISPLAY_PORT_MAX 2 | ||
224 | #define G4X_P2_DISPLAY_PORT_SLOW 10 | ||
225 | #define G4X_P2_DISPLAY_PORT_FAST 10 | ||
226 | #define G4X_P2_DISPLAY_PORT_LIMIT 0 | ||
227 | |||
221 | /* IGDNG */ | 228 | /* IGDNG */ |
222 | /* as we calculate clock using (register_value + 2) for | 229 | /* as we calculate clock using (register_value + 2) for |
223 | N/M1/M2, so here the range value for them is (actual_value-2). | 230 | N/M1/M2, so here the range value for them is (actual_value-2). |
@@ -256,8 +263,11 @@ static bool | |||
256 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 263 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
257 | int target, int refclk, intel_clock_t *best_clock); | 264 | int target, int refclk, intel_clock_t *best_clock); |
258 | 265 | ||
259 | static const intel_limit_t intel_limits[] = { | 266 | static bool |
260 | { /* INTEL_LIMIT_I8XX_DVO_DAC */ | 267 | intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, |
268 | int target, int refclk, intel_clock_t *best_clock); | ||
269 | |||
270 | static const intel_limit_t intel_limits_i8xx_dvo = { | ||
261 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | 271 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, |
262 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, | 272 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, |
263 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, | 273 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, |
@@ -269,8 +279,9 @@ static const intel_limit_t intel_limits[] = { | |||
269 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 279 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
270 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, | 280 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, |
271 | .find_pll = intel_find_best_PLL, | 281 | .find_pll = intel_find_best_PLL, |
272 | }, | 282 | }; |
273 | { /* INTEL_LIMIT_I8XX_LVDS */ | 283 | |
284 | static const intel_limit_t intel_limits_i8xx_lvds = { | ||
274 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | 285 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, |
275 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, | 286 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, |
276 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, | 287 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, |
@@ -282,8 +293,9 @@ static const intel_limit_t intel_limits[] = { | |||
282 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 293 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
283 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, | 294 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, |
284 | .find_pll = intel_find_best_PLL, | 295 | .find_pll = intel_find_best_PLL, |
285 | }, | 296 | }; |
286 | { /* INTEL_LIMIT_I9XX_SDVO_DAC */ | 297 | |
298 | static const intel_limit_t intel_limits_i9xx_sdvo = { | ||
287 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 299 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
288 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, | 300 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, |
289 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, | 301 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, |
@@ -295,8 +307,9 @@ static const intel_limit_t intel_limits[] = { | |||
295 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 307 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
296 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 308 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
297 | .find_pll = intel_find_best_PLL, | 309 | .find_pll = intel_find_best_PLL, |
298 | }, | 310 | }; |
299 | { /* INTEL_LIMIT_I9XX_LVDS */ | 311 | |
312 | static const intel_limit_t intel_limits_i9xx_lvds = { | ||
300 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 313 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
301 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, | 314 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, |
302 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, | 315 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, |
@@ -311,9 +324,10 @@ static const intel_limit_t intel_limits[] = { | |||
311 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 324 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
312 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, | 325 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, |
313 | .find_pll = intel_find_best_PLL, | 326 | .find_pll = intel_find_best_PLL, |
314 | }, | 327 | }; |
328 | |||
315 | /* below parameter and function is for G4X Chipset Family*/ | 329 | /* below parameter and function is for G4X Chipset Family*/ |
316 | { /* INTEL_LIMIT_G4X_SDVO */ | 330 | static const intel_limit_t intel_limits_g4x_sdvo = { |
317 | .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX }, | 331 | .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX }, |
318 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, | 332 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, |
319 | .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX }, | 333 | .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX }, |
@@ -327,8 +341,9 @@ static const intel_limit_t intel_limits[] = { | |||
327 | .p2_fast = G4X_P2_SDVO_FAST | 341 | .p2_fast = G4X_P2_SDVO_FAST |
328 | }, | 342 | }, |
329 | .find_pll = intel_g4x_find_best_PLL, | 343 | .find_pll = intel_g4x_find_best_PLL, |
330 | }, | 344 | }; |
331 | { /* INTEL_LIMIT_G4X_HDMI_DAC */ | 345 | |
346 | static const intel_limit_t intel_limits_g4x_hdmi = { | ||
332 | .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, | 347 | .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, |
333 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, | 348 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, |
334 | .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX }, | 349 | .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX }, |
@@ -342,8 +357,9 @@ static const intel_limit_t intel_limits[] = { | |||
342 | .p2_fast = G4X_P2_HDMI_DAC_FAST | 357 | .p2_fast = G4X_P2_HDMI_DAC_FAST |
343 | }, | 358 | }, |
344 | .find_pll = intel_g4x_find_best_PLL, | 359 | .find_pll = intel_g4x_find_best_PLL, |
345 | }, | 360 | }; |
346 | { /* INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS */ | 361 | |
362 | static const intel_limit_t intel_limits_g4x_single_channel_lvds = { | ||
347 | .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, | 363 | .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, |
348 | .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX }, | 364 | .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX }, |
349 | .vco = { .min = G4X_VCO_MIN, | 365 | .vco = { .min = G4X_VCO_MIN, |
@@ -365,8 +381,9 @@ static const intel_limit_t intel_limits[] = { | |||
365 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST | 381 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST |
366 | }, | 382 | }, |
367 | .find_pll = intel_g4x_find_best_PLL, | 383 | .find_pll = intel_g4x_find_best_PLL, |
368 | }, | 384 | }; |
369 | { /* INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS */ | 385 | |
386 | static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { | ||
370 | .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, | 387 | .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, |
371 | .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX }, | 388 | .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX }, |
372 | .vco = { .min = G4X_VCO_MIN, | 389 | .vco = { .min = G4X_VCO_MIN, |
@@ -388,8 +405,32 @@ static const intel_limit_t intel_limits[] = { | |||
388 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST | 405 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST |
389 | }, | 406 | }, |
390 | .find_pll = intel_g4x_find_best_PLL, | 407 | .find_pll = intel_g4x_find_best_PLL, |
391 | }, | 408 | }; |
392 | { /* INTEL_LIMIT_IGD_SDVO */ | 409 | |
410 | static const intel_limit_t intel_limits_g4x_display_port = { | ||
411 | .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN, | ||
412 | .max = G4X_DOT_DISPLAY_PORT_MAX }, | ||
413 | .vco = { .min = G4X_VCO_MIN, | ||
414 | .max = G4X_VCO_MAX}, | ||
415 | .n = { .min = G4X_N_DISPLAY_PORT_MIN, | ||
416 | .max = G4X_N_DISPLAY_PORT_MAX }, | ||
417 | .m = { .min = G4X_M_DISPLAY_PORT_MIN, | ||
418 | .max = G4X_M_DISPLAY_PORT_MAX }, | ||
419 | .m1 = { .min = G4X_M1_DISPLAY_PORT_MIN, | ||
420 | .max = G4X_M1_DISPLAY_PORT_MAX }, | ||
421 | .m2 = { .min = G4X_M2_DISPLAY_PORT_MIN, | ||
422 | .max = G4X_M2_DISPLAY_PORT_MAX }, | ||
423 | .p = { .min = G4X_P_DISPLAY_PORT_MIN, | ||
424 | .max = G4X_P_DISPLAY_PORT_MAX }, | ||
425 | .p1 = { .min = G4X_P1_DISPLAY_PORT_MIN, | ||
426 | .max = G4X_P1_DISPLAY_PORT_MAX}, | ||
427 | .p2 = { .dot_limit = G4X_P2_DISPLAY_PORT_LIMIT, | ||
428 | .p2_slow = G4X_P2_DISPLAY_PORT_SLOW, | ||
429 | .p2_fast = G4X_P2_DISPLAY_PORT_FAST }, | ||
430 | .find_pll = intel_find_pll_g4x_dp, | ||
431 | }; | ||
432 | |||
433 | static const intel_limit_t intel_limits_igd_sdvo = { | ||
393 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, | 434 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, |
394 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, | 435 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, |
395 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, | 436 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, |
@@ -401,8 +442,9 @@ static const intel_limit_t intel_limits[] = { | |||
401 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 442 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
402 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 443 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
403 | .find_pll = intel_find_best_PLL, | 444 | .find_pll = intel_find_best_PLL, |
404 | }, | 445 | }; |
405 | { /* INTEL_LIMIT_IGD_LVDS */ | 446 | |
447 | static const intel_limit_t intel_limits_igd_lvds = { | ||
406 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 448 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
407 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, | 449 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, |
408 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, | 450 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, |
@@ -415,8 +457,9 @@ static const intel_limit_t intel_limits[] = { | |||
415 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 457 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
416 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, | 458 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, |
417 | .find_pll = intel_find_best_PLL, | 459 | .find_pll = intel_find_best_PLL, |
418 | }, | 460 | }; |
419 | { /* INTEL_LIMIT_IGDNG_SDVO_DAC */ | 461 | |
462 | static const intel_limit_t intel_limits_igdng_sdvo = { | ||
420 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, | 463 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, |
421 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, | 464 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, |
422 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, | 465 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, |
@@ -429,8 +472,9 @@ static const intel_limit_t intel_limits[] = { | |||
429 | .p2_slow = IGDNG_P2_SDVO_DAC_SLOW, | 472 | .p2_slow = IGDNG_P2_SDVO_DAC_SLOW, |
430 | .p2_fast = IGDNG_P2_SDVO_DAC_FAST }, | 473 | .p2_fast = IGDNG_P2_SDVO_DAC_FAST }, |
431 | .find_pll = intel_igdng_find_best_PLL, | 474 | .find_pll = intel_igdng_find_best_PLL, |
432 | }, | 475 | }; |
433 | { /* INTEL_LIMIT_IGDNG_LVDS */ | 476 | |
477 | static const intel_limit_t intel_limits_igdng_lvds = { | ||
434 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, | 478 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, |
435 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, | 479 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, |
436 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, | 480 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, |
@@ -443,16 +487,15 @@ static const intel_limit_t intel_limits[] = { | |||
443 | .p2_slow = IGDNG_P2_LVDS_SLOW, | 487 | .p2_slow = IGDNG_P2_LVDS_SLOW, |
444 | .p2_fast = IGDNG_P2_LVDS_FAST }, | 488 | .p2_fast = IGDNG_P2_LVDS_FAST }, |
445 | .find_pll = intel_igdng_find_best_PLL, | 489 | .find_pll = intel_igdng_find_best_PLL, |
446 | }, | ||
447 | }; | 490 | }; |
448 | 491 | ||
449 | static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc) | 492 | static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc) |
450 | { | 493 | { |
451 | const intel_limit_t *limit; | 494 | const intel_limit_t *limit; |
452 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 495 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
453 | limit = &intel_limits[INTEL_LIMIT_IGDNG_LVDS]; | 496 | limit = &intel_limits_igdng_lvds; |
454 | else | 497 | else |
455 | limit = &intel_limits[INTEL_LIMIT_IGDNG_SDVO_DAC]; | 498 | limit = &intel_limits_igdng_sdvo; |
456 | 499 | ||
457 | return limit; | 500 | return limit; |
458 | } | 501 | } |
@@ -467,19 +510,19 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) | |||
467 | if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == | 510 | if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == |
468 | LVDS_CLKB_POWER_UP) | 511 | LVDS_CLKB_POWER_UP) |
469 | /* LVDS with dual channel */ | 512 | /* LVDS with dual channel */ |
470 | limit = &intel_limits | 513 | limit = &intel_limits_g4x_dual_channel_lvds; |
471 | [INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS]; | ||
472 | else | 514 | else |
473 | /* LVDS with dual channel */ | 515 | /* LVDS with dual channel */ |
474 | limit = &intel_limits | 516 | limit = &intel_limits_g4x_single_channel_lvds; |
475 | [INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS]; | ||
476 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || | 517 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || |
477 | intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { | 518 | intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { |
478 | limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC]; | 519 | limit = &intel_limits_g4x_hdmi; |
479 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { | 520 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { |
480 | limit = &intel_limits[INTEL_LIMIT_G4X_SDVO]; | 521 | limit = &intel_limits_g4x_sdvo; |
522 | } else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) { | ||
523 | limit = &intel_limits_g4x_display_port; | ||
481 | } else /* The option is for other outputs */ | 524 | } else /* The option is for other outputs */ |
482 | limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; | 525 | limit = &intel_limits_i9xx_sdvo; |
483 | 526 | ||
484 | return limit; | 527 | return limit; |
485 | } | 528 | } |
@@ -495,19 +538,19 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) | |||
495 | limit = intel_g4x_limit(crtc); | 538 | limit = intel_g4x_limit(crtc); |
496 | } else if (IS_I9XX(dev) && !IS_IGD(dev)) { | 539 | } else if (IS_I9XX(dev) && !IS_IGD(dev)) { |
497 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 540 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
498 | limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; | 541 | limit = &intel_limits_i9xx_lvds; |
499 | else | 542 | else |
500 | limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; | 543 | limit = &intel_limits_i9xx_sdvo; |
501 | } else if (IS_IGD(dev)) { | 544 | } else if (IS_IGD(dev)) { |
502 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 545 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
503 | limit = &intel_limits[INTEL_LIMIT_IGD_LVDS]; | 546 | limit = &intel_limits_igd_lvds; |
504 | else | 547 | else |
505 | limit = &intel_limits[INTEL_LIMIT_IGD_SDVO_DAC]; | 548 | limit = &intel_limits_igd_sdvo; |
506 | } else { | 549 | } else { |
507 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 550 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
508 | limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS]; | 551 | limit = &intel_limits_i8xx_lvds; |
509 | else | 552 | else |
510 | limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC]; | 553 | limit = &intel_limits_i8xx_dvo; |
511 | } | 554 | } |
512 | return limit; | 555 | return limit; |
513 | } | 556 | } |
@@ -764,6 +807,35 @@ out: | |||
764 | return found; | 807 | return found; |
765 | } | 808 | } |
766 | 809 | ||
810 | /* DisplayPort has only two frequencies, 162MHz and 270MHz */ | ||
811 | static bool | ||
812 | intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
813 | int target, int refclk, intel_clock_t *best_clock) | ||
814 | { | ||
815 | intel_clock_t clock; | ||
816 | if (target < 200000) { | ||
817 | clock.dot = 161670; | ||
818 | clock.p = 20; | ||
819 | clock.p1 = 2; | ||
820 | clock.p2 = 10; | ||
821 | clock.n = 0x01; | ||
822 | clock.m = 97; | ||
823 | clock.m1 = 0x10; | ||
824 | clock.m2 = 0x05; | ||
825 | } else { | ||
826 | clock.dot = 270000; | ||
827 | clock.p = 10; | ||
828 | clock.p1 = 1; | ||
829 | clock.p2 = 10; | ||
830 | clock.n = 0x02; | ||
831 | clock.m = 108; | ||
832 | clock.m1 = 0x12; | ||
833 | clock.m2 = 0x06; | ||
834 | } | ||
835 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); | ||
836 | return true; | ||
837 | } | ||
838 | |||
767 | void | 839 | void |
768 | intel_wait_for_vblank(struct drm_device *dev) | 840 | intel_wait_for_vblank(struct drm_device *dev) |
769 | { | 841 | { |
@@ -1541,7 +1613,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1541 | intel_clock_t clock; | 1613 | intel_clock_t clock; |
1542 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; | 1614 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; |
1543 | bool ok, is_sdvo = false, is_dvo = false; | 1615 | bool ok, is_sdvo = false, is_dvo = false; |
1544 | bool is_crt = false, is_lvds = false, is_tv = false; | 1616 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; |
1545 | struct drm_mode_config *mode_config = &dev->mode_config; | 1617 | struct drm_mode_config *mode_config = &dev->mode_config; |
1546 | struct drm_connector *connector; | 1618 | struct drm_connector *connector; |
1547 | const intel_limit_t *limit; | 1619 | const intel_limit_t *limit; |
@@ -1585,6 +1657,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1585 | case INTEL_OUTPUT_ANALOG: | 1657 | case INTEL_OUTPUT_ANALOG: |
1586 | is_crt = true; | 1658 | is_crt = true; |
1587 | break; | 1659 | break; |
1660 | case INTEL_OUTPUT_DISPLAYPORT: | ||
1661 | is_dp = true; | ||
1662 | break; | ||
1588 | } | 1663 | } |
1589 | 1664 | ||
1590 | num_outputs++; | 1665 | num_outputs++; |
@@ -1600,6 +1675,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1600 | } else { | 1675 | } else { |
1601 | refclk = 48000; | 1676 | refclk = 48000; |
1602 | } | 1677 | } |
1678 | |||
1603 | 1679 | ||
1604 | /* | 1680 | /* |
1605 | * Returns a set of divisors for the desired target clock with the given | 1681 | * Returns a set of divisors for the desired target clock with the given |
@@ -1662,6 +1738,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1662 | else if (IS_IGDNG(dev)) | 1738 | else if (IS_IGDNG(dev)) |
1663 | dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; | 1739 | dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; |
1664 | } | 1740 | } |
1741 | if (is_dp) | ||
1742 | dpll |= DPLL_DVO_HIGH_SPEED; | ||
1665 | 1743 | ||
1666 | /* compute bitmask from p1 value */ | 1744 | /* compute bitmask from p1 value */ |
1667 | if (IS_IGD(dev)) | 1745 | if (IS_IGD(dev)) |
@@ -1809,6 +1887,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1809 | I915_WRITE(lvds_reg, lvds); | 1887 | I915_WRITE(lvds_reg, lvds); |
1810 | I915_READ(lvds_reg); | 1888 | I915_READ(lvds_reg); |
1811 | } | 1889 | } |
1890 | if (is_dp) | ||
1891 | intel_dp_set_m_n(crtc, mode, adjusted_mode); | ||
1812 | 1892 | ||
1813 | I915_WRITE(fp_reg, fp); | 1893 | I915_WRITE(fp_reg, fp); |
1814 | I915_WRITE(dpll_reg, dpll); | 1894 | I915_WRITE(dpll_reg, dpll); |
@@ -2475,6 +2555,8 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
2475 | found = intel_sdvo_init(dev, SDVOB); | 2555 | found = intel_sdvo_init(dev, SDVOB); |
2476 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | 2556 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) |
2477 | intel_hdmi_init(dev, SDVOB); | 2557 | intel_hdmi_init(dev, SDVOB); |
2558 | if (!found && SUPPORTS_INTEGRATED_DP(dev)) | ||
2559 | intel_dp_init(dev, DP_B); | ||
2478 | } | 2560 | } |
2479 | 2561 | ||
2480 | /* Before G4X SDVOC doesn't have its own detect register */ | 2562 | /* Before G4X SDVOC doesn't have its own detect register */ |
@@ -2487,7 +2569,11 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
2487 | found = intel_sdvo_init(dev, SDVOC); | 2569 | found = intel_sdvo_init(dev, SDVOC); |
2488 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | 2570 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) |
2489 | intel_hdmi_init(dev, SDVOC); | 2571 | intel_hdmi_init(dev, SDVOC); |
2572 | if (!found && SUPPORTS_INTEGRATED_DP(dev)) | ||
2573 | intel_dp_init(dev, DP_C); | ||
2490 | } | 2574 | } |
2575 | if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) | ||
2576 | intel_dp_init(dev, DP_D); | ||
2491 | } else | 2577 | } else |
2492 | intel_dvo_init(dev); | 2578 | intel_dvo_init(dev); |
2493 | 2579 | ||
@@ -2530,6 +2616,11 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
2530 | (1 << 1)); | 2616 | (1 << 1)); |
2531 | clone_mask = (1 << INTEL_OUTPUT_TVOUT); | 2617 | clone_mask = (1 << INTEL_OUTPUT_TVOUT); |
2532 | break; | 2618 | break; |
2619 | case INTEL_OUTPUT_DISPLAYPORT: | ||
2620 | crtc_mask = ((1 << 0) | | ||
2621 | (1 << 1)); | ||
2622 | clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT); | ||
2623 | break; | ||
2533 | } | 2624 | } |
2534 | encoder->possible_crtcs = crtc_mask; | 2625 | encoder->possible_crtcs = crtc_mask; |
2535 | encoder->possible_clones = intel_connector_clones(dev, clone_mask); | 2626 | encoder->possible_clones = intel_connector_clones(dev, clone_mask); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c new file mode 100644 index 000000000000..8f8d37d5663a --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -0,0 +1,1153 @@ | |||
1 | /* | ||
2 | * Copyright © 2008 Intel Corporation | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Keith Packard <keithp@keithp.com> | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <linux/i2c.h> | ||
29 | #include "drmP.h" | ||
30 | #include "drm.h" | ||
31 | #include "drm_crtc.h" | ||
32 | #include "drm_crtc_helper.h" | ||
33 | #include "intel_drv.h" | ||
34 | #include "i915_drm.h" | ||
35 | #include "i915_drv.h" | ||
36 | #include "intel_dp.h" | ||
37 | |||
38 | #define DP_LINK_STATUS_SIZE 6 | ||
39 | #define DP_LINK_CHECK_TIMEOUT (10 * 1000) | ||
40 | |||
41 | #define DP_LINK_CONFIGURATION_SIZE 9 | ||
42 | |||
43 | struct intel_dp_priv { | ||
44 | uint32_t output_reg; | ||
45 | uint32_t DP; | ||
46 | uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; | ||
47 | uint32_t save_DP; | ||
48 | uint8_t save_link_configuration[DP_LINK_CONFIGURATION_SIZE]; | ||
49 | bool has_audio; | ||
50 | int dpms_mode; | ||
51 | uint8_t link_bw; | ||
52 | uint8_t lane_count; | ||
53 | uint8_t dpcd[4]; | ||
54 | struct intel_output *intel_output; | ||
55 | struct i2c_adapter adapter; | ||
56 | struct i2c_algo_dp_aux_data algo; | ||
57 | }; | ||
58 | |||
59 | static void | ||
60 | intel_dp_link_train(struct intel_output *intel_output, uint32_t DP, | ||
61 | uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]); | ||
62 | |||
63 | static void | ||
64 | intel_dp_link_down(struct intel_output *intel_output, uint32_t DP); | ||
65 | |||
66 | static int | ||
67 | intel_dp_max_lane_count(struct intel_output *intel_output) | ||
68 | { | ||
69 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
70 | int max_lane_count = 4; | ||
71 | |||
72 | if (dp_priv->dpcd[0] >= 0x11) { | ||
73 | max_lane_count = dp_priv->dpcd[2] & 0x1f; | ||
74 | switch (max_lane_count) { | ||
75 | case 1: case 2: case 4: | ||
76 | break; | ||
77 | default: | ||
78 | max_lane_count = 4; | ||
79 | } | ||
80 | } | ||
81 | return max_lane_count; | ||
82 | } | ||
83 | |||
84 | static int | ||
85 | intel_dp_max_link_bw(struct intel_output *intel_output) | ||
86 | { | ||
87 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
88 | int max_link_bw = dp_priv->dpcd[1]; | ||
89 | |||
90 | switch (max_link_bw) { | ||
91 | case DP_LINK_BW_1_62: | ||
92 | case DP_LINK_BW_2_7: | ||
93 | break; | ||
94 | default: | ||
95 | max_link_bw = DP_LINK_BW_1_62; | ||
96 | break; | ||
97 | } | ||
98 | return max_link_bw; | ||
99 | } | ||
100 | |||
101 | static int | ||
102 | intel_dp_link_clock(uint8_t link_bw) | ||
103 | { | ||
104 | if (link_bw == DP_LINK_BW_2_7) | ||
105 | return 270000; | ||
106 | else | ||
107 | return 162000; | ||
108 | } | ||
109 | |||
110 | /* I think this is a fiction */ | ||
111 | static int | ||
112 | intel_dp_link_required(int pixel_clock) | ||
113 | { | ||
114 | return pixel_clock * 3; | ||
115 | } | ||
116 | |||
117 | static int | ||
118 | intel_dp_mode_valid(struct drm_connector *connector, | ||
119 | struct drm_display_mode *mode) | ||
120 | { | ||
121 | struct intel_output *intel_output = to_intel_output(connector); | ||
122 | int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output)); | ||
123 | int max_lanes = intel_dp_max_lane_count(intel_output); | ||
124 | |||
125 | if (intel_dp_link_required(mode->clock) > max_link_clock * max_lanes) | ||
126 | return MODE_CLOCK_HIGH; | ||
127 | |||
128 | if (mode->clock < 10000) | ||
129 | return MODE_CLOCK_LOW; | ||
130 | |||
131 | return MODE_OK; | ||
132 | } | ||
133 | |||
134 | static uint32_t | ||
135 | pack_aux(uint8_t *src, int src_bytes) | ||
136 | { | ||
137 | int i; | ||
138 | uint32_t v = 0; | ||
139 | |||
140 | if (src_bytes > 4) | ||
141 | src_bytes = 4; | ||
142 | for (i = 0; i < src_bytes; i++) | ||
143 | v |= ((uint32_t) src[i]) << ((3-i) * 8); | ||
144 | return v; | ||
145 | } | ||
146 | |||
147 | static void | ||
148 | unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) | ||
149 | { | ||
150 | int i; | ||
151 | if (dst_bytes > 4) | ||
152 | dst_bytes = 4; | ||
153 | for (i = 0; i < dst_bytes; i++) | ||
154 | dst[i] = src >> ((3-i) * 8); | ||
155 | } | ||
156 | |||
157 | /* hrawclock is 1/4 the FSB frequency */ | ||
158 | static int | ||
159 | intel_hrawclk(struct drm_device *dev) | ||
160 | { | ||
161 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
162 | uint32_t clkcfg; | ||
163 | |||
164 | clkcfg = I915_READ(CLKCFG); | ||
165 | switch (clkcfg & CLKCFG_FSB_MASK) { | ||
166 | case CLKCFG_FSB_400: | ||
167 | return 100; | ||
168 | case CLKCFG_FSB_533: | ||
169 | return 133; | ||
170 | case CLKCFG_FSB_667: | ||
171 | return 166; | ||
172 | case CLKCFG_FSB_800: | ||
173 | return 200; | ||
174 | case CLKCFG_FSB_1067: | ||
175 | return 266; | ||
176 | case CLKCFG_FSB_1333: | ||
177 | return 333; | ||
178 | /* these two are just a guess; one of them might be right */ | ||
179 | case CLKCFG_FSB_1600: | ||
180 | case CLKCFG_FSB_1600_ALT: | ||
181 | return 400; | ||
182 | default: | ||
183 | return 133; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | static int | ||
188 | intel_dp_aux_ch(struct intel_output *intel_output, | ||
189 | uint8_t *send, int send_bytes, | ||
190 | uint8_t *recv, int recv_size) | ||
191 | { | ||
192 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
193 | uint32_t output_reg = dp_priv->output_reg; | ||
194 | struct drm_device *dev = intel_output->base.dev; | ||
195 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
196 | uint32_t ch_ctl = output_reg + 0x10; | ||
197 | uint32_t ch_data = ch_ctl + 4; | ||
198 | int i; | ||
199 | int recv_bytes; | ||
200 | uint32_t ctl; | ||
201 | uint32_t status; | ||
202 | uint32_t aux_clock_divider; | ||
203 | int try; | ||
204 | |||
205 | /* The clock divider is based off the hrawclk, | ||
206 | * and would like to run at 2MHz. So, take the | ||
207 | * hrawclk value and divide by 2 and use that | ||
208 | */ | ||
209 | aux_clock_divider = intel_hrawclk(dev) / 2; | ||
210 | /* Must try at least 3 times according to DP spec */ | ||
211 | for (try = 0; try < 5; try++) { | ||
212 | /* Load the send data into the aux channel data registers */ | ||
213 | for (i = 0; i < send_bytes; i += 4) { | ||
214 | uint32_t d = pack_aux(send + i, send_bytes - i);; | ||
215 | |||
216 | I915_WRITE(ch_data + i, d); | ||
217 | } | ||
218 | |||
219 | ctl = (DP_AUX_CH_CTL_SEND_BUSY | | ||
220 | DP_AUX_CH_CTL_TIME_OUT_400us | | ||
221 | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | | ||
222 | (5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | | ||
223 | (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | | ||
224 | DP_AUX_CH_CTL_DONE | | ||
225 | DP_AUX_CH_CTL_TIME_OUT_ERROR | | ||
226 | DP_AUX_CH_CTL_RECEIVE_ERROR); | ||
227 | |||
228 | /* Send the command and wait for it to complete */ | ||
229 | I915_WRITE(ch_ctl, ctl); | ||
230 | (void) I915_READ(ch_ctl); | ||
231 | for (;;) { | ||
232 | udelay(100); | ||
233 | status = I915_READ(ch_ctl); | ||
234 | if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) | ||
235 | break; | ||
236 | } | ||
237 | |||
238 | /* Clear done status and any errors */ | ||
239 | I915_WRITE(ch_ctl, (ctl | | ||
240 | DP_AUX_CH_CTL_DONE | | ||
241 | DP_AUX_CH_CTL_TIME_OUT_ERROR | | ||
242 | DP_AUX_CH_CTL_RECEIVE_ERROR)); | ||
243 | (void) I915_READ(ch_ctl); | ||
244 | if ((status & DP_AUX_CH_CTL_TIME_OUT_ERROR) == 0) | ||
245 | break; | ||
246 | } | ||
247 | |||
248 | if ((status & DP_AUX_CH_CTL_DONE) == 0) { | ||
249 | printk(KERN_ERR "dp_aux_ch not done status 0x%08x\n", status); | ||
250 | return -EBUSY; | ||
251 | } | ||
252 | |||
253 | /* Check for timeout or receive error. | ||
254 | * Timeouts occur when the sink is not connected | ||
255 | */ | ||
256 | if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { | ||
257 | printk(KERN_ERR "dp_aux_ch receive error status 0x%08x\n", status); | ||
258 | return -EIO; | ||
259 | } | ||
260 | if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { | ||
261 | printk(KERN_ERR "dp_aux_ch timeout status 0x%08x\n", status); | ||
262 | return -ETIMEDOUT; | ||
263 | } | ||
264 | |||
265 | /* Unload any bytes sent back from the other side */ | ||
266 | recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> | ||
267 | DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); | ||
268 | |||
269 | if (recv_bytes > recv_size) | ||
270 | recv_bytes = recv_size; | ||
271 | |||
272 | for (i = 0; i < recv_bytes; i += 4) { | ||
273 | uint32_t d = I915_READ(ch_data + i); | ||
274 | |||
275 | unpack_aux(d, recv + i, recv_bytes - i); | ||
276 | } | ||
277 | |||
278 | return recv_bytes; | ||
279 | } | ||
280 | |||
281 | /* Write data to the aux channel in native mode */ | ||
282 | static int | ||
283 | intel_dp_aux_native_write(struct intel_output *intel_output, | ||
284 | uint16_t address, uint8_t *send, int send_bytes) | ||
285 | { | ||
286 | int ret; | ||
287 | uint8_t msg[20]; | ||
288 | int msg_bytes; | ||
289 | uint8_t ack; | ||
290 | |||
291 | if (send_bytes > 16) | ||
292 | return -1; | ||
293 | msg[0] = AUX_NATIVE_WRITE << 4; | ||
294 | msg[1] = address >> 8; | ||
295 | msg[2] = address; | ||
296 | msg[3] = send_bytes - 1; | ||
297 | memcpy(&msg[4], send, send_bytes); | ||
298 | msg_bytes = send_bytes + 4; | ||
299 | for (;;) { | ||
300 | ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, &ack, 1); | ||
301 | if (ret < 0) | ||
302 | return ret; | ||
303 | if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) | ||
304 | break; | ||
305 | else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) | ||
306 | udelay(100); | ||
307 | else | ||
308 | return -EIO; | ||
309 | } | ||
310 | return send_bytes; | ||
311 | } | ||
312 | |||
313 | /* Write a single byte to the aux channel in native mode */ | ||
314 | static int | ||
315 | intel_dp_aux_native_write_1(struct intel_output *intel_output, | ||
316 | uint16_t address, uint8_t byte) | ||
317 | { | ||
318 | return intel_dp_aux_native_write(intel_output, address, &byte, 1); | ||
319 | } | ||
320 | |||
321 | /* read bytes from a native aux channel */ | ||
322 | static int | ||
323 | intel_dp_aux_native_read(struct intel_output *intel_output, | ||
324 | uint16_t address, uint8_t *recv, int recv_bytes) | ||
325 | { | ||
326 | uint8_t msg[4]; | ||
327 | int msg_bytes; | ||
328 | uint8_t reply[20]; | ||
329 | int reply_bytes; | ||
330 | uint8_t ack; | ||
331 | int ret; | ||
332 | |||
333 | msg[0] = AUX_NATIVE_READ << 4; | ||
334 | msg[1] = address >> 8; | ||
335 | msg[2] = address & 0xff; | ||
336 | msg[3] = recv_bytes - 1; | ||
337 | |||
338 | msg_bytes = 4; | ||
339 | reply_bytes = recv_bytes + 1; | ||
340 | |||
341 | for (;;) { | ||
342 | ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, | ||
343 | reply, reply_bytes); | ||
344 | if (ret == 0) | ||
345 | return -EPROTO; | ||
346 | if (ret < 0) | ||
347 | return ret; | ||
348 | ack = reply[0]; | ||
349 | if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) { | ||
350 | memcpy(recv, reply + 1, ret - 1); | ||
351 | return ret - 1; | ||
352 | } | ||
353 | else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) | ||
354 | udelay(100); | ||
355 | else | ||
356 | return -EIO; | ||
357 | } | ||
358 | } | ||
359 | |||
360 | static int | ||
361 | intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, | ||
362 | uint8_t *send, int send_bytes, | ||
363 | uint8_t *recv, int recv_bytes) | ||
364 | { | ||
365 | struct intel_dp_priv *dp_priv = container_of(adapter, | ||
366 | struct intel_dp_priv, | ||
367 | adapter); | ||
368 | struct intel_output *intel_output = dp_priv->intel_output; | ||
369 | |||
370 | return intel_dp_aux_ch(intel_output, | ||
371 | send, send_bytes, recv, recv_bytes); | ||
372 | } | ||
373 | |||
374 | static int | ||
375 | intel_dp_i2c_init(struct intel_output *intel_output, const char *name) | ||
376 | { | ||
377 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
378 | |||
379 | DRM_ERROR("i2c_init %s\n", name); | ||
380 | dp_priv->algo.running = false; | ||
381 | dp_priv->algo.address = 0; | ||
382 | dp_priv->algo.aux_ch = intel_dp_i2c_aux_ch; | ||
383 | |||
384 | memset(&dp_priv->adapter, '\0', sizeof (dp_priv->adapter)); | ||
385 | dp_priv->adapter.owner = THIS_MODULE; | ||
386 | dp_priv->adapter.class = I2C_CLASS_DDC; | ||
387 | strncpy (dp_priv->adapter.name, name, sizeof dp_priv->adapter.name - 1); | ||
388 | dp_priv->adapter.name[sizeof dp_priv->adapter.name - 1] = '\0'; | ||
389 | dp_priv->adapter.algo_data = &dp_priv->algo; | ||
390 | dp_priv->adapter.dev.parent = &intel_output->base.kdev; | ||
391 | |||
392 | return i2c_dp_aux_add_bus(&dp_priv->adapter); | ||
393 | } | ||
394 | |||
395 | static bool | ||
396 | intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | ||
397 | struct drm_display_mode *adjusted_mode) | ||
398 | { | ||
399 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
400 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
401 | int lane_count, clock; | ||
402 | int max_lane_count = intel_dp_max_lane_count(intel_output); | ||
403 | int max_clock = intel_dp_max_link_bw(intel_output) == DP_LINK_BW_2_7 ? 1 : 0; | ||
404 | static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; | ||
405 | |||
406 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { | ||
407 | for (clock = 0; clock <= max_clock; clock++) { | ||
408 | int link_avail = intel_dp_link_clock(bws[clock]) * lane_count; | ||
409 | |||
410 | if (intel_dp_link_required(mode->clock) <= link_avail) { | ||
411 | dp_priv->link_bw = bws[clock]; | ||
412 | dp_priv->lane_count = lane_count; | ||
413 | adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); | ||
414 | printk(KERN_ERR "link bw %02x lane count %d clock %d\n", | ||
415 | dp_priv->link_bw, dp_priv->lane_count, | ||
416 | adjusted_mode->clock); | ||
417 | return true; | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | return false; | ||
422 | } | ||
423 | |||
424 | struct intel_dp_m_n { | ||
425 | uint32_t tu; | ||
426 | uint32_t gmch_m; | ||
427 | uint32_t gmch_n; | ||
428 | uint32_t link_m; | ||
429 | uint32_t link_n; | ||
430 | }; | ||
431 | |||
432 | static void | ||
433 | intel_reduce_ratio(uint32_t *num, uint32_t *den) | ||
434 | { | ||
435 | while (*num > 0xffffff || *den > 0xffffff) { | ||
436 | *num >>= 1; | ||
437 | *den >>= 1; | ||
438 | } | ||
439 | } | ||
440 | |||
441 | static void | ||
442 | intel_dp_compute_m_n(int bytes_per_pixel, | ||
443 | int nlanes, | ||
444 | int pixel_clock, | ||
445 | int link_clock, | ||
446 | struct intel_dp_m_n *m_n) | ||
447 | { | ||
448 | m_n->tu = 64; | ||
449 | m_n->gmch_m = pixel_clock * bytes_per_pixel; | ||
450 | m_n->gmch_n = link_clock * nlanes; | ||
451 | intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); | ||
452 | m_n->link_m = pixel_clock; | ||
453 | m_n->link_n = link_clock; | ||
454 | intel_reduce_ratio(&m_n->link_m, &m_n->link_n); | ||
455 | } | ||
456 | |||
457 | void | ||
458 | intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | ||
459 | struct drm_display_mode *adjusted_mode) | ||
460 | { | ||
461 | struct drm_device *dev = crtc->dev; | ||
462 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
463 | struct drm_connector *connector; | ||
464 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
465 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
466 | int lane_count = 4; | ||
467 | struct intel_dp_m_n m_n; | ||
468 | |||
469 | /* | ||
470 | * Find the lane count in the intel_output private | ||
471 | */ | ||
472 | list_for_each_entry(connector, &mode_config->connector_list, head) { | ||
473 | struct intel_output *intel_output = to_intel_output(connector); | ||
474 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
475 | |||
476 | if (!connector->encoder || connector->encoder->crtc != crtc) | ||
477 | continue; | ||
478 | |||
479 | if (intel_output->type == INTEL_OUTPUT_DISPLAYPORT) { | ||
480 | lane_count = dp_priv->lane_count; | ||
481 | break; | ||
482 | } | ||
483 | } | ||
484 | |||
485 | /* | ||
486 | * Compute the GMCH and Link ratios. The '3' here is | ||
487 | * the number of bytes_per_pixel post-LUT, which we always | ||
488 | * set up for 8-bits of R/G/B, or 3 bytes total. | ||
489 | */ | ||
490 | intel_dp_compute_m_n(3, lane_count, | ||
491 | mode->clock, adjusted_mode->clock, &m_n); | ||
492 | |||
493 | if (intel_crtc->pipe == 0) { | ||
494 | I915_WRITE(PIPEA_GMCH_DATA_M, | ||
495 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | ||
496 | m_n.gmch_m); | ||
497 | I915_WRITE(PIPEA_GMCH_DATA_N, | ||
498 | m_n.gmch_n); | ||
499 | I915_WRITE(PIPEA_DP_LINK_M, m_n.link_m); | ||
500 | I915_WRITE(PIPEA_DP_LINK_N, m_n.link_n); | ||
501 | } else { | ||
502 | I915_WRITE(PIPEB_GMCH_DATA_M, | ||
503 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | ||
504 | m_n.gmch_m); | ||
505 | I915_WRITE(PIPEB_GMCH_DATA_N, | ||
506 | m_n.gmch_n); | ||
507 | I915_WRITE(PIPEB_DP_LINK_M, m_n.link_m); | ||
508 | I915_WRITE(PIPEB_DP_LINK_N, m_n.link_n); | ||
509 | } | ||
510 | } | ||
511 | |||
512 | static void | ||
513 | intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | ||
514 | struct drm_display_mode *adjusted_mode) | ||
515 | { | ||
516 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
517 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
518 | struct drm_crtc *crtc = intel_output->enc.crtc; | ||
519 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
520 | |||
521 | dp_priv->DP = (DP_LINK_TRAIN_OFF | | ||
522 | DP_VOLTAGE_0_4 | | ||
523 | DP_PRE_EMPHASIS_0 | | ||
524 | DP_SYNC_VS_HIGH | | ||
525 | DP_SYNC_HS_HIGH); | ||
526 | |||
527 | switch (dp_priv->lane_count) { | ||
528 | case 1: | ||
529 | dp_priv->DP |= DP_PORT_WIDTH_1; | ||
530 | break; | ||
531 | case 2: | ||
532 | dp_priv->DP |= DP_PORT_WIDTH_2; | ||
533 | break; | ||
534 | case 4: | ||
535 | dp_priv->DP |= DP_PORT_WIDTH_4; | ||
536 | break; | ||
537 | } | ||
538 | if (dp_priv->has_audio) | ||
539 | dp_priv->DP |= DP_AUDIO_OUTPUT_ENABLE; | ||
540 | |||
541 | memset(dp_priv->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); | ||
542 | dp_priv->link_configuration[0] = dp_priv->link_bw; | ||
543 | dp_priv->link_configuration[1] = dp_priv->lane_count; | ||
544 | |||
545 | /* | ||
546 | * Check for DPCD version > 1.1, | ||
547 | * enable enahanced frame stuff in that case | ||
548 | */ | ||
549 | if (dp_priv->dpcd[0] >= 0x11) { | ||
550 | dp_priv->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; | ||
551 | dp_priv->DP |= DP_ENHANCED_FRAMING; | ||
552 | } | ||
553 | |||
554 | if (intel_crtc->pipe == 1) | ||
555 | dp_priv->DP |= DP_PIPEB_SELECT; | ||
556 | } | ||
557 | |||
558 | |||
559 | static void | ||
560 | intel_dp_dpms(struct drm_encoder *encoder, int mode) | ||
561 | { | ||
562 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
563 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
564 | struct drm_device *dev = intel_output->base.dev; | ||
565 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
566 | uint32_t dp_reg = I915_READ(dp_priv->output_reg); | ||
567 | |||
568 | if (mode != DRM_MODE_DPMS_ON) { | ||
569 | if (dp_reg & DP_PORT_EN) | ||
570 | intel_dp_link_down(intel_output, dp_priv->DP); | ||
571 | } else { | ||
572 | if (!(dp_reg & DP_PORT_EN)) | ||
573 | intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); | ||
574 | } | ||
575 | dp_priv->dpms_mode = mode; | ||
576 | } | ||
577 | |||
578 | /* | ||
579 | * Fetch AUX CH registers 0x202 - 0x207 which contain | ||
580 | * link status information | ||
581 | */ | ||
582 | static bool | ||
583 | intel_dp_get_link_status(struct intel_output *intel_output, | ||
584 | uint8_t link_status[DP_LINK_STATUS_SIZE]) | ||
585 | { | ||
586 | int ret; | ||
587 | |||
588 | ret = intel_dp_aux_native_read(intel_output, | ||
589 | DP_LANE0_1_STATUS, | ||
590 | link_status, DP_LINK_STATUS_SIZE); | ||
591 | if (ret != DP_LINK_STATUS_SIZE) | ||
592 | return false; | ||
593 | return true; | ||
594 | } | ||
595 | |||
596 | static uint8_t | ||
597 | intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
598 | int r) | ||
599 | { | ||
600 | return link_status[r - DP_LANE0_1_STATUS]; | ||
601 | } | ||
602 | |||
603 | static void | ||
604 | intel_dp_save(struct drm_connector *connector) | ||
605 | { | ||
606 | struct intel_output *intel_output = to_intel_output(connector); | ||
607 | struct drm_device *dev = intel_output->base.dev; | ||
608 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
609 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
610 | |||
611 | dp_priv->save_DP = I915_READ(dp_priv->output_reg); | ||
612 | intel_dp_aux_native_read(intel_output, DP_LINK_BW_SET, | ||
613 | dp_priv->save_link_configuration, | ||
614 | sizeof (dp_priv->save_link_configuration)); | ||
615 | } | ||
616 | |||
617 | static uint8_t | ||
618 | intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
619 | int lane) | ||
620 | { | ||
621 | int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); | ||
622 | int s = ((lane & 1) ? | ||
623 | DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : | ||
624 | DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); | ||
625 | uint8_t l = intel_dp_link_status(link_status, i); | ||
626 | |||
627 | return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; | ||
628 | } | ||
629 | |||
630 | static uint8_t | ||
631 | intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
632 | int lane) | ||
633 | { | ||
634 | int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); | ||
635 | int s = ((lane & 1) ? | ||
636 | DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : | ||
637 | DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); | ||
638 | uint8_t l = intel_dp_link_status(link_status, i); | ||
639 | |||
640 | return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; | ||
641 | } | ||
642 | |||
643 | |||
644 | #if 0 | ||
645 | static char *voltage_names[] = { | ||
646 | "0.4V", "0.6V", "0.8V", "1.2V" | ||
647 | }; | ||
648 | static char *pre_emph_names[] = { | ||
649 | "0dB", "3.5dB", "6dB", "9.5dB" | ||
650 | }; | ||
651 | static char *link_train_names[] = { | ||
652 | "pattern 1", "pattern 2", "idle", "off" | ||
653 | }; | ||
654 | #endif | ||
655 | |||
656 | /* | ||
657 | * These are source-specific values; current Intel hardware supports | ||
658 | * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB | ||
659 | */ | ||
660 | #define I830_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_800 | ||
661 | |||
662 | static uint8_t | ||
663 | intel_dp_pre_emphasis_max(uint8_t voltage_swing) | ||
664 | { | ||
665 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { | ||
666 | case DP_TRAIN_VOLTAGE_SWING_400: | ||
667 | return DP_TRAIN_PRE_EMPHASIS_6; | ||
668 | case DP_TRAIN_VOLTAGE_SWING_600: | ||
669 | return DP_TRAIN_PRE_EMPHASIS_6; | ||
670 | case DP_TRAIN_VOLTAGE_SWING_800: | ||
671 | return DP_TRAIN_PRE_EMPHASIS_3_5; | ||
672 | case DP_TRAIN_VOLTAGE_SWING_1200: | ||
673 | default: | ||
674 | return DP_TRAIN_PRE_EMPHASIS_0; | ||
675 | } | ||
676 | } | ||
677 | |||
678 | static void | ||
679 | intel_get_adjust_train(struct intel_output *intel_output, | ||
680 | uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
681 | int lane_count, | ||
682 | uint8_t train_set[4]) | ||
683 | { | ||
684 | uint8_t v = 0; | ||
685 | uint8_t p = 0; | ||
686 | int lane; | ||
687 | |||
688 | for (lane = 0; lane < lane_count; lane++) { | ||
689 | uint8_t this_v = intel_get_adjust_request_voltage(link_status, lane); | ||
690 | uint8_t this_p = intel_get_adjust_request_pre_emphasis(link_status, lane); | ||
691 | |||
692 | if (this_v > v) | ||
693 | v = this_v; | ||
694 | if (this_p > p) | ||
695 | p = this_p; | ||
696 | } | ||
697 | |||
698 | if (v >= I830_DP_VOLTAGE_MAX) | ||
699 | v = I830_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED; | ||
700 | |||
701 | if (p >= intel_dp_pre_emphasis_max(v)) | ||
702 | p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; | ||
703 | |||
704 | for (lane = 0; lane < 4; lane++) | ||
705 | train_set[lane] = v | p; | ||
706 | } | ||
707 | |||
708 | static uint32_t | ||
709 | intel_dp_signal_levels(uint8_t train_set, int lane_count) | ||
710 | { | ||
711 | uint32_t signal_levels = 0; | ||
712 | |||
713 | switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { | ||
714 | case DP_TRAIN_VOLTAGE_SWING_400: | ||
715 | default: | ||
716 | signal_levels |= DP_VOLTAGE_0_4; | ||
717 | break; | ||
718 | case DP_TRAIN_VOLTAGE_SWING_600: | ||
719 | signal_levels |= DP_VOLTAGE_0_6; | ||
720 | break; | ||
721 | case DP_TRAIN_VOLTAGE_SWING_800: | ||
722 | signal_levels |= DP_VOLTAGE_0_8; | ||
723 | break; | ||
724 | case DP_TRAIN_VOLTAGE_SWING_1200: | ||
725 | signal_levels |= DP_VOLTAGE_1_2; | ||
726 | break; | ||
727 | } | ||
728 | switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { | ||
729 | case DP_TRAIN_PRE_EMPHASIS_0: | ||
730 | default: | ||
731 | signal_levels |= DP_PRE_EMPHASIS_0; | ||
732 | break; | ||
733 | case DP_TRAIN_PRE_EMPHASIS_3_5: | ||
734 | signal_levels |= DP_PRE_EMPHASIS_3_5; | ||
735 | break; | ||
736 | case DP_TRAIN_PRE_EMPHASIS_6: | ||
737 | signal_levels |= DP_PRE_EMPHASIS_6; | ||
738 | break; | ||
739 | case DP_TRAIN_PRE_EMPHASIS_9_5: | ||
740 | signal_levels |= DP_PRE_EMPHASIS_9_5; | ||
741 | break; | ||
742 | } | ||
743 | return signal_levels; | ||
744 | } | ||
745 | |||
746 | static uint8_t | ||
747 | intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
748 | int lane) | ||
749 | { | ||
750 | int i = DP_LANE0_1_STATUS + (lane >> 1); | ||
751 | int s = (lane & 1) * 4; | ||
752 | uint8_t l = intel_dp_link_status(link_status, i); | ||
753 | |||
754 | return (l >> s) & 0xf; | ||
755 | } | ||
756 | |||
757 | /* Check for clock recovery is done on all channels */ | ||
758 | static bool | ||
759 | intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) | ||
760 | { | ||
761 | int lane; | ||
762 | uint8_t lane_status; | ||
763 | |||
764 | for (lane = 0; lane < lane_count; lane++) { | ||
765 | lane_status = intel_get_lane_status(link_status, lane); | ||
766 | if ((lane_status & DP_LANE_CR_DONE) == 0) | ||
767 | return false; | ||
768 | } | ||
769 | return true; | ||
770 | } | ||
771 | |||
772 | /* Check to see if channel eq is done on all channels */ | ||
773 | #define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\ | ||
774 | DP_LANE_CHANNEL_EQ_DONE|\ | ||
775 | DP_LANE_SYMBOL_LOCKED) | ||
776 | static bool | ||
777 | intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) | ||
778 | { | ||
779 | uint8_t lane_align; | ||
780 | uint8_t lane_status; | ||
781 | int lane; | ||
782 | |||
783 | lane_align = intel_dp_link_status(link_status, | ||
784 | DP_LANE_ALIGN_STATUS_UPDATED); | ||
785 | if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) | ||
786 | return false; | ||
787 | for (lane = 0; lane < lane_count; lane++) { | ||
788 | lane_status = intel_get_lane_status(link_status, lane); | ||
789 | if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) | ||
790 | return false; | ||
791 | } | ||
792 | return true; | ||
793 | } | ||
794 | |||
795 | static bool | ||
796 | intel_dp_set_link_train(struct intel_output *intel_output, | ||
797 | uint32_t dp_reg_value, | ||
798 | uint8_t dp_train_pat, | ||
799 | uint8_t train_set[4], | ||
800 | bool first) | ||
801 | { | ||
802 | struct drm_device *dev = intel_output->base.dev; | ||
803 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
804 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
805 | int ret; | ||
806 | |||
807 | I915_WRITE(dp_priv->output_reg, dp_reg_value); | ||
808 | POSTING_READ(dp_priv->output_reg); | ||
809 | if (first) | ||
810 | intel_wait_for_vblank(dev); | ||
811 | |||
812 | intel_dp_aux_native_write_1(intel_output, | ||
813 | DP_TRAINING_PATTERN_SET, | ||
814 | dp_train_pat); | ||
815 | |||
816 | ret = intel_dp_aux_native_write(intel_output, | ||
817 | DP_TRAINING_LANE0_SET, train_set, 4); | ||
818 | if (ret != 4) | ||
819 | return false; | ||
820 | |||
821 | return true; | ||
822 | } | ||
823 | |||
824 | static void | ||
825 | intel_dp_link_train(struct intel_output *intel_output, uint32_t DP, | ||
826 | uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]) | ||
827 | { | ||
828 | struct drm_device *dev = intel_output->base.dev; | ||
829 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
830 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
831 | uint8_t train_set[4]; | ||
832 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | ||
833 | int i; | ||
834 | uint8_t voltage; | ||
835 | bool clock_recovery = false; | ||
836 | bool channel_eq = false; | ||
837 | bool first = true; | ||
838 | int tries; | ||
839 | |||
840 | /* Write the link configuration data */ | ||
841 | intel_dp_aux_native_write(intel_output, 0x100, | ||
842 | link_configuration, DP_LINK_CONFIGURATION_SIZE); | ||
843 | |||
844 | DP |= DP_PORT_EN; | ||
845 | DP &= ~DP_LINK_TRAIN_MASK; | ||
846 | memset(train_set, 0, 4); | ||
847 | voltage = 0xff; | ||
848 | tries = 0; | ||
849 | clock_recovery = false; | ||
850 | for (;;) { | ||
851 | /* Use train_set[0] to set the voltage and pre emphasis values */ | ||
852 | uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count); | ||
853 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | ||
854 | |||
855 | if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_1, | ||
856 | DP_TRAINING_PATTERN_1, train_set, first)) | ||
857 | break; | ||
858 | first = false; | ||
859 | /* Set training pattern 1 */ | ||
860 | |||
861 | udelay(100); | ||
862 | if (!intel_dp_get_link_status(intel_output, link_status)) | ||
863 | break; | ||
864 | |||
865 | if (intel_clock_recovery_ok(link_status, dp_priv->lane_count)) { | ||
866 | clock_recovery = true; | ||
867 | break; | ||
868 | } | ||
869 | |||
870 | /* Check to see if we've tried the max voltage */ | ||
871 | for (i = 0; i < dp_priv->lane_count; i++) | ||
872 | if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) | ||
873 | break; | ||
874 | if (i == dp_priv->lane_count) | ||
875 | break; | ||
876 | |||
877 | /* Check to see if we've tried the same voltage 5 times */ | ||
878 | if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { | ||
879 | ++tries; | ||
880 | if (tries == 5) | ||
881 | break; | ||
882 | } else | ||
883 | tries = 0; | ||
884 | voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; | ||
885 | |||
886 | /* Compute new train_set as requested by target */ | ||
887 | intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set); | ||
888 | } | ||
889 | |||
890 | /* channel equalization */ | ||
891 | tries = 0; | ||
892 | channel_eq = false; | ||
893 | for (;;) { | ||
894 | /* Use train_set[0] to set the voltage and pre emphasis values */ | ||
895 | uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count); | ||
896 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | ||
897 | |||
898 | /* channel eq pattern */ | ||
899 | if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_2, | ||
900 | DP_TRAINING_PATTERN_2, train_set, | ||
901 | false)) | ||
902 | break; | ||
903 | |||
904 | udelay(400); | ||
905 | if (!intel_dp_get_link_status(intel_output, link_status)) | ||
906 | break; | ||
907 | |||
908 | if (intel_channel_eq_ok(link_status, dp_priv->lane_count)) { | ||
909 | channel_eq = true; | ||
910 | break; | ||
911 | } | ||
912 | |||
913 | /* Try 5 times */ | ||
914 | if (tries > 5) | ||
915 | break; | ||
916 | |||
917 | /* Compute new train_set as requested by target */ | ||
918 | intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set); | ||
919 | ++tries; | ||
920 | } | ||
921 | |||
922 | I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_OFF); | ||
923 | POSTING_READ(dp_priv->output_reg); | ||
924 | intel_dp_aux_native_write_1(intel_output, | ||
925 | DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE); | ||
926 | } | ||
927 | |||
928 | static void | ||
929 | intel_dp_link_down(struct intel_output *intel_output, uint32_t DP) | ||
930 | { | ||
931 | struct drm_device *dev = intel_output->base.dev; | ||
932 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
933 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
934 | |||
935 | I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN); | ||
936 | POSTING_READ(dp_priv->output_reg); | ||
937 | } | ||
938 | |||
939 | static void | ||
940 | intel_dp_restore(struct drm_connector *connector) | ||
941 | { | ||
942 | struct intel_output *intel_output = to_intel_output(connector); | ||
943 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
944 | |||
945 | if (dp_priv->save_DP & DP_PORT_EN) | ||
946 | intel_dp_link_train(intel_output, dp_priv->save_DP, dp_priv->save_link_configuration); | ||
947 | else | ||
948 | intel_dp_link_down(intel_output, dp_priv->save_DP); | ||
949 | } | ||
950 | |||
951 | /* | ||
952 | * According to DP spec | ||
953 | * 5.1.2: | ||
954 | * 1. Read DPCD | ||
955 | * 2. Configure link according to Receiver Capabilities | ||
956 | * 3. Use Link Training from 2.5.3.3 and 3.5.1.3 | ||
957 | * 4. Check link status on receipt of hot-plug interrupt | ||
958 | */ | ||
959 | |||
960 | static void | ||
961 | intel_dp_check_link_status(struct intel_output *intel_output) | ||
962 | { | ||
963 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
964 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | ||
965 | |||
966 | if (!intel_output->enc.crtc) | ||
967 | return; | ||
968 | |||
969 | if (!intel_dp_get_link_status(intel_output, link_status)) { | ||
970 | intel_dp_link_down(intel_output, dp_priv->DP); | ||
971 | return; | ||
972 | } | ||
973 | |||
974 | if (!intel_channel_eq_ok(link_status, dp_priv->lane_count)) | ||
975 | intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); | ||
976 | } | ||
977 | |||
978 | /** | ||
979 | * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. | ||
980 | * | ||
981 | * \return true if DP port is connected. | ||
982 | * \return false if DP port is disconnected. | ||
983 | */ | ||
984 | static enum drm_connector_status | ||
985 | intel_dp_detect(struct drm_connector *connector) | ||
986 | { | ||
987 | struct intel_output *intel_output = to_intel_output(connector); | ||
988 | struct drm_device *dev = intel_output->base.dev; | ||
989 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
990 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
991 | uint32_t temp, bit; | ||
992 | enum drm_connector_status status; | ||
993 | |||
994 | dp_priv->has_audio = false; | ||
995 | |||
996 | temp = I915_READ(PORT_HOTPLUG_EN); | ||
997 | |||
998 | I915_WRITE(PORT_HOTPLUG_EN, | ||
999 | temp | | ||
1000 | DPB_HOTPLUG_INT_EN | | ||
1001 | DPC_HOTPLUG_INT_EN | | ||
1002 | DPD_HOTPLUG_INT_EN); | ||
1003 | |||
1004 | POSTING_READ(PORT_HOTPLUG_EN); | ||
1005 | |||
1006 | switch (dp_priv->output_reg) { | ||
1007 | case DP_B: | ||
1008 | bit = DPB_HOTPLUG_INT_STATUS; | ||
1009 | break; | ||
1010 | case DP_C: | ||
1011 | bit = DPC_HOTPLUG_INT_STATUS; | ||
1012 | break; | ||
1013 | case DP_D: | ||
1014 | bit = DPD_HOTPLUG_INT_STATUS; | ||
1015 | break; | ||
1016 | default: | ||
1017 | return connector_status_unknown; | ||
1018 | } | ||
1019 | |||
1020 | temp = I915_READ(PORT_HOTPLUG_STAT); | ||
1021 | |||
1022 | if ((temp & bit) == 0) | ||
1023 | return connector_status_disconnected; | ||
1024 | |||
1025 | status = connector_status_disconnected; | ||
1026 | if (intel_dp_aux_native_read(intel_output, | ||
1027 | 0x000, dp_priv->dpcd, | ||
1028 | sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd)) | ||
1029 | { | ||
1030 | if (dp_priv->dpcd[0] != 0) | ||
1031 | status = connector_status_connected; | ||
1032 | } | ||
1033 | return status; | ||
1034 | } | ||
1035 | |||
1036 | static int intel_dp_get_modes(struct drm_connector *connector) | ||
1037 | { | ||
1038 | struct intel_output *intel_output = to_intel_output(connector); | ||
1039 | |||
1040 | /* We should parse the EDID data and find out if it has an audio sink | ||
1041 | */ | ||
1042 | |||
1043 | return intel_ddc_get_modes(intel_output); | ||
1044 | } | ||
1045 | |||
1046 | static void | ||
1047 | intel_dp_destroy (struct drm_connector *connector) | ||
1048 | { | ||
1049 | struct intel_output *intel_output = to_intel_output(connector); | ||
1050 | |||
1051 | if (intel_output->i2c_bus) | ||
1052 | intel_i2c_destroy(intel_output->i2c_bus); | ||
1053 | drm_sysfs_connector_remove(connector); | ||
1054 | drm_connector_cleanup(connector); | ||
1055 | kfree(intel_output); | ||
1056 | } | ||
1057 | |||
1058 | static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = { | ||
1059 | .dpms = intel_dp_dpms, | ||
1060 | .mode_fixup = intel_dp_mode_fixup, | ||
1061 | .prepare = intel_encoder_prepare, | ||
1062 | .mode_set = intel_dp_mode_set, | ||
1063 | .commit = intel_encoder_commit, | ||
1064 | }; | ||
1065 | |||
1066 | static const struct drm_connector_funcs intel_dp_connector_funcs = { | ||
1067 | .dpms = drm_helper_connector_dpms, | ||
1068 | .save = intel_dp_save, | ||
1069 | .restore = intel_dp_restore, | ||
1070 | .detect = intel_dp_detect, | ||
1071 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
1072 | .destroy = intel_dp_destroy, | ||
1073 | }; | ||
1074 | |||
1075 | static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = { | ||
1076 | .get_modes = intel_dp_get_modes, | ||
1077 | .mode_valid = intel_dp_mode_valid, | ||
1078 | .best_encoder = intel_best_encoder, | ||
1079 | }; | ||
1080 | |||
1081 | static void intel_dp_enc_destroy(struct drm_encoder *encoder) | ||
1082 | { | ||
1083 | drm_encoder_cleanup(encoder); | ||
1084 | } | ||
1085 | |||
1086 | static const struct drm_encoder_funcs intel_dp_enc_funcs = { | ||
1087 | .destroy = intel_dp_enc_destroy, | ||
1088 | }; | ||
1089 | |||
1090 | void | ||
1091 | intel_dp_hot_plug(struct intel_output *intel_output) | ||
1092 | { | ||
1093 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
1094 | |||
1095 | if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON) | ||
1096 | intel_dp_check_link_status(intel_output); | ||
1097 | } | ||
1098 | |||
1099 | void | ||
1100 | intel_dp_init(struct drm_device *dev, int output_reg) | ||
1101 | { | ||
1102 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1103 | struct drm_connector *connector; | ||
1104 | struct intel_output *intel_output; | ||
1105 | struct intel_dp_priv *dp_priv; | ||
1106 | |||
1107 | intel_output = kcalloc(sizeof(struct intel_output) + | ||
1108 | sizeof(struct intel_dp_priv), 1, GFP_KERNEL); | ||
1109 | if (!intel_output) | ||
1110 | return; | ||
1111 | |||
1112 | dp_priv = (struct intel_dp_priv *)(intel_output + 1); | ||
1113 | |||
1114 | connector = &intel_output->base; | ||
1115 | drm_connector_init(dev, connector, &intel_dp_connector_funcs, | ||
1116 | DRM_MODE_CONNECTOR_DisplayPort); | ||
1117 | drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); | ||
1118 | |||
1119 | intel_output->type = INTEL_OUTPUT_DISPLAYPORT; | ||
1120 | |||
1121 | connector->interlace_allowed = true; | ||
1122 | connector->doublescan_allowed = 0; | ||
1123 | |||
1124 | dp_priv->intel_output = intel_output; | ||
1125 | dp_priv->output_reg = output_reg; | ||
1126 | dp_priv->has_audio = false; | ||
1127 | dp_priv->dpms_mode = DRM_MODE_DPMS_ON; | ||
1128 | intel_output->dev_priv = dp_priv; | ||
1129 | |||
1130 | drm_encoder_init(dev, &intel_output->enc, &intel_dp_enc_funcs, | ||
1131 | DRM_MODE_ENCODER_TMDS); | ||
1132 | drm_encoder_helper_add(&intel_output->enc, &intel_dp_helper_funcs); | ||
1133 | |||
1134 | drm_mode_connector_attach_encoder(&intel_output->base, | ||
1135 | &intel_output->enc); | ||
1136 | drm_sysfs_connector_add(connector); | ||
1137 | |||
1138 | /* Set up the DDC bus. */ | ||
1139 | intel_dp_i2c_init(intel_output, | ||
1140 | (output_reg == DP_B) ? "DPDDC-B" : | ||
1141 | (output_reg == DP_C) ? "DPDDC-C" : "DPDDC-D"); | ||
1142 | intel_output->ddc_bus = &dp_priv->adapter; | ||
1143 | intel_output->hot_plug = intel_dp_hot_plug; | ||
1144 | |||
1145 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written | ||
1146 | * 0xd. Failure to do so will result in spurious interrupts being | ||
1147 | * generated on the port when a cable is not attached. | ||
1148 | */ | ||
1149 | if (IS_G4X(dev) && !IS_GM45(dev)) { | ||
1150 | u32 temp = I915_READ(PEG_BAND_GAP_DATA); | ||
1151 | I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); | ||
1152 | } | ||
1153 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_dp.h b/drivers/gpu/drm/i915/intel_dp.h new file mode 100644 index 000000000000..2b38054d3b6d --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp.h | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * Copyright © 2008 Keith Packard | ||
3 | * | ||
4 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
5 | * documentation for any purpose is hereby granted without fee, provided that | ||
6 | * the above copyright notice appear in all copies and that both that copyright | ||
7 | * notice and this permission notice appear in supporting documentation, and | ||
8 | * that the name of the copyright holders not be used in advertising or | ||
9 | * publicity pertaining to distribution of the software without specific, | ||
10 | * written prior permission. The copyright holders make no representations | ||
11 | * about the suitability of this software for any purpose. It is provided "as | ||
12 | * is" without express or implied warranty. | ||
13 | * | ||
14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
20 | * OF THIS SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #ifndef _INTEL_DP_H_ | ||
24 | #define _INTEL_DP_H_ | ||
25 | |||
26 | /* From the VESA DisplayPort spec */ | ||
27 | |||
28 | #define AUX_NATIVE_WRITE 0x8 | ||
29 | #define AUX_NATIVE_READ 0x9 | ||
30 | #define AUX_I2C_WRITE 0x0 | ||
31 | #define AUX_I2C_READ 0x1 | ||
32 | #define AUX_I2C_STATUS 0x2 | ||
33 | #define AUX_I2C_MOT 0x4 | ||
34 | |||
35 | #define AUX_NATIVE_REPLY_ACK (0x0 << 4) | ||
36 | #define AUX_NATIVE_REPLY_NACK (0x1 << 4) | ||
37 | #define AUX_NATIVE_REPLY_DEFER (0x2 << 4) | ||
38 | #define AUX_NATIVE_REPLY_MASK (0x3 << 4) | ||
39 | |||
40 | #define AUX_I2C_REPLY_ACK (0x0 << 6) | ||
41 | #define AUX_I2C_REPLY_NACK (0x1 << 6) | ||
42 | #define AUX_I2C_REPLY_DEFER (0x2 << 6) | ||
43 | #define AUX_I2C_REPLY_MASK (0x3 << 6) | ||
44 | |||
45 | /* AUX CH addresses */ | ||
46 | #define DP_LINK_BW_SET 0x100 | ||
47 | # define DP_LINK_BW_1_62 0x06 | ||
48 | # define DP_LINK_BW_2_7 0x0a | ||
49 | |||
50 | #define DP_LANE_COUNT_SET 0x101 | ||
51 | # define DP_LANE_COUNT_MASK 0x0f | ||
52 | # define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7) | ||
53 | |||
54 | #define DP_TRAINING_PATTERN_SET 0x102 | ||
55 | |||
56 | # define DP_TRAINING_PATTERN_DISABLE 0 | ||
57 | # define DP_TRAINING_PATTERN_1 1 | ||
58 | # define DP_TRAINING_PATTERN_2 2 | ||
59 | # define DP_TRAINING_PATTERN_MASK 0x3 | ||
60 | |||
61 | # define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2) | ||
62 | # define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2) | ||
63 | # define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2) | ||
64 | # define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2) | ||
65 | # define DP_LINK_QUAL_PATTERN_MASK (3 << 2) | ||
66 | |||
67 | # define DP_RECOVERED_CLOCK_OUT_EN (1 << 4) | ||
68 | # define DP_LINK_SCRAMBLING_DISABLE (1 << 5) | ||
69 | |||
70 | # define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6) | ||
71 | # define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6) | ||
72 | # define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6) | ||
73 | # define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6) | ||
74 | |||
75 | #define DP_TRAINING_LANE0_SET 0x103 | ||
76 | #define DP_TRAINING_LANE1_SET 0x104 | ||
77 | #define DP_TRAINING_LANE2_SET 0x105 | ||
78 | #define DP_TRAINING_LANE3_SET 0x106 | ||
79 | |||
80 | # define DP_TRAIN_VOLTAGE_SWING_MASK 0x3 | ||
81 | # define DP_TRAIN_VOLTAGE_SWING_SHIFT 0 | ||
82 | # define DP_TRAIN_MAX_SWING_REACHED (1 << 2) | ||
83 | # define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0) | ||
84 | # define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0) | ||
85 | # define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0) | ||
86 | # define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0) | ||
87 | |||
88 | # define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3) | ||
89 | # define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3) | ||
90 | # define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3) | ||
91 | # define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3) | ||
92 | # define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3) | ||
93 | |||
94 | # define DP_TRAIN_PRE_EMPHASIS_SHIFT 3 | ||
95 | # define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5) | ||
96 | |||
97 | #define DP_DOWNSPREAD_CTRL 0x107 | ||
98 | # define DP_SPREAD_AMP_0_5 (1 << 4) | ||
99 | |||
100 | #define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108 | ||
101 | # define DP_SET_ANSI_8B10B (1 << 0) | ||
102 | |||
103 | #define DP_LANE0_1_STATUS 0x202 | ||
104 | #define DP_LANE2_3_STATUS 0x203 | ||
105 | |||
106 | # define DP_LANE_CR_DONE (1 << 0) | ||
107 | # define DP_LANE_CHANNEL_EQ_DONE (1 << 1) | ||
108 | # define DP_LANE_SYMBOL_LOCKED (1 << 2) | ||
109 | |||
110 | #define DP_LANE_ALIGN_STATUS_UPDATED 0x204 | ||
111 | |||
112 | #define DP_INTERLANE_ALIGN_DONE (1 << 0) | ||
113 | #define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6) | ||
114 | #define DP_LINK_STATUS_UPDATED (1 << 7) | ||
115 | |||
116 | #define DP_SINK_STATUS 0x205 | ||
117 | |||
118 | #define DP_RECEIVE_PORT_0_STATUS (1 << 0) | ||
119 | #define DP_RECEIVE_PORT_1_STATUS (1 << 1) | ||
120 | |||
121 | #define DP_ADJUST_REQUEST_LANE0_1 0x206 | ||
122 | #define DP_ADJUST_REQUEST_LANE2_3 0x207 | ||
123 | |||
124 | #define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03 | ||
125 | #define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0 | ||
126 | #define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c | ||
127 | #define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2 | ||
128 | #define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30 | ||
129 | #define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4 | ||
130 | #define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 | ||
131 | #define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 | ||
132 | |||
133 | struct i2c_algo_dp_aux_data { | ||
134 | bool running; | ||
135 | u16 address; | ||
136 | int (*aux_ch) (struct i2c_adapter *adapter, | ||
137 | uint8_t *send, int send_bytes, | ||
138 | uint8_t *recv, int recv_bytes); | ||
139 | }; | ||
140 | |||
141 | int | ||
142 | i2c_dp_aux_add_bus(struct i2c_adapter *adapter); | ||
143 | |||
144 | #endif /* _INTEL_DP_H_ */ | ||
diff --git a/drivers/gpu/drm/i915/intel_dp_i2c.c b/drivers/gpu/drm/i915/intel_dp_i2c.c new file mode 100644 index 000000000000..4e60f14b1a6d --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp_i2c.c | |||
@@ -0,0 +1,272 @@ | |||
1 | /* | ||
2 | * Copyright © 2009 Keith Packard | ||
3 | * | ||
4 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
5 | * documentation for any purpose is hereby granted without fee, provided that | ||
6 | * the above copyright notice appear in all copies and that both that copyright | ||
7 | * notice and this permission notice appear in supporting documentation, and | ||
8 | * that the name of the copyright holders not be used in advertising or | ||
9 | * publicity pertaining to distribution of the software without specific, | ||
10 | * written prior permission. The copyright holders make no representations | ||
11 | * about the suitability of this software for any purpose. It is provided "as | ||
12 | * is" without express or implied warranty. | ||
13 | * | ||
14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
20 | * OF THIS SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/i2c.h> | ||
31 | #include "intel_dp.h" | ||
32 | |||
33 | /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ | ||
34 | |||
35 | #define MODE_I2C_START 1 | ||
36 | #define MODE_I2C_WRITE 2 | ||
37 | #define MODE_I2C_READ 4 | ||
38 | #define MODE_I2C_STOP 8 | ||
39 | |||
40 | static int | ||
41 | i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, | ||
42 | uint8_t write_byte, uint8_t *read_byte) | ||
43 | { | ||
44 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
45 | uint16_t address = algo_data->address; | ||
46 | uint8_t msg[5]; | ||
47 | uint8_t reply[2]; | ||
48 | int msg_bytes; | ||
49 | int reply_bytes; | ||
50 | int ret; | ||
51 | |||
52 | /* Set up the command byte */ | ||
53 | if (mode & MODE_I2C_READ) | ||
54 | msg[0] = AUX_I2C_READ << 4; | ||
55 | else | ||
56 | msg[0] = AUX_I2C_WRITE << 4; | ||
57 | |||
58 | if (!(mode & MODE_I2C_STOP)) | ||
59 | msg[0] |= AUX_I2C_MOT << 4; | ||
60 | |||
61 | msg[1] = address >> 8; | ||
62 | msg[2] = address; | ||
63 | |||
64 | switch (mode) { | ||
65 | case MODE_I2C_WRITE: | ||
66 | msg[3] = 0; | ||
67 | msg[4] = write_byte; | ||
68 | msg_bytes = 5; | ||
69 | reply_bytes = 1; | ||
70 | break; | ||
71 | case MODE_I2C_READ: | ||
72 | msg[3] = 0; | ||
73 | msg_bytes = 4; | ||
74 | reply_bytes = 2; | ||
75 | break; | ||
76 | default: | ||
77 | msg_bytes = 3; | ||
78 | reply_bytes = 1; | ||
79 | break; | ||
80 | } | ||
81 | |||
82 | for (;;) { | ||
83 | ret = (*algo_data->aux_ch)(adapter, | ||
84 | msg, msg_bytes, | ||
85 | reply, reply_bytes); | ||
86 | if (ret < 0) { | ||
87 | printk(KERN_ERR "aux_ch failed %d\n", ret); | ||
88 | return ret; | ||
89 | } | ||
90 | switch (reply[0] & AUX_I2C_REPLY_MASK) { | ||
91 | case AUX_I2C_REPLY_ACK: | ||
92 | if (mode == MODE_I2C_READ) { | ||
93 | *read_byte = reply[1]; | ||
94 | } | ||
95 | return reply_bytes - 1; | ||
96 | case AUX_I2C_REPLY_NACK: | ||
97 | printk(KERN_ERR "aux_ch nack\n"); | ||
98 | return -EREMOTEIO; | ||
99 | case AUX_I2C_REPLY_DEFER: | ||
100 | printk(KERN_ERR "aux_ch defer\n"); | ||
101 | udelay(100); | ||
102 | break; | ||
103 | default: | ||
104 | printk(KERN_ERR "aux_ch invalid reply 0x%02x\n", reply[0]); | ||
105 | return -EREMOTEIO; | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | * I2C over AUX CH | ||
112 | */ | ||
113 | |||
114 | /* | ||
115 | * Send the address. If the I2C link is running, this 'restarts' | ||
116 | * the connection with the new address, this is used for doing | ||
117 | * a write followed by a read (as needed for DDC) | ||
118 | */ | ||
119 | static int | ||
120 | i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading) | ||
121 | { | ||
122 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
123 | int mode = MODE_I2C_START; | ||
124 | int ret; | ||
125 | |||
126 | if (reading) | ||
127 | mode |= MODE_I2C_READ; | ||
128 | else | ||
129 | mode |= MODE_I2C_WRITE; | ||
130 | algo_data->address = address; | ||
131 | algo_data->running = true; | ||
132 | ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); | ||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * Stop the I2C transaction. This closes out the link, sending | ||
138 | * a bare address packet with the MOT bit turned off | ||
139 | */ | ||
140 | static void | ||
141 | i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading) | ||
142 | { | ||
143 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
144 | int mode = MODE_I2C_STOP; | ||
145 | |||
146 | if (reading) | ||
147 | mode |= MODE_I2C_READ; | ||
148 | else | ||
149 | mode |= MODE_I2C_WRITE; | ||
150 | if (algo_data->running) { | ||
151 | (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); | ||
152 | algo_data->running = false; | ||
153 | } | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | * Write a single byte to the current I2C address, the | ||
158 | * the I2C link must be running or this returns -EIO | ||
159 | */ | ||
160 | static int | ||
161 | i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte) | ||
162 | { | ||
163 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
164 | int ret; | ||
165 | |||
166 | if (!algo_data->running) | ||
167 | return -EIO; | ||
168 | |||
169 | ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL); | ||
170 | return ret; | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * Read a single byte from the current I2C address, the | ||
175 | * I2C link must be running or this returns -EIO | ||
176 | */ | ||
177 | static int | ||
178 | i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret) | ||
179 | { | ||
180 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
181 | int ret; | ||
182 | |||
183 | if (!algo_data->running) | ||
184 | return -EIO; | ||
185 | |||
186 | ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret); | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | static int | ||
191 | i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter, | ||
192 | struct i2c_msg *msgs, | ||
193 | int num) | ||
194 | { | ||
195 | int ret = 0; | ||
196 | bool reading = false; | ||
197 | int m; | ||
198 | int b; | ||
199 | |||
200 | for (m = 0; m < num; m++) { | ||
201 | u16 len = msgs[m].len; | ||
202 | u8 *buf = msgs[m].buf; | ||
203 | reading = (msgs[m].flags & I2C_M_RD) != 0; | ||
204 | ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading); | ||
205 | if (ret < 0) | ||
206 | break; | ||
207 | if (reading) { | ||
208 | for (b = 0; b < len; b++) { | ||
209 | ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]); | ||
210 | if (ret < 0) | ||
211 | break; | ||
212 | } | ||
213 | } else { | ||
214 | for (b = 0; b < len; b++) { | ||
215 | ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]); | ||
216 | if (ret < 0) | ||
217 | break; | ||
218 | } | ||
219 | } | ||
220 | if (ret < 0) | ||
221 | break; | ||
222 | } | ||
223 | if (ret >= 0) | ||
224 | ret = num; | ||
225 | i2c_algo_dp_aux_stop(adapter, reading); | ||
226 | printk(KERN_ERR "dp_aux_xfer return %d\n", ret); | ||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | static u32 | ||
231 | i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter) | ||
232 | { | ||
233 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | | ||
234 | I2C_FUNC_SMBUS_READ_BLOCK_DATA | | ||
235 | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | | ||
236 | I2C_FUNC_10BIT_ADDR; | ||
237 | } | ||
238 | |||
239 | static const struct i2c_algorithm i2c_dp_aux_algo = { | ||
240 | .master_xfer = i2c_algo_dp_aux_xfer, | ||
241 | .functionality = i2c_algo_dp_aux_functionality, | ||
242 | }; | ||
243 | |||
244 | static void | ||
245 | i2c_dp_aux_reset_bus(struct i2c_adapter *adapter) | ||
246 | { | ||
247 | (void) i2c_algo_dp_aux_address(adapter, 0, false); | ||
248 | (void) i2c_algo_dp_aux_stop(adapter, false); | ||
249 | |||
250 | } | ||
251 | |||
252 | static int | ||
253 | i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter) | ||
254 | { | ||
255 | adapter->algo = &i2c_dp_aux_algo; | ||
256 | adapter->retries = 3; | ||
257 | i2c_dp_aux_reset_bus(adapter); | ||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | int | ||
262 | i2c_dp_aux_add_bus(struct i2c_adapter *adapter) | ||
263 | { | ||
264 | int error; | ||
265 | |||
266 | error = i2c_dp_aux_prepare_bus(adapter); | ||
267 | if (error) | ||
268 | return error; | ||
269 | error = i2c_add_adapter(adapter); | ||
270 | return error; | ||
271 | } | ||
272 | EXPORT_SYMBOL(i2c_dp_aux_add_bus); | ||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index cd4b9c5f715e..004541c935a8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -54,6 +54,7 @@ | |||
54 | #define INTEL_OUTPUT_LVDS 4 | 54 | #define INTEL_OUTPUT_LVDS 4 |
55 | #define INTEL_OUTPUT_TVOUT 5 | 55 | #define INTEL_OUTPUT_TVOUT 5 |
56 | #define INTEL_OUTPUT_HDMI 6 | 56 | #define INTEL_OUTPUT_HDMI 6 |
57 | #define INTEL_OUTPUT_DISPLAYPORT 7 | ||
57 | 58 | ||
58 | #define INTEL_DVO_CHIP_NONE 0 | 59 | #define INTEL_DVO_CHIP_NONE 0 |
59 | #define INTEL_DVO_CHIP_LVDS 1 | 60 | #define INTEL_DVO_CHIP_LVDS 1 |
@@ -65,7 +66,6 @@ struct intel_i2c_chan { | |||
65 | u32 reg; /* GPIO reg */ | 66 | u32 reg; /* GPIO reg */ |
66 | struct i2c_adapter adapter; | 67 | struct i2c_adapter adapter; |
67 | struct i2c_algo_bit_data algo; | 68 | struct i2c_algo_bit_data algo; |
68 | u8 slave_addr; | ||
69 | }; | 69 | }; |
70 | 70 | ||
71 | struct intel_framebuffer { | 71 | struct intel_framebuffer { |
@@ -79,11 +79,12 @@ struct intel_output { | |||
79 | 79 | ||
80 | struct drm_encoder enc; | 80 | struct drm_encoder enc; |
81 | int type; | 81 | int type; |
82 | struct intel_i2c_chan *i2c_bus; /* for control functions */ | 82 | struct i2c_adapter *i2c_bus; |
83 | struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */ | 83 | struct i2c_adapter *ddc_bus; |
84 | bool load_detect_temp; | 84 | bool load_detect_temp; |
85 | bool needs_tv_clock; | 85 | bool needs_tv_clock; |
86 | void *dev_priv; | 86 | void *dev_priv; |
87 | void (*hot_plug)(struct intel_output *); | ||
87 | }; | 88 | }; |
88 | 89 | ||
89 | struct intel_crtc { | 90 | struct intel_crtc { |
@@ -104,9 +105,9 @@ struct intel_crtc { | |||
104 | #define enc_to_intel_output(x) container_of(x, struct intel_output, enc) | 105 | #define enc_to_intel_output(x) container_of(x, struct intel_output, enc) |
105 | #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) | 106 | #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) |
106 | 107 | ||
107 | struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, | 108 | struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, |
108 | const char *name); | 109 | const char *name); |
109 | void intel_i2c_destroy(struct intel_i2c_chan *chan); | 110 | void intel_i2c_destroy(struct i2c_adapter *adapter); |
110 | int intel_ddc_get_modes(struct intel_output *intel_output); | 111 | int intel_ddc_get_modes(struct intel_output *intel_output); |
111 | extern bool intel_ddc_probe(struct intel_output *intel_output); | 112 | extern bool intel_ddc_probe(struct intel_output *intel_output); |
112 | void intel_i2c_quirk_set(struct drm_device *dev, bool enable); | 113 | void intel_i2c_quirk_set(struct drm_device *dev, bool enable); |
@@ -116,6 +117,10 @@ extern bool intel_sdvo_init(struct drm_device *dev, int output_device); | |||
116 | extern void intel_dvo_init(struct drm_device *dev); | 117 | extern void intel_dvo_init(struct drm_device *dev); |
117 | extern void intel_tv_init(struct drm_device *dev); | 118 | extern void intel_tv_init(struct drm_device *dev); |
118 | extern void intel_lvds_init(struct drm_device *dev); | 119 | extern void intel_lvds_init(struct drm_device *dev); |
120 | extern void intel_dp_init(struct drm_device *dev, int dp_reg); | ||
121 | void | ||
122 | intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | ||
123 | struct drm_display_mode *adjusted_mode); | ||
119 | 124 | ||
120 | extern void intel_crtc_load_lut(struct drm_crtc *crtc); | 125 | extern void intel_crtc_load_lut(struct drm_crtc *crtc); |
121 | extern void intel_encoder_prepare (struct drm_encoder *encoder); | 126 | extern void intel_encoder_prepare (struct drm_encoder *encoder); |
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 1ee3007d6ec0..13bff20930e8 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c | |||
@@ -384,10 +384,9 @@ void intel_dvo_init(struct drm_device *dev) | |||
384 | { | 384 | { |
385 | struct intel_output *intel_output; | 385 | struct intel_output *intel_output; |
386 | struct intel_dvo_device *dvo; | 386 | struct intel_dvo_device *dvo; |
387 | struct intel_i2c_chan *i2cbus = NULL; | 387 | struct i2c_adapter *i2cbus = NULL; |
388 | int ret = 0; | 388 | int ret = 0; |
389 | int i; | 389 | int i; |
390 | int gpio_inited = 0; | ||
391 | int encoder_type = DRM_MODE_ENCODER_NONE; | 390 | int encoder_type = DRM_MODE_ENCODER_NONE; |
392 | intel_output = kzalloc (sizeof(struct intel_output), GFP_KERNEL); | 391 | intel_output = kzalloc (sizeof(struct intel_output), GFP_KERNEL); |
393 | if (!intel_output) | 392 | if (!intel_output) |
@@ -420,14 +419,11 @@ void intel_dvo_init(struct drm_device *dev) | |||
420 | * It appears that everything is on GPIOE except for panels | 419 | * It appears that everything is on GPIOE except for panels |
421 | * on i830 laptops, which are on GPIOB (DVOA). | 420 | * on i830 laptops, which are on GPIOB (DVOA). |
422 | */ | 421 | */ |
423 | if (gpio_inited != gpio) { | 422 | if (i2cbus != NULL) |
424 | if (i2cbus != NULL) | 423 | intel_i2c_destroy(i2cbus); |
425 | intel_i2c_destroy(i2cbus); | 424 | if (!(i2cbus = intel_i2c_create(dev, gpio, |
426 | if (!(i2cbus = intel_i2c_create(dev, gpio, | 425 | gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) { |
427 | gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) { | 426 | continue; |
428 | continue; | ||
429 | } | ||
430 | gpio_inited = gpio; | ||
431 | } | 427 | } |
432 | 428 | ||
433 | if (dvo->dev_ops!= NULL) | 429 | if (dvo->dev_ops!= NULL) |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4ea2a651b92c..9e30daae37dc 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "drmP.h" | 31 | #include "drmP.h" |
32 | #include "drm.h" | 32 | #include "drm.h" |
33 | #include "drm_crtc.h" | 33 | #include "drm_crtc.h" |
34 | #include "drm_edid.h" | ||
34 | #include "intel_drv.h" | 35 | #include "intel_drv.h" |
35 | #include "i915_drm.h" | 36 | #include "i915_drm.h" |
36 | #include "i915_drv.h" | 37 | #include "i915_drv.h" |
@@ -56,8 +57,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, | |||
56 | sdvox = SDVO_ENCODING_HDMI | | 57 | sdvox = SDVO_ENCODING_HDMI | |
57 | SDVO_BORDER_ENABLE | | 58 | SDVO_BORDER_ENABLE | |
58 | SDVO_VSYNC_ACTIVE_HIGH | | 59 | SDVO_VSYNC_ACTIVE_HIGH | |
59 | SDVO_HSYNC_ACTIVE_HIGH | | 60 | SDVO_HSYNC_ACTIVE_HIGH; |
60 | SDVO_NULL_PACKETS_DURING_VSYNC; | ||
61 | 61 | ||
62 | if (hdmi_priv->has_hdmi_sink) | 62 | if (hdmi_priv->has_hdmi_sink) |
63 | sdvox |= SDVO_AUDIO_ENABLE; | 63 | sdvox |= SDVO_AUDIO_ENABLE; |
@@ -129,20 +129,26 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | |||
129 | return true; | 129 | return true; |
130 | } | 130 | } |
131 | 131 | ||
132 | static void | 132 | static enum drm_connector_status |
133 | intel_hdmi_sink_detect(struct drm_connector *connector) | 133 | intel_hdmi_edid_detect(struct drm_connector *connector) |
134 | { | 134 | { |
135 | struct intel_output *intel_output = to_intel_output(connector); | 135 | struct intel_output *intel_output = to_intel_output(connector); |
136 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | 136 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; |
137 | struct edid *edid = NULL; | 137 | struct edid *edid = NULL; |
138 | enum drm_connector_status status = connector_status_disconnected; | ||
138 | 139 | ||
139 | edid = drm_get_edid(&intel_output->base, | 140 | edid = drm_get_edid(&intel_output->base, |
140 | &intel_output->ddc_bus->adapter); | 141 | intel_output->ddc_bus); |
141 | if (edid != NULL) { | 142 | hdmi_priv->has_hdmi_sink = false; |
142 | hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); | 143 | if (edid) { |
143 | kfree(edid); | 144 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
145 | status = connector_status_connected; | ||
146 | hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); | ||
147 | } | ||
144 | intel_output->base.display_info.raw_edid = NULL; | 148 | intel_output->base.display_info.raw_edid = NULL; |
149 | kfree(edid); | ||
145 | } | 150 | } |
151 | return status; | ||
146 | } | 152 | } |
147 | 153 | ||
148 | static enum drm_connector_status | 154 | static enum drm_connector_status |
@@ -154,11 +160,7 @@ igdng_hdmi_detect(struct drm_connector *connector) | |||
154 | /* FIXME hotplug detect */ | 160 | /* FIXME hotplug detect */ |
155 | 161 | ||
156 | hdmi_priv->has_hdmi_sink = false; | 162 | hdmi_priv->has_hdmi_sink = false; |
157 | intel_hdmi_sink_detect(connector); | 163 | return intel_hdmi_edid_detect(connector); |
158 | if (hdmi_priv->has_hdmi_sink) | ||
159 | return connector_status_connected; | ||
160 | else | ||
161 | return connector_status_disconnected; | ||
162 | } | 164 | } |
163 | 165 | ||
164 | static enum drm_connector_status | 166 | static enum drm_connector_status |
@@ -201,10 +203,9 @@ intel_hdmi_detect(struct drm_connector *connector) | |||
201 | return connector_status_unknown; | 203 | return connector_status_unknown; |
202 | } | 204 | } |
203 | 205 | ||
204 | if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) { | 206 | if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) |
205 | intel_hdmi_sink_detect(connector); | 207 | return intel_hdmi_edid_detect(connector); |
206 | return connector_status_connected; | 208 | else |
207 | } else | ||
208 | return connector_status_disconnected; | 209 | return connector_status_disconnected; |
209 | } | 210 | } |
210 | 211 | ||
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index f7061f68d050..62b8bead7652 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c | |||
@@ -124,6 +124,7 @@ static void set_data(void *data, int state_high) | |||
124 | * @output: driver specific output device | 124 | * @output: driver specific output device |
125 | * @reg: GPIO reg to use | 125 | * @reg: GPIO reg to use |
126 | * @name: name for this bus | 126 | * @name: name for this bus |
127 | * @slave_addr: slave address (if fixed) | ||
127 | * | 128 | * |
128 | * Creates and registers a new i2c bus with the Linux i2c layer, for use | 129 | * Creates and registers a new i2c bus with the Linux i2c layer, for use |
129 | * in output probing and control (e.g. DDC or SDVO control functions). | 130 | * in output probing and control (e.g. DDC or SDVO control functions). |
@@ -139,8 +140,8 @@ static void set_data(void *data, int state_high) | |||
139 | * %GPIOH | 140 | * %GPIOH |
140 | * see PRM for details on how these different busses are used. | 141 | * see PRM for details on how these different busses are used. |
141 | */ | 142 | */ |
142 | struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, | 143 | struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, |
143 | const char *name) | 144 | const char *name) |
144 | { | 145 | { |
145 | struct intel_i2c_chan *chan; | 146 | struct intel_i2c_chan *chan; |
146 | 147 | ||
@@ -174,7 +175,7 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, | |||
174 | intel_i2c_quirk_set(dev, false); | 175 | intel_i2c_quirk_set(dev, false); |
175 | udelay(20); | 176 | udelay(20); |
176 | 177 | ||
177 | return chan; | 178 | return &chan->adapter; |
178 | 179 | ||
179 | out_free: | 180 | out_free: |
180 | kfree(chan); | 181 | kfree(chan); |
@@ -187,11 +188,16 @@ out_free: | |||
187 | * | 188 | * |
188 | * Unregister the adapter from the i2c layer, then free the structure. | 189 | * Unregister the adapter from the i2c layer, then free the structure. |
189 | */ | 190 | */ |
190 | void intel_i2c_destroy(struct intel_i2c_chan *chan) | 191 | void intel_i2c_destroy(struct i2c_adapter *adapter) |
191 | { | 192 | { |
192 | if (!chan) | 193 | struct intel_i2c_chan *chan; |
194 | |||
195 | if (!adapter) | ||
193 | return; | 196 | return; |
194 | 197 | ||
198 | chan = container_of(adapter, | ||
199 | struct intel_i2c_chan, | ||
200 | adapter); | ||
195 | i2c_del_adapter(&chan->adapter); | 201 | i2c_del_adapter(&chan->adapter); |
196 | kfree(chan); | 202 | kfree(chan); |
197 | } | 203 | } |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index f073ed8432e8..9564ca44a977 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -39,6 +39,21 @@ | |||
39 | 39 | ||
40 | #define I915_LVDS "i915_lvds" | 40 | #define I915_LVDS "i915_lvds" |
41 | 41 | ||
42 | /* | ||
43 | * the following four scaling options are defined. | ||
44 | * #define DRM_MODE_SCALE_NON_GPU 0 | ||
45 | * #define DRM_MODE_SCALE_FULLSCREEN 1 | ||
46 | * #define DRM_MODE_SCALE_NO_SCALE 2 | ||
47 | * #define DRM_MODE_SCALE_ASPECT 3 | ||
48 | */ | ||
49 | |||
50 | /* Private structure for the integrated LVDS support */ | ||
51 | struct intel_lvds_priv { | ||
52 | int fitting_mode; | ||
53 | u32 pfit_control; | ||
54 | u32 pfit_pgm_ratios; | ||
55 | }; | ||
56 | |||
42 | /** | 57 | /** |
43 | * Sets the backlight level. | 58 | * Sets the backlight level. |
44 | * | 59 | * |
@@ -213,10 +228,27 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
213 | struct drm_display_mode *mode, | 228 | struct drm_display_mode *mode, |
214 | struct drm_display_mode *adjusted_mode) | 229 | struct drm_display_mode *adjusted_mode) |
215 | { | 230 | { |
231 | /* | ||
232 | * float point operation is not supported . So the PANEL_RATIO_FACTOR | ||
233 | * is defined, which can avoid the float point computation when | ||
234 | * calculating the panel ratio. | ||
235 | */ | ||
236 | #define PANEL_RATIO_FACTOR 8192 | ||
216 | struct drm_device *dev = encoder->dev; | 237 | struct drm_device *dev = encoder->dev; |
217 | struct drm_i915_private *dev_priv = dev->dev_private; | 238 | struct drm_i915_private *dev_priv = dev->dev_private; |
218 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 239 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
219 | struct drm_encoder *tmp_encoder; | 240 | struct drm_encoder *tmp_encoder; |
241 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
242 | struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; | ||
243 | u32 pfit_control = 0, pfit_pgm_ratios = 0; | ||
244 | int left_border = 0, right_border = 0, top_border = 0; | ||
245 | int bottom_border = 0; | ||
246 | bool border = 0; | ||
247 | int panel_ratio, desired_ratio, vert_scale, horiz_scale; | ||
248 | int horiz_ratio, vert_ratio; | ||
249 | u32 hsync_width, vsync_width; | ||
250 | u32 hblank_width, vblank_width; | ||
251 | u32 hsync_pos, vsync_pos; | ||
220 | 252 | ||
221 | /* Should never happen!! */ | 253 | /* Should never happen!! */ |
222 | if (!IS_I965G(dev) && intel_crtc->pipe == 0) { | 254 | if (!IS_I965G(dev) && intel_crtc->pipe == 0) { |
@@ -232,7 +264,9 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
232 | return false; | 264 | return false; |
233 | } | 265 | } |
234 | } | 266 | } |
235 | 267 | /* If we don't have a panel mode, there is nothing we can do */ | |
268 | if (dev_priv->panel_fixed_mode == NULL) | ||
269 | return true; | ||
236 | /* | 270 | /* |
237 | * If we have timings from the BIOS for the panel, put them in | 271 | * If we have timings from the BIOS for the panel, put them in |
238 | * to the adjusted mode. The CRTC will be set up for this mode, | 272 | * to the adjusted mode. The CRTC will be set up for this mode, |
@@ -256,6 +290,243 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
256 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); | 290 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); |
257 | } | 291 | } |
258 | 292 | ||
293 | /* Make sure pre-965s set dither correctly */ | ||
294 | if (!IS_I965G(dev)) { | ||
295 | if (dev_priv->panel_wants_dither || dev_priv->lvds_dither) | ||
296 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; | ||
297 | } | ||
298 | |||
299 | /* Native modes don't need fitting */ | ||
300 | if (adjusted_mode->hdisplay == mode->hdisplay && | ||
301 | adjusted_mode->vdisplay == mode->vdisplay) { | ||
302 | pfit_pgm_ratios = 0; | ||
303 | border = 0; | ||
304 | goto out; | ||
305 | } | ||
306 | |||
307 | /* 965+ wants fuzzy fitting */ | ||
308 | if (IS_I965G(dev)) | ||
309 | pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) | | ||
310 | PFIT_FILTER_FUZZY; | ||
311 | |||
312 | hsync_width = adjusted_mode->crtc_hsync_end - | ||
313 | adjusted_mode->crtc_hsync_start; | ||
314 | vsync_width = adjusted_mode->crtc_vsync_end - | ||
315 | adjusted_mode->crtc_vsync_start; | ||
316 | hblank_width = adjusted_mode->crtc_hblank_end - | ||
317 | adjusted_mode->crtc_hblank_start; | ||
318 | vblank_width = adjusted_mode->crtc_vblank_end - | ||
319 | adjusted_mode->crtc_vblank_start; | ||
320 | /* | ||
321 | * Deal with panel fitting options. Figure out how to stretch the | ||
322 | * image based on its aspect ratio & the current panel fitting mode. | ||
323 | */ | ||
324 | panel_ratio = adjusted_mode->hdisplay * PANEL_RATIO_FACTOR / | ||
325 | adjusted_mode->vdisplay; | ||
326 | desired_ratio = mode->hdisplay * PANEL_RATIO_FACTOR / | ||
327 | mode->vdisplay; | ||
328 | /* | ||
329 | * Enable automatic panel scaling for non-native modes so that they fill | ||
330 | * the screen. Should be enabled before the pipe is enabled, according | ||
331 | * to register description and PRM. | ||
332 | * Change the value here to see the borders for debugging | ||
333 | */ | ||
334 | I915_WRITE(BCLRPAT_A, 0); | ||
335 | I915_WRITE(BCLRPAT_B, 0); | ||
336 | |||
337 | switch (lvds_priv->fitting_mode) { | ||
338 | case DRM_MODE_SCALE_NO_SCALE: | ||
339 | /* | ||
340 | * For centered modes, we have to calculate border widths & | ||
341 | * heights and modify the values programmed into the CRTC. | ||
342 | */ | ||
343 | left_border = (adjusted_mode->hdisplay - mode->hdisplay) / 2; | ||
344 | right_border = left_border; | ||
345 | if (mode->hdisplay & 1) | ||
346 | right_border++; | ||
347 | top_border = (adjusted_mode->vdisplay - mode->vdisplay) / 2; | ||
348 | bottom_border = top_border; | ||
349 | if (mode->vdisplay & 1) | ||
350 | bottom_border++; | ||
351 | /* Set active & border values */ | ||
352 | adjusted_mode->crtc_hdisplay = mode->hdisplay; | ||
353 | /* Keep the boder be even */ | ||
354 | if (right_border & 1) | ||
355 | right_border++; | ||
356 | /* use the border directly instead of border minuse one */ | ||
357 | adjusted_mode->crtc_hblank_start = mode->hdisplay + | ||
358 | right_border; | ||
359 | /* keep the blank width constant */ | ||
360 | adjusted_mode->crtc_hblank_end = | ||
361 | adjusted_mode->crtc_hblank_start + hblank_width; | ||
362 | /* get the hsync pos relative to hblank start */ | ||
363 | hsync_pos = (hblank_width - hsync_width) / 2; | ||
364 | /* keep the hsync pos be even */ | ||
365 | if (hsync_pos & 1) | ||
366 | hsync_pos++; | ||
367 | adjusted_mode->crtc_hsync_start = | ||
368 | adjusted_mode->crtc_hblank_start + hsync_pos; | ||
369 | /* keep the hsync width constant */ | ||
370 | adjusted_mode->crtc_hsync_end = | ||
371 | adjusted_mode->crtc_hsync_start + hsync_width; | ||
372 | adjusted_mode->crtc_vdisplay = mode->vdisplay; | ||
373 | /* use the border instead of border minus one */ | ||
374 | adjusted_mode->crtc_vblank_start = mode->vdisplay + | ||
375 | bottom_border; | ||
376 | /* keep the vblank width constant */ | ||
377 | adjusted_mode->crtc_vblank_end = | ||
378 | adjusted_mode->crtc_vblank_start + vblank_width; | ||
379 | /* get the vsync start postion relative to vblank start */ | ||
380 | vsync_pos = (vblank_width - vsync_width) / 2; | ||
381 | adjusted_mode->crtc_vsync_start = | ||
382 | adjusted_mode->crtc_vblank_start + vsync_pos; | ||
383 | /* keep the vsync width constant */ | ||
384 | adjusted_mode->crtc_vsync_end = | ||
385 | adjusted_mode->crtc_vblank_start + vsync_width; | ||
386 | border = 1; | ||
387 | break; | ||
388 | case DRM_MODE_SCALE_ASPECT: | ||
389 | /* Scale but preserve the spect ratio */ | ||
390 | pfit_control |= PFIT_ENABLE; | ||
391 | if (IS_I965G(dev)) { | ||
392 | /* 965+ is easy, it does everything in hw */ | ||
393 | if (panel_ratio > desired_ratio) | ||
394 | pfit_control |= PFIT_SCALING_PILLAR; | ||
395 | else if (panel_ratio < desired_ratio) | ||
396 | pfit_control |= PFIT_SCALING_LETTER; | ||
397 | else | ||
398 | pfit_control |= PFIT_SCALING_AUTO; | ||
399 | } else { | ||
400 | /* | ||
401 | * For earlier chips we have to calculate the scaling | ||
402 | * ratio by hand and program it into the | ||
403 | * PFIT_PGM_RATIO register | ||
404 | */ | ||
405 | u32 horiz_bits, vert_bits, bits = 12; | ||
406 | horiz_ratio = mode->hdisplay * PANEL_RATIO_FACTOR/ | ||
407 | adjusted_mode->hdisplay; | ||
408 | vert_ratio = mode->vdisplay * PANEL_RATIO_FACTOR/ | ||
409 | adjusted_mode->vdisplay; | ||
410 | horiz_scale = adjusted_mode->hdisplay * | ||
411 | PANEL_RATIO_FACTOR / mode->hdisplay; | ||
412 | vert_scale = adjusted_mode->vdisplay * | ||
413 | PANEL_RATIO_FACTOR / mode->vdisplay; | ||
414 | |||
415 | /* retain aspect ratio */ | ||
416 | if (panel_ratio > desired_ratio) { /* Pillar */ | ||
417 | u32 scaled_width; | ||
418 | scaled_width = mode->hdisplay * vert_scale / | ||
419 | PANEL_RATIO_FACTOR; | ||
420 | horiz_ratio = vert_ratio; | ||
421 | pfit_control |= (VERT_AUTO_SCALE | | ||
422 | VERT_INTERP_BILINEAR | | ||
423 | HORIZ_INTERP_BILINEAR); | ||
424 | /* Pillar will have left/right borders */ | ||
425 | left_border = (adjusted_mode->hdisplay - | ||
426 | scaled_width) / 2; | ||
427 | right_border = left_border; | ||
428 | if (mode->hdisplay & 1) /* odd resolutions */ | ||
429 | right_border++; | ||
430 | /* keep the border be even */ | ||
431 | if (right_border & 1) | ||
432 | right_border++; | ||
433 | adjusted_mode->crtc_hdisplay = scaled_width; | ||
434 | /* use border instead of border minus one */ | ||
435 | adjusted_mode->crtc_hblank_start = | ||
436 | scaled_width + right_border; | ||
437 | /* keep the hblank width constant */ | ||
438 | adjusted_mode->crtc_hblank_end = | ||
439 | adjusted_mode->crtc_hblank_start + | ||
440 | hblank_width; | ||
441 | /* | ||
442 | * get the hsync start pos relative to | ||
443 | * hblank start | ||
444 | */ | ||
445 | hsync_pos = (hblank_width - hsync_width) / 2; | ||
446 | /* keep the hsync_pos be even */ | ||
447 | if (hsync_pos & 1) | ||
448 | hsync_pos++; | ||
449 | adjusted_mode->crtc_hsync_start = | ||
450 | adjusted_mode->crtc_hblank_start + | ||
451 | hsync_pos; | ||
452 | /* keept hsync width constant */ | ||
453 | adjusted_mode->crtc_hsync_end = | ||
454 | adjusted_mode->crtc_hsync_start + | ||
455 | hsync_width; | ||
456 | border = 1; | ||
457 | } else if (panel_ratio < desired_ratio) { /* letter */ | ||
458 | u32 scaled_height = mode->vdisplay * | ||
459 | horiz_scale / PANEL_RATIO_FACTOR; | ||
460 | vert_ratio = horiz_ratio; | ||
461 | pfit_control |= (HORIZ_AUTO_SCALE | | ||
462 | VERT_INTERP_BILINEAR | | ||
463 | HORIZ_INTERP_BILINEAR); | ||
464 | /* Letterbox will have top/bottom border */ | ||
465 | top_border = (adjusted_mode->vdisplay - | ||
466 | scaled_height) / 2; | ||
467 | bottom_border = top_border; | ||
468 | if (mode->vdisplay & 1) | ||
469 | bottom_border++; | ||
470 | adjusted_mode->crtc_vdisplay = scaled_height; | ||
471 | /* use border instead of border minus one */ | ||
472 | adjusted_mode->crtc_vblank_start = | ||
473 | scaled_height + bottom_border; | ||
474 | /* keep the vblank width constant */ | ||
475 | adjusted_mode->crtc_vblank_end = | ||
476 | adjusted_mode->crtc_vblank_start + | ||
477 | vblank_width; | ||
478 | /* | ||
479 | * get the vsync start pos relative to | ||
480 | * vblank start | ||
481 | */ | ||
482 | vsync_pos = (vblank_width - vsync_width) / 2; | ||
483 | adjusted_mode->crtc_vsync_start = | ||
484 | adjusted_mode->crtc_vblank_start + | ||
485 | vsync_pos; | ||
486 | /* keep the vsync width constant */ | ||
487 | adjusted_mode->crtc_vsync_end = | ||
488 | adjusted_mode->crtc_vsync_start + | ||
489 | vsync_width; | ||
490 | border = 1; | ||
491 | } else { | ||
492 | /* Aspects match, Let hw scale both directions */ | ||
493 | pfit_control |= (VERT_AUTO_SCALE | | ||
494 | HORIZ_AUTO_SCALE | | ||
495 | VERT_INTERP_BILINEAR | | ||
496 | HORIZ_INTERP_BILINEAR); | ||
497 | } | ||
498 | horiz_bits = (1 << bits) * horiz_ratio / | ||
499 | PANEL_RATIO_FACTOR; | ||
500 | vert_bits = (1 << bits) * vert_ratio / | ||
501 | PANEL_RATIO_FACTOR; | ||
502 | pfit_pgm_ratios = | ||
503 | ((vert_bits << PFIT_VERT_SCALE_SHIFT) & | ||
504 | PFIT_VERT_SCALE_MASK) | | ||
505 | ((horiz_bits << PFIT_HORIZ_SCALE_SHIFT) & | ||
506 | PFIT_HORIZ_SCALE_MASK); | ||
507 | } | ||
508 | break; | ||
509 | |||
510 | case DRM_MODE_SCALE_FULLSCREEN: | ||
511 | /* | ||
512 | * Full scaling, even if it changes the aspect ratio. | ||
513 | * Fortunately this is all done for us in hw. | ||
514 | */ | ||
515 | pfit_control |= PFIT_ENABLE; | ||
516 | if (IS_I965G(dev)) | ||
517 | pfit_control |= PFIT_SCALING_AUTO; | ||
518 | else | ||
519 | pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | | ||
520 | VERT_INTERP_BILINEAR | | ||
521 | HORIZ_INTERP_BILINEAR); | ||
522 | break; | ||
523 | default: | ||
524 | break; | ||
525 | } | ||
526 | |||
527 | out: | ||
528 | lvds_priv->pfit_control = pfit_control; | ||
529 | lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios; | ||
259 | /* | 530 | /* |
260 | * XXX: It would be nice to support lower refresh rates on the | 531 | * XXX: It would be nice to support lower refresh rates on the |
261 | * panels to reduce power consumption, and perhaps match the | 532 | * panels to reduce power consumption, and perhaps match the |
@@ -301,8 +572,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
301 | { | 572 | { |
302 | struct drm_device *dev = encoder->dev; | 573 | struct drm_device *dev = encoder->dev; |
303 | struct drm_i915_private *dev_priv = dev->dev_private; | 574 | struct drm_i915_private *dev_priv = dev->dev_private; |
304 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 575 | struct intel_output *intel_output = enc_to_intel_output(encoder); |
305 | u32 pfit_control; | 576 | struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; |
306 | 577 | ||
307 | /* | 578 | /* |
308 | * The LVDS pin pair will already have been turned on in the | 579 | * The LVDS pin pair will already have been turned on in the |
@@ -319,22 +590,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
319 | * screen. Should be enabled before the pipe is enabled, according to | 590 | * screen. Should be enabled before the pipe is enabled, according to |
320 | * register description and PRM. | 591 | * register description and PRM. |
321 | */ | 592 | */ |
322 | if (mode->hdisplay != adjusted_mode->hdisplay || | 593 | I915_WRITE(PFIT_PGM_RATIOS, lvds_priv->pfit_pgm_ratios); |
323 | mode->vdisplay != adjusted_mode->vdisplay) | 594 | I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control); |
324 | pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | | ||
325 | HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | | ||
326 | HORIZ_INTERP_BILINEAR); | ||
327 | else | ||
328 | pfit_control = 0; | ||
329 | |||
330 | if (!IS_I965G(dev)) { | ||
331 | if (dev_priv->panel_wants_dither || dev_priv->lvds_dither) | ||
332 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; | ||
333 | } | ||
334 | else | ||
335 | pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT; | ||
336 | |||
337 | I915_WRITE(PFIT_CONTROL, pfit_control); | ||
338 | } | 595 | } |
339 | 596 | ||
340 | /** | 597 | /** |
@@ -406,6 +663,34 @@ static int intel_lvds_set_property(struct drm_connector *connector, | |||
406 | struct drm_property *property, | 663 | struct drm_property *property, |
407 | uint64_t value) | 664 | uint64_t value) |
408 | { | 665 | { |
666 | struct drm_device *dev = connector->dev; | ||
667 | struct intel_output *intel_output = | ||
668 | to_intel_output(connector); | ||
669 | |||
670 | if (property == dev->mode_config.scaling_mode_property && | ||
671 | connector->encoder) { | ||
672 | struct drm_crtc *crtc = connector->encoder->crtc; | ||
673 | struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; | ||
674 | if (value == DRM_MODE_SCALE_NON_GPU) { | ||
675 | DRM_DEBUG_KMS(I915_LVDS, | ||
676 | "non_GPU property is unsupported\n"); | ||
677 | return 0; | ||
678 | } | ||
679 | if (lvds_priv->fitting_mode == value) { | ||
680 | /* the LVDS scaling property is not changed */ | ||
681 | return 0; | ||
682 | } | ||
683 | lvds_priv->fitting_mode = value; | ||
684 | if (crtc && crtc->enabled) { | ||
685 | /* | ||
686 | * If the CRTC is enabled, the display will be changed | ||
687 | * according to the new panel fitting mode. | ||
688 | */ | ||
689 | drm_crtc_helper_set_mode(crtc, &crtc->mode, | ||
690 | crtc->x, crtc->y, crtc->fb); | ||
691 | } | ||
692 | } | ||
693 | |||
409 | return 0; | 694 | return 0; |
410 | } | 695 | } |
411 | 696 | ||
@@ -456,7 +741,7 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
456 | .callback = intel_no_lvds_dmi_callback, | 741 | .callback = intel_no_lvds_dmi_callback, |
457 | .ident = "Apple Mac Mini (Core series)", | 742 | .ident = "Apple Mac Mini (Core series)", |
458 | .matches = { | 743 | .matches = { |
459 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 744 | DMI_MATCH(DMI_SYS_VENDOR, "Apple"), |
460 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), | 745 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), |
461 | }, | 746 | }, |
462 | }, | 747 | }, |
@@ -464,7 +749,7 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
464 | .callback = intel_no_lvds_dmi_callback, | 749 | .callback = intel_no_lvds_dmi_callback, |
465 | .ident = "Apple Mac Mini (Core 2 series)", | 750 | .ident = "Apple Mac Mini (Core 2 series)", |
466 | .matches = { | 751 | .matches = { |
467 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 752 | DMI_MATCH(DMI_SYS_VENDOR, "Apple"), |
468 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"), | 753 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"), |
469 | }, | 754 | }, |
470 | }, | 755 | }, |
@@ -518,6 +803,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
518 | struct drm_encoder *encoder; | 803 | struct drm_encoder *encoder; |
519 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ | 804 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ |
520 | struct drm_crtc *crtc; | 805 | struct drm_crtc *crtc; |
806 | struct intel_lvds_priv *lvds_priv; | ||
521 | u32 lvds; | 807 | u32 lvds; |
522 | int pipe, gpio = GPIOC; | 808 | int pipe, gpio = GPIOC; |
523 | 809 | ||
@@ -531,7 +817,8 @@ void intel_lvds_init(struct drm_device *dev) | |||
531 | gpio = PCH_GPIOC; | 817 | gpio = PCH_GPIOC; |
532 | } | 818 | } |
533 | 819 | ||
534 | intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); | 820 | intel_output = kzalloc(sizeof(struct intel_output) + |
821 | sizeof(struct intel_lvds_priv), GFP_KERNEL); | ||
535 | if (!intel_output) { | 822 | if (!intel_output) { |
536 | return; | 823 | return; |
537 | } | 824 | } |
@@ -553,7 +840,18 @@ void intel_lvds_init(struct drm_device *dev) | |||
553 | connector->interlace_allowed = false; | 840 | connector->interlace_allowed = false; |
554 | connector->doublescan_allowed = false; | 841 | connector->doublescan_allowed = false; |
555 | 842 | ||
843 | lvds_priv = (struct intel_lvds_priv *)(intel_output + 1); | ||
844 | intel_output->dev_priv = lvds_priv; | ||
845 | /* create the scaling mode property */ | ||
846 | drm_mode_create_scaling_mode_property(dev); | ||
847 | /* | ||
848 | * the initial panel fitting mode will be FULL_SCREEN. | ||
849 | */ | ||
556 | 850 | ||
851 | drm_connector_attach_property(&intel_output->base, | ||
852 | dev->mode_config.scaling_mode_property, | ||
853 | DRM_MODE_SCALE_FULLSCREEN); | ||
854 | lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN; | ||
557 | /* | 855 | /* |
558 | * LVDS discovery: | 856 | * LVDS discovery: |
559 | * 1) check for EDID on DDC | 857 | * 1) check for EDID on DDC |
@@ -649,5 +947,5 @@ failed: | |||
649 | if (intel_output->ddc_bus) | 947 | if (intel_output->ddc_bus) |
650 | intel_i2c_destroy(intel_output->ddc_bus); | 948 | intel_i2c_destroy(intel_output->ddc_bus); |
651 | drm_connector_cleanup(connector); | 949 | drm_connector_cleanup(connector); |
652 | kfree(connector); | 950 | kfree(intel_output); |
653 | } | 951 | } |
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index e0910fefce87..67e2f4632a24 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c | |||
@@ -53,10 +53,9 @@ bool intel_ddc_probe(struct intel_output *intel_output) | |||
53 | } | 53 | } |
54 | }; | 54 | }; |
55 | 55 | ||
56 | intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true); | 56 | intel_i2c_quirk_set(intel_output->base.dev, true); |
57 | ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2); | 57 | ret = i2c_transfer(intel_output->ddc_bus, msgs, 2); |
58 | intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false); | 58 | intel_i2c_quirk_set(intel_output->base.dev, false); |
59 | |||
60 | if (ret == 2) | 59 | if (ret == 2) |
61 | return true; | 60 | return true; |
62 | 61 | ||
@@ -74,10 +73,9 @@ int intel_ddc_get_modes(struct intel_output *intel_output) | |||
74 | struct edid *edid; | 73 | struct edid *edid; |
75 | int ret = 0; | 74 | int ret = 0; |
76 | 75 | ||
77 | intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true); | 76 | intel_i2c_quirk_set(intel_output->base.dev, true); |
78 | edid = drm_get_edid(&intel_output->base, | 77 | edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus); |
79 | &intel_output->ddc_bus->adapter); | 78 | intel_i2c_quirk_set(intel_output->base.dev, false); |
80 | intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false); | ||
81 | if (edid) { | 79 | if (edid) { |
82 | drm_mode_connector_update_edid_property(&intel_output->base, | 80 | drm_mode_connector_update_edid_property(&intel_output->base, |
83 | edid); | 81 | edid); |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 9a00adb3a508..f03473779feb 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -38,8 +38,7 @@ | |||
38 | #undef SDVO_DEBUG | 38 | #undef SDVO_DEBUG |
39 | #define I915_SDVO "i915_sdvo" | 39 | #define I915_SDVO "i915_sdvo" |
40 | struct intel_sdvo_priv { | 40 | struct intel_sdvo_priv { |
41 | struct intel_i2c_chan *i2c_bus; | 41 | u8 slave_addr; |
42 | int slaveaddr; | ||
43 | 42 | ||
44 | /* Register for the SDVO device: SDVOB or SDVOC */ | 43 | /* Register for the SDVO device: SDVOB or SDVOC */ |
45 | int output_device; | 44 | int output_device; |
@@ -146,13 +145,13 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, | |||
146 | 145 | ||
147 | struct i2c_msg msgs[] = { | 146 | struct i2c_msg msgs[] = { |
148 | { | 147 | { |
149 | .addr = sdvo_priv->i2c_bus->slave_addr, | 148 | .addr = sdvo_priv->slave_addr >> 1, |
150 | .flags = 0, | 149 | .flags = 0, |
151 | .len = 1, | 150 | .len = 1, |
152 | .buf = out_buf, | 151 | .buf = out_buf, |
153 | }, | 152 | }, |
154 | { | 153 | { |
155 | .addr = sdvo_priv->i2c_bus->slave_addr, | 154 | .addr = sdvo_priv->slave_addr >> 1, |
156 | .flags = I2C_M_RD, | 155 | .flags = I2C_M_RD, |
157 | .len = 1, | 156 | .len = 1, |
158 | .buf = buf, | 157 | .buf = buf, |
@@ -162,7 +161,7 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, | |||
162 | out_buf[0] = addr; | 161 | out_buf[0] = addr; |
163 | out_buf[1] = 0; | 162 | out_buf[1] = 0; |
164 | 163 | ||
165 | if ((ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2)) == 2) | 164 | if ((ret = i2c_transfer(intel_output->i2c_bus, msgs, 2)) == 2) |
166 | { | 165 | { |
167 | *ch = buf[0]; | 166 | *ch = buf[0]; |
168 | return true; | 167 | return true; |
@@ -175,10 +174,11 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, | |||
175 | static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, | 174 | static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, |
176 | u8 ch) | 175 | u8 ch) |
177 | { | 176 | { |
177 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
178 | u8 out_buf[2]; | 178 | u8 out_buf[2]; |
179 | struct i2c_msg msgs[] = { | 179 | struct i2c_msg msgs[] = { |
180 | { | 180 | { |
181 | .addr = intel_output->i2c_bus->slave_addr, | 181 | .addr = sdvo_priv->slave_addr >> 1, |
182 | .flags = 0, | 182 | .flags = 0, |
183 | .len = 2, | 183 | .len = 2, |
184 | .buf = out_buf, | 184 | .buf = out_buf, |
@@ -188,7 +188,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, | |||
188 | out_buf[0] = addr; | 188 | out_buf[0] = addr; |
189 | out_buf[1] = ch; | 189 | out_buf[1] = ch; |
190 | 190 | ||
191 | if (i2c_transfer(&intel_output->i2c_bus->adapter, msgs, 1) == 1) | 191 | if (i2c_transfer(intel_output->i2c_bus, msgs, 1) == 1) |
192 | { | 192 | { |
193 | return true; | 193 | return true; |
194 | } | 194 | } |
@@ -1369,9 +1369,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | |||
1369 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | 1369 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; |
1370 | struct edid *edid = NULL; | 1370 | struct edid *edid = NULL; |
1371 | 1371 | ||
1372 | intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); | ||
1373 | edid = drm_get_edid(&intel_output->base, | 1372 | edid = drm_get_edid(&intel_output->base, |
1374 | &intel_output->ddc_bus->adapter); | 1373 | intel_output->ddc_bus); |
1375 | if (edid != NULL) { | 1374 | if (edid != NULL) { |
1376 | sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid); | 1375 | sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid); |
1377 | kfree(edid); | 1376 | kfree(edid); |
@@ -1549,7 +1548,6 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector) | |||
1549 | static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | 1548 | static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) |
1550 | { | 1549 | { |
1551 | struct intel_output *intel_output = to_intel_output(connector); | 1550 | struct intel_output *intel_output = to_intel_output(connector); |
1552 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
1553 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | 1551 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
1554 | 1552 | ||
1555 | /* | 1553 | /* |
@@ -1557,8 +1555,6 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | |||
1557 | * Assume that the preferred modes are | 1555 | * Assume that the preferred modes are |
1558 | * arranged in priority order. | 1556 | * arranged in priority order. |
1559 | */ | 1557 | */ |
1560 | /* set the bus switch and get the modes */ | ||
1561 | intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); | ||
1562 | intel_ddc_get_modes(intel_output); | 1558 | intel_ddc_get_modes(intel_output); |
1563 | if (list_empty(&connector->probed_modes) == false) | 1559 | if (list_empty(&connector->probed_modes) == false) |
1564 | return; | 1560 | return; |
@@ -1709,7 +1705,7 @@ intel_sdvo_chan_to_intel_output(struct intel_i2c_chan *chan) | |||
1709 | 1705 | ||
1710 | list_for_each_entry(connector, | 1706 | list_for_each_entry(connector, |
1711 | &dev->mode_config.connector_list, head) { | 1707 | &dev->mode_config.connector_list, head) { |
1712 | if (to_intel_output(connector)->ddc_bus == chan) { | 1708 | if (to_intel_output(connector)->ddc_bus == &chan->adapter) { |
1713 | intel_output = to_intel_output(connector); | 1709 | intel_output = to_intel_output(connector); |
1714 | break; | 1710 | break; |
1715 | } | 1711 | } |
@@ -1723,7 +1719,7 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap, | |||
1723 | struct intel_output *intel_output; | 1719 | struct intel_output *intel_output; |
1724 | struct intel_sdvo_priv *sdvo_priv; | 1720 | struct intel_sdvo_priv *sdvo_priv; |
1725 | struct i2c_algo_bit_data *algo_data; | 1721 | struct i2c_algo_bit_data *algo_data; |
1726 | struct i2c_algorithm *algo; | 1722 | const struct i2c_algorithm *algo; |
1727 | 1723 | ||
1728 | algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data; | 1724 | algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data; |
1729 | intel_output = | 1725 | intel_output = |
@@ -1733,7 +1729,7 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap, | |||
1733 | return -EINVAL; | 1729 | return -EINVAL; |
1734 | 1730 | ||
1735 | sdvo_priv = intel_output->dev_priv; | 1731 | sdvo_priv = intel_output->dev_priv; |
1736 | algo = (struct i2c_algorithm *)intel_output->i2c_bus->adapter.algo; | 1732 | algo = intel_output->i2c_bus->algo; |
1737 | 1733 | ||
1738 | intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); | 1734 | intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); |
1739 | return algo->master_xfer(i2c_adap, msgs, num); | 1735 | return algo->master_xfer(i2c_adap, msgs, num); |
@@ -1785,13 +1781,11 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
1785 | struct drm_connector *connector; | 1781 | struct drm_connector *connector; |
1786 | struct intel_output *intel_output; | 1782 | struct intel_output *intel_output; |
1787 | struct intel_sdvo_priv *sdvo_priv; | 1783 | struct intel_sdvo_priv *sdvo_priv; |
1788 | struct intel_i2c_chan *i2cbus = NULL; | 1784 | |
1789 | struct intel_i2c_chan *ddcbus = NULL; | ||
1790 | int connector_type; | 1785 | int connector_type; |
1791 | u8 ch[0x40]; | 1786 | u8 ch[0x40]; |
1792 | int i; | 1787 | int i; |
1793 | int encoder_type, output_id; | 1788 | int encoder_type; |
1794 | u8 slave_addr; | ||
1795 | 1789 | ||
1796 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); | 1790 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); |
1797 | if (!intel_output) { | 1791 | if (!intel_output) { |
@@ -1799,29 +1793,24 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
1799 | } | 1793 | } |
1800 | 1794 | ||
1801 | sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1); | 1795 | sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1); |
1796 | sdvo_priv->output_device = output_device; | ||
1797 | |||
1798 | intel_output->dev_priv = sdvo_priv; | ||
1802 | intel_output->type = INTEL_OUTPUT_SDVO; | 1799 | intel_output->type = INTEL_OUTPUT_SDVO; |
1803 | 1800 | ||
1804 | /* setup the DDC bus. */ | 1801 | /* setup the DDC bus. */ |
1805 | if (output_device == SDVOB) | 1802 | if (output_device == SDVOB) |
1806 | i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); | 1803 | intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); |
1807 | else | 1804 | else |
1808 | i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); | 1805 | intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); |
1809 | 1806 | ||
1810 | if (!i2cbus) | 1807 | if (!intel_output->i2c_bus) |
1811 | goto err_inteloutput; | 1808 | goto err_inteloutput; |
1812 | 1809 | ||
1813 | slave_addr = intel_sdvo_get_slave_addr(dev, output_device); | 1810 | sdvo_priv->slave_addr = intel_sdvo_get_slave_addr(dev, output_device); |
1814 | sdvo_priv->i2c_bus = i2cbus; | ||
1815 | 1811 | ||
1816 | if (output_device == SDVOB) { | 1812 | /* Save the bit-banging i2c functionality for use by the DDC wrapper */ |
1817 | output_id = 1; | 1813 | intel_sdvo_i2c_bit_algo.functionality = intel_output->i2c_bus->algo->functionality; |
1818 | } else { | ||
1819 | output_id = 2; | ||
1820 | } | ||
1821 | sdvo_priv->i2c_bus->slave_addr = slave_addr >> 1; | ||
1822 | sdvo_priv->output_device = output_device; | ||
1823 | intel_output->i2c_bus = i2cbus; | ||
1824 | intel_output->dev_priv = sdvo_priv; | ||
1825 | 1814 | ||
1826 | /* Read the regs to test if we can talk to the device */ | 1815 | /* Read the regs to test if we can talk to the device */ |
1827 | for (i = 0; i < 0x40; i++) { | 1816 | for (i = 0; i < 0x40; i++) { |
@@ -1835,17 +1824,15 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
1835 | 1824 | ||
1836 | /* setup the DDC bus. */ | 1825 | /* setup the DDC bus. */ |
1837 | if (output_device == SDVOB) | 1826 | if (output_device == SDVOB) |
1838 | ddcbus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); | 1827 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); |
1839 | else | 1828 | else |
1840 | ddcbus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); | 1829 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); |
1841 | 1830 | ||
1842 | if (ddcbus == NULL) | 1831 | if (intel_output->ddc_bus == NULL) |
1843 | goto err_i2c; | 1832 | goto err_i2c; |
1844 | 1833 | ||
1845 | intel_sdvo_i2c_bit_algo.functionality = | 1834 | /* Wrap with our custom algo which switches to DDC mode */ |
1846 | intel_output->i2c_bus->adapter.algo->functionality; | 1835 | intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo; |
1847 | ddcbus->adapter.algo = &intel_sdvo_i2c_bit_algo; | ||
1848 | intel_output->ddc_bus = ddcbus; | ||
1849 | 1836 | ||
1850 | /* In defaut case sdvo lvds is false */ | 1837 | /* In defaut case sdvo lvds is false */ |
1851 | sdvo_priv->is_lvds = false; | 1838 | sdvo_priv->is_lvds = false; |
@@ -1965,9 +1952,10 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
1965 | return true; | 1952 | return true; |
1966 | 1953 | ||
1967 | err_i2c: | 1954 | err_i2c: |
1968 | if (ddcbus != NULL) | 1955 | if (intel_output->ddc_bus != NULL) |
1969 | intel_i2c_destroy(intel_output->ddc_bus); | 1956 | intel_i2c_destroy(intel_output->ddc_bus); |
1970 | intel_i2c_destroy(intel_output->i2c_bus); | 1957 | if (intel_output->i2c_bus != NULL) |
1958 | intel_i2c_destroy(intel_output->i2c_bus); | ||
1971 | err_inteloutput: | 1959 | err_inteloutput: |
1972 | kfree(intel_output); | 1960 | kfree(intel_output); |
1973 | 1961 | ||
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index ea68992e4416..a43c98e3f077 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
@@ -1383,34 +1383,31 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output) | |||
1383 | /* | 1383 | /* |
1384 | * Detect TV by polling) | 1384 | * Detect TV by polling) |
1385 | */ | 1385 | */ |
1386 | if (intel_output->load_detect_temp) { | 1386 | save_tv_dac = tv_dac; |
1387 | /* TV not currently running, prod it with destructive detect */ | 1387 | tv_ctl = I915_READ(TV_CTL); |
1388 | save_tv_dac = tv_dac; | 1388 | save_tv_ctl = tv_ctl; |
1389 | tv_ctl = I915_READ(TV_CTL); | 1389 | tv_ctl &= ~TV_ENC_ENABLE; |
1390 | save_tv_ctl = tv_ctl; | 1390 | tv_ctl &= ~TV_TEST_MODE_MASK; |
1391 | tv_ctl &= ~TV_ENC_ENABLE; | 1391 | tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; |
1392 | tv_ctl &= ~TV_TEST_MODE_MASK; | 1392 | tv_dac &= ~TVDAC_SENSE_MASK; |
1393 | tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; | 1393 | tv_dac &= ~DAC_A_MASK; |
1394 | tv_dac &= ~TVDAC_SENSE_MASK; | 1394 | tv_dac &= ~DAC_B_MASK; |
1395 | tv_dac &= ~DAC_A_MASK; | 1395 | tv_dac &= ~DAC_C_MASK; |
1396 | tv_dac &= ~DAC_B_MASK; | 1396 | tv_dac |= (TVDAC_STATE_CHG_EN | |
1397 | tv_dac &= ~DAC_C_MASK; | 1397 | TVDAC_A_SENSE_CTL | |
1398 | tv_dac |= (TVDAC_STATE_CHG_EN | | 1398 | TVDAC_B_SENSE_CTL | |
1399 | TVDAC_A_SENSE_CTL | | 1399 | TVDAC_C_SENSE_CTL | |
1400 | TVDAC_B_SENSE_CTL | | 1400 | DAC_CTL_OVERRIDE | |
1401 | TVDAC_C_SENSE_CTL | | 1401 | DAC_A_0_7_V | |
1402 | DAC_CTL_OVERRIDE | | 1402 | DAC_B_0_7_V | |
1403 | DAC_A_0_7_V | | 1403 | DAC_C_0_7_V); |
1404 | DAC_B_0_7_V | | 1404 | I915_WRITE(TV_CTL, tv_ctl); |
1405 | DAC_C_0_7_V); | 1405 | I915_WRITE(TV_DAC, tv_dac); |
1406 | I915_WRITE(TV_CTL, tv_ctl); | 1406 | intel_wait_for_vblank(dev); |
1407 | I915_WRITE(TV_DAC, tv_dac); | 1407 | tv_dac = I915_READ(TV_DAC); |
1408 | intel_wait_for_vblank(dev); | 1408 | I915_WRITE(TV_DAC, save_tv_dac); |
1409 | tv_dac = I915_READ(TV_DAC); | 1409 | I915_WRITE(TV_CTL, save_tv_ctl); |
1410 | I915_WRITE(TV_DAC, save_tv_dac); | 1410 | intel_wait_for_vblank(dev); |
1411 | I915_WRITE(TV_CTL, save_tv_ctl); | ||
1412 | intel_wait_for_vblank(dev); | ||
1413 | } | ||
1414 | /* | 1411 | /* |
1415 | * A B C | 1412 | * A B C |
1416 | * 0 1 1 Composite | 1413 | * 0 1 1 Composite |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index f30aa7274a54..f97563db4e59 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -35,6 +35,23 @@ | |||
35 | #include "atom.h" | 35 | #include "atom.h" |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * Clear GPU surface registers. | ||
39 | */ | ||
40 | static void radeon_surface_init(struct radeon_device *rdev) | ||
41 | { | ||
42 | /* FIXME: check this out */ | ||
43 | if (rdev->family < CHIP_R600) { | ||
44 | int i; | ||
45 | |||
46 | for (i = 0; i < 8; i++) { | ||
47 | WREG32(RADEON_SURFACE0_INFO + | ||
48 | i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), | ||
49 | 0); | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | /* | ||
38 | * GPU scratch registers helpers function. | 55 | * GPU scratch registers helpers function. |
39 | */ | 56 | */ |
40 | static void radeon_scratch_init(struct radeon_device *rdev) | 57 | static void radeon_scratch_init(struct radeon_device *rdev) |
@@ -496,6 +513,8 @@ int radeon_device_init(struct radeon_device *rdev, | |||
496 | radeon_errata(rdev); | 513 | radeon_errata(rdev); |
497 | /* Initialize scratch registers */ | 514 | /* Initialize scratch registers */ |
498 | radeon_scratch_init(rdev); | 515 | radeon_scratch_init(rdev); |
516 | /* Initialize surface registers */ | ||
517 | radeon_surface_init(rdev); | ||
499 | 518 | ||
500 | /* TODO: disable VGA need to use VGA request */ | 519 | /* TODO: disable VGA need to use VGA request */ |
501 | /* BIOS*/ | 520 | /* BIOS*/ |
@@ -604,9 +623,6 @@ int radeon_device_init(struct radeon_device *rdev, | |||
604 | if (r) { | 623 | if (r) { |
605 | return r; | 624 | return r; |
606 | } | 625 | } |
607 | if (rdev->fbdev_rfb && rdev->fbdev_rfb->obj) { | ||
608 | rdev->fbdev_robj = rdev->fbdev_rfb->obj->driver_private; | ||
609 | } | ||
610 | if (!ret) { | 626 | if (!ret) { |
611 | DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); | 627 | DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); |
612 | } | 628 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 09c9fb9f6210..84ba69f48784 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
@@ -345,7 +345,7 @@ static void __exit radeon_exit(void) | |||
345 | drm_exit(driver); | 345 | drm_exit(driver); |
346 | } | 346 | } |
347 | 347 | ||
348 | late_initcall(radeon_init); | 348 | module_init(radeon_init); |
349 | module_exit(radeon_exit); | 349 | module_exit(radeon_exit); |
350 | 350 | ||
351 | MODULE_AUTHOR(DRIVER_AUTHOR); | 351 | MODULE_AUTHOR(DRIVER_AUTHOR); |
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index fa86d398945e..9e8f191eb64a 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
@@ -478,14 +478,16 @@ int radeonfb_create(struct radeon_device *rdev, | |||
478 | { | 478 | { |
479 | struct fb_info *info; | 479 | struct fb_info *info; |
480 | struct radeon_fb_device *rfbdev; | 480 | struct radeon_fb_device *rfbdev; |
481 | struct drm_framebuffer *fb; | 481 | struct drm_framebuffer *fb = NULL; |
482 | struct radeon_framebuffer *rfb; | 482 | struct radeon_framebuffer *rfb; |
483 | struct drm_mode_fb_cmd mode_cmd; | 483 | struct drm_mode_fb_cmd mode_cmd; |
484 | struct drm_gem_object *gobj = NULL; | 484 | struct drm_gem_object *gobj = NULL; |
485 | struct radeon_object *robj = NULL; | 485 | struct radeon_object *robj = NULL; |
486 | struct device *device = &rdev->pdev->dev; | 486 | struct device *device = &rdev->pdev->dev; |
487 | int size, aligned_size, ret; | 487 | int size, aligned_size, ret; |
488 | u64 fb_gpuaddr; | ||
488 | void *fbptr = NULL; | 489 | void *fbptr = NULL; |
490 | unsigned long tmp; | ||
489 | 491 | ||
490 | mode_cmd.width = surface_width; | 492 | mode_cmd.width = surface_width; |
491 | mode_cmd.height = surface_height; | 493 | mode_cmd.height = surface_height; |
@@ -498,11 +500,12 @@ int radeonfb_create(struct radeon_device *rdev, | |||
498 | aligned_size = ALIGN(size, PAGE_SIZE); | 500 | aligned_size = ALIGN(size, PAGE_SIZE); |
499 | 501 | ||
500 | ret = radeon_gem_object_create(rdev, aligned_size, 0, | 502 | ret = radeon_gem_object_create(rdev, aligned_size, 0, |
501 | RADEON_GEM_DOMAIN_VRAM, | 503 | RADEON_GEM_DOMAIN_VRAM, |
502 | false, ttm_bo_type_kernel, | 504 | false, ttm_bo_type_kernel, |
503 | false, &gobj); | 505 | false, &gobj); |
504 | if (ret) { | 506 | if (ret) { |
505 | printk(KERN_ERR "failed to allocate framebuffer\n"); | 507 | printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n", |
508 | surface_width, surface_height); | ||
506 | ret = -ENOMEM; | 509 | ret = -ENOMEM; |
507 | goto out; | 510 | goto out; |
508 | } | 511 | } |
@@ -515,12 +518,19 @@ int radeonfb_create(struct radeon_device *rdev, | |||
515 | ret = -ENOMEM; | 518 | ret = -ENOMEM; |
516 | goto out_unref; | 519 | goto out_unref; |
517 | } | 520 | } |
521 | ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr); | ||
522 | if (ret) { | ||
523 | printk(KERN_ERR "failed to pin framebuffer\n"); | ||
524 | ret = -ENOMEM; | ||
525 | goto out_unref; | ||
526 | } | ||
518 | 527 | ||
519 | list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list); | 528 | list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list); |
520 | 529 | ||
521 | rfb = to_radeon_framebuffer(fb); | 530 | rfb = to_radeon_framebuffer(fb); |
522 | *rfb_p = rfb; | 531 | *rfb_p = rfb; |
523 | rdev->fbdev_rfb = rfb; | 532 | rdev->fbdev_rfb = rfb; |
533 | rdev->fbdev_robj = robj; | ||
524 | 534 | ||
525 | info = framebuffer_alloc(sizeof(struct radeon_fb_device), device); | 535 | info = framebuffer_alloc(sizeof(struct radeon_fb_device), device); |
526 | if (info == NULL) { | 536 | if (info == NULL) { |
@@ -541,13 +551,13 @@ int radeonfb_create(struct radeon_device *rdev, | |||
541 | info->fix.xpanstep = 1; /* doing it in hw */ | 551 | info->fix.xpanstep = 1; /* doing it in hw */ |
542 | info->fix.ypanstep = 1; /* doing it in hw */ | 552 | info->fix.ypanstep = 1; /* doing it in hw */ |
543 | info->fix.ywrapstep = 0; | 553 | info->fix.ywrapstep = 0; |
544 | info->fix.accel = FB_ACCEL_I830; | 554 | info->fix.accel = FB_ACCEL_NONE; |
545 | info->fix.type_aux = 0; | 555 | info->fix.type_aux = 0; |
546 | info->flags = FBINFO_DEFAULT; | 556 | info->flags = FBINFO_DEFAULT; |
547 | info->fbops = &radeonfb_ops; | 557 | info->fbops = &radeonfb_ops; |
548 | info->fix.line_length = fb->pitch; | 558 | info->fix.line_length = fb->pitch; |
549 | info->screen_base = fbptr; | 559 | tmp = fb_gpuaddr - rdev->mc.vram_location; |
550 | info->fix.smem_start = (unsigned long)fbptr; | 560 | info->fix.smem_start = rdev->mc.aper_base + tmp; |
551 | info->fix.smem_len = size; | 561 | info->fix.smem_len = size; |
552 | info->screen_base = fbptr; | 562 | info->screen_base = fbptr; |
553 | info->screen_size = size; | 563 | info->screen_size = size; |
@@ -562,8 +572,8 @@ int radeonfb_create(struct radeon_device *rdev, | |||
562 | info->var.width = -1; | 572 | info->var.width = -1; |
563 | info->var.xres = fb_width; | 573 | info->var.xres = fb_width; |
564 | info->var.yres = fb_height; | 574 | info->var.yres = fb_height; |
565 | info->fix.mmio_start = pci_resource_start(rdev->pdev, 2); | 575 | info->fix.mmio_start = 0; |
566 | info->fix.mmio_len = pci_resource_len(rdev->pdev, 2); | 576 | info->fix.mmio_len = 0; |
567 | info->pixmap.size = 64*1024; | 577 | info->pixmap.size = 64*1024; |
568 | info->pixmap.buf_align = 8; | 578 | info->pixmap.buf_align = 8; |
569 | info->pixmap.access_align = 32; | 579 | info->pixmap.access_align = 32; |
@@ -644,7 +654,7 @@ out_unref: | |||
644 | if (robj) { | 654 | if (robj) { |
645 | radeon_object_kunmap(robj); | 655 | radeon_object_kunmap(robj); |
646 | } | 656 | } |
647 | if (ret) { | 657 | if (fb && ret) { |
648 | list_del(&fb->filp_head); | 658 | list_del(&fb->filp_head); |
649 | drm_gem_object_unreference(gobj); | 659 | drm_gem_object_unreference(gobj); |
650 | drm_framebuffer_cleanup(fb); | 660 | drm_framebuffer_cleanup(fb); |
@@ -813,6 +823,7 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) | |||
813 | robj = rfb->obj->driver_private; | 823 | robj = rfb->obj->driver_private; |
814 | unregister_framebuffer(info); | 824 | unregister_framebuffer(info); |
815 | radeon_object_kunmap(robj); | 825 | radeon_object_kunmap(robj); |
826 | radeon_object_unpin(robj); | ||
816 | framebuffer_release(info); | 827 | framebuffer_release(info); |
817 | } | 828 | } |
818 | 829 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 983e8df5e000..bac0d06c52ac 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
@@ -223,7 +223,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain, | |||
223 | { | 223 | { |
224 | uint32_t flags; | 224 | uint32_t flags; |
225 | uint32_t tmp; | 225 | uint32_t tmp; |
226 | void *fbptr; | ||
227 | int r; | 226 | int r; |
228 | 227 | ||
229 | flags = radeon_object_flags_from_domain(domain); | 228 | flags = radeon_object_flags_from_domain(domain); |
@@ -242,10 +241,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain, | |||
242 | DRM_ERROR("radeon: failed to reserve object for pinning it.\n"); | 241 | DRM_ERROR("radeon: failed to reserve object for pinning it.\n"); |
243 | return r; | 242 | return r; |
244 | } | 243 | } |
245 | if (robj->rdev->fbdev_robj == robj) { | ||
246 | mutex_lock(&robj->rdev->fbdev_info->lock); | ||
247 | radeon_object_kunmap(robj); | ||
248 | } | ||
249 | tmp = robj->tobj.mem.placement; | 244 | tmp = robj->tobj.mem.placement; |
250 | ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM); | 245 | ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM); |
251 | robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING; | 246 | robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING; |
@@ -261,23 +256,12 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain, | |||
261 | DRM_ERROR("radeon: failed to pin object.\n"); | 256 | DRM_ERROR("radeon: failed to pin object.\n"); |
262 | } | 257 | } |
263 | radeon_object_unreserve(robj); | 258 | radeon_object_unreserve(robj); |
264 | if (robj->rdev->fbdev_robj == robj) { | ||
265 | if (!r) { | ||
266 | r = radeon_object_kmap(robj, &fbptr); | ||
267 | } | ||
268 | if (!r) { | ||
269 | robj->rdev->fbdev_info->screen_base = fbptr; | ||
270 | robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr; | ||
271 | } | ||
272 | mutex_unlock(&robj->rdev->fbdev_info->lock); | ||
273 | } | ||
274 | return r; | 259 | return r; |
275 | } | 260 | } |
276 | 261 | ||
277 | void radeon_object_unpin(struct radeon_object *robj) | 262 | void radeon_object_unpin(struct radeon_object *robj) |
278 | { | 263 | { |
279 | uint32_t flags; | 264 | uint32_t flags; |
280 | void *fbptr; | ||
281 | int r; | 265 | int r; |
282 | 266 | ||
283 | spin_lock(&robj->tobj.lock); | 267 | spin_lock(&robj->tobj.lock); |
@@ -297,10 +281,6 @@ void radeon_object_unpin(struct radeon_object *robj) | |||
297 | DRM_ERROR("radeon: failed to reserve object for unpinning it.\n"); | 281 | DRM_ERROR("radeon: failed to reserve object for unpinning it.\n"); |
298 | return; | 282 | return; |
299 | } | 283 | } |
300 | if (robj->rdev->fbdev_robj == robj) { | ||
301 | mutex_lock(&robj->rdev->fbdev_info->lock); | ||
302 | radeon_object_kunmap(robj); | ||
303 | } | ||
304 | flags = robj->tobj.mem.placement; | 284 | flags = robj->tobj.mem.placement; |
305 | robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT; | 285 | robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT; |
306 | r = ttm_buffer_object_validate(&robj->tobj, | 286 | r = ttm_buffer_object_validate(&robj->tobj, |
@@ -310,16 +290,6 @@ void radeon_object_unpin(struct radeon_object *robj) | |||
310 | DRM_ERROR("radeon: failed to unpin buffer.\n"); | 290 | DRM_ERROR("radeon: failed to unpin buffer.\n"); |
311 | } | 291 | } |
312 | radeon_object_unreserve(robj); | 292 | radeon_object_unreserve(robj); |
313 | if (robj->rdev->fbdev_robj == robj) { | ||
314 | if (!r) { | ||
315 | r = radeon_object_kmap(robj, &fbptr); | ||
316 | } | ||
317 | if (!r) { | ||
318 | robj->rdev->fbdev_info->screen_base = fbptr; | ||
319 | robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr; | ||
320 | } | ||
321 | mutex_unlock(&robj->rdev->fbdev_info->lock); | ||
322 | } | ||
323 | } | 293 | } |
324 | 294 | ||
325 | int radeon_object_wait(struct radeon_object *robj) | 295 | int radeon_object_wait(struct radeon_object *robj) |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 517c84559633..bdec583901eb 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/highmem.h> | 34 | #include <linux/highmem.h> |
35 | #include <linux/wait.h> | 35 | #include <linux/wait.h> |
36 | #include <linux/vmalloc.h> | 36 | #include <linux/vmalloc.h> |
37 | #include <linux/version.h> | ||
38 | #include <linux/module.h> | 37 | #include <linux/module.h> |
39 | 38 | ||
40 | void ttm_bo_free_old_node(struct ttm_buffer_object *bo) | 39 | void ttm_bo_free_old_node(struct ttm_buffer_object *bo) |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 27b146c54fbc..40b75032ea47 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <ttm/ttm_bo_driver.h> | 32 | #include <ttm/ttm_bo_driver.h> |
33 | #include <ttm/ttm_placement.h> | 33 | #include <ttm/ttm_placement.h> |
34 | #include <linux/mm.h> | 34 | #include <linux/mm.h> |
35 | #include <linux/version.h> | ||
36 | #include <linux/rbtree.h> | 35 | #include <linux/rbtree.h> |
37 | #include <linux/module.h> | 36 | #include <linux/module.h> |
38 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 0331fa74cd3f..75dc8bd24592 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c | |||
@@ -28,7 +28,6 @@ | |||
28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <linux/version.h> | ||
32 | #include <linux/vmalloc.h> | 31 | #include <linux/vmalloc.h> |
33 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
34 | #include <linux/highmem.h> | 33 | #include <linux/highmem.h> |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index aa87b6a3bbef..8206442fbabd 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -328,6 +328,7 @@ config I2C_DAVINCI | |||
328 | 328 | ||
329 | config I2C_DESIGNWARE | 329 | config I2C_DESIGNWARE |
330 | tristate "Synopsys DesignWare" | 330 | tristate "Synopsys DesignWare" |
331 | depends on HAVE_CLK | ||
331 | help | 332 | help |
332 | If you say yes to this option, support will be included for the | 333 | If you say yes to this option, support will be included for the |
333 | Synopsys DesignWare I2C adapter. Only master mode is supported. | 334 | Synopsys DesignWare I2C adapter. Only master mode is supported. |
diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c index bd066bb9d611..09f98ed0731f 100644 --- a/drivers/ide/cs5520.c +++ b/drivers/ide/cs5520.c | |||
@@ -135,6 +135,7 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic | |||
135 | 135 | ||
136 | ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); | 136 | ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); |
137 | hw[0].irq = 14; | 137 | hw[0].irq = 14; |
138 | hw[1].irq = 15; | ||
138 | 139 | ||
139 | return ide_host_add(d, hws, 2, NULL); | 140 | return ide_host_add(d, hws, 2, NULL); |
140 | } | 141 | } |
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 77f79d26b264..c509c9916464 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c | |||
@@ -92,6 +92,11 @@ int ide_acpi_init(void) | |||
92 | return 0; | 92 | return 0; |
93 | } | 93 | } |
94 | 94 | ||
95 | bool ide_port_acpi(ide_hwif_t *hwif) | ||
96 | { | ||
97 | return ide_noacpi == 0 && hwif->acpidata; | ||
98 | } | ||
99 | |||
95 | /** | 100 | /** |
96 | * ide_get_dev_handle - finds acpi_handle and PCI device.function | 101 | * ide_get_dev_handle - finds acpi_handle and PCI device.function |
97 | * @dev: device to locate | 102 | * @dev: device to locate |
@@ -352,9 +357,6 @@ int ide_acpi_exec_tfs(ide_drive_t *drive) | |||
352 | unsigned long gtf_address; | 357 | unsigned long gtf_address; |
353 | unsigned long obj_loc; | 358 | unsigned long obj_loc; |
354 | 359 | ||
355 | if (ide_noacpi) | ||
356 | return 0; | ||
357 | |||
358 | DEBPRINT("call get_GTF, drive=%s port=%d\n", drive->name, drive->dn); | 360 | DEBPRINT("call get_GTF, drive=%s port=%d\n", drive->name, drive->dn); |
359 | 361 | ||
360 | ret = do_drive_get_GTF(drive, >f_length, >f_address, &obj_loc); | 362 | ret = do_drive_get_GTF(drive, >f_length, >f_address, &obj_loc); |
@@ -389,16 +391,6 @@ void ide_acpi_get_timing(ide_hwif_t *hwif) | |||
389 | struct acpi_buffer output; | 391 | struct acpi_buffer output; |
390 | union acpi_object *out_obj; | 392 | union acpi_object *out_obj; |
391 | 393 | ||
392 | if (ide_noacpi) | ||
393 | return; | ||
394 | |||
395 | DEBPRINT("ENTER:\n"); | ||
396 | |||
397 | if (!hwif->acpidata) { | ||
398 | DEBPRINT("no ACPI data for %s\n", hwif->name); | ||
399 | return; | ||
400 | } | ||
401 | |||
402 | /* Setting up output buffer for _GTM */ | 394 | /* Setting up output buffer for _GTM */ |
403 | output.length = ACPI_ALLOCATE_BUFFER; | 395 | output.length = ACPI_ALLOCATE_BUFFER; |
404 | output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ | 396 | output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ |
@@ -479,16 +471,6 @@ void ide_acpi_push_timing(ide_hwif_t *hwif) | |||
479 | struct ide_acpi_drive_link *master = &hwif->acpidata->master; | 471 | struct ide_acpi_drive_link *master = &hwif->acpidata->master; |
480 | struct ide_acpi_drive_link *slave = &hwif->acpidata->slave; | 472 | struct ide_acpi_drive_link *slave = &hwif->acpidata->slave; |
481 | 473 | ||
482 | if (ide_noacpi) | ||
483 | return; | ||
484 | |||
485 | DEBPRINT("ENTER:\n"); | ||
486 | |||
487 | if (!hwif->acpidata) { | ||
488 | DEBPRINT("no ACPI data for %s\n", hwif->name); | ||
489 | return; | ||
490 | } | ||
491 | |||
492 | /* Give the GTM buffer + drive Identify data to the channel via the | 474 | /* Give the GTM buffer + drive Identify data to the channel via the |
493 | * _STM method: */ | 475 | * _STM method: */ |
494 | /* setup input parameters buffer for _STM */ | 476 | /* setup input parameters buffer for _STM */ |
@@ -527,16 +509,11 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) | |||
527 | ide_drive_t *drive; | 509 | ide_drive_t *drive; |
528 | int i; | 510 | int i; |
529 | 511 | ||
530 | if (ide_noacpi || ide_noacpi_psx) | 512 | if (ide_noacpi_psx) |
531 | return; | 513 | return; |
532 | 514 | ||
533 | DEBPRINT("ENTER:\n"); | 515 | DEBPRINT("ENTER:\n"); |
534 | 516 | ||
535 | if (!hwif->acpidata) { | ||
536 | DEBPRINT("no ACPI data for %s\n", hwif->name); | ||
537 | return; | ||
538 | } | ||
539 | |||
540 | /* channel first and then drives for power on and verse versa for power off */ | 517 | /* channel first and then drives for power on and verse versa for power off */ |
541 | if (on) | 518 | if (on) |
542 | acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0); | 519 | acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0); |
@@ -616,7 +593,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) | |||
616 | drive->name, err); | 593 | drive->name, err); |
617 | } | 594 | } |
618 | 595 | ||
619 | if (!ide_acpionboot) { | 596 | if (ide_noacpi || ide_acpionboot == 0) { |
620 | DEBPRINT("ACPI methods disabled on boot\n"); | 597 | DEBPRINT("ACPI methods disabled on boot\n"); |
621 | return; | 598 | return; |
622 | } | 599 | } |
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 4a19686fcfe9..6a9a769bffc1 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -592,9 +592,19 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
592 | } | 592 | } |
593 | } else if (!blk_pc_request(rq)) { | 593 | } else if (!blk_pc_request(rq)) { |
594 | ide_cd_request_sense_fixup(drive, cmd); | 594 | ide_cd_request_sense_fixup(drive, cmd); |
595 | /* complain if we still have data left to transfer */ | 595 | |
596 | uptodate = cmd->nleft ? 0 : 1; | 596 | uptodate = cmd->nleft ? 0 : 1; |
597 | if (uptodate == 0) | 597 | |
598 | /* | ||
599 | * suck out the remaining bytes from the drive in an | ||
600 | * attempt to complete the data xfer. (see BZ#13399) | ||
601 | */ | ||
602 | if (!(stat & ATA_ERR) && !uptodate && thislen) { | ||
603 | ide_pio_bytes(drive, cmd, write, thislen); | ||
604 | uptodate = cmd->nleft ? 0 : 1; | ||
605 | } | ||
606 | |||
607 | if (!uptodate) | ||
598 | rq->cmd_flags |= REQ_FAILED; | 608 | rq->cmd_flags |= REQ_FAILED; |
599 | } | 609 | } |
600 | goto out_end; | 610 | goto out_end; |
@@ -876,9 +886,12 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, | |||
876 | return stat; | 886 | return stat; |
877 | 887 | ||
878 | /* | 888 | /* |
879 | * Sanity check the given block size | 889 | * Sanity check the given block size, in so far as making |
890 | * sure the sectors_per_frame we give to the caller won't | ||
891 | * end up being bogus. | ||
880 | */ | 892 | */ |
881 | blocklen = be32_to_cpu(capbuf.blocklen); | 893 | blocklen = be32_to_cpu(capbuf.blocklen); |
894 | blocklen = (blocklen >> SECTOR_BITS) << SECTOR_BITS; | ||
882 | switch (blocklen) { | 895 | switch (blocklen) { |
883 | case 512: | 896 | case 512: |
884 | case 1024: | 897 | case 1024: |
@@ -886,10 +899,9 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, | |||
886 | case 4096: | 899 | case 4096: |
887 | break; | 900 | break; |
888 | default: | 901 | default: |
889 | printk(KERN_ERR PFX "%s: weird block size %u\n", | 902 | printk_once(KERN_ERR PFX "%s: weird block size %u; " |
903 | "setting default block size to 2048\n", | ||
890 | drive->name, blocklen); | 904 | drive->name, blocklen); |
891 | printk(KERN_ERR PFX "%s: default to 2kb block size\n", | ||
892 | drive->name); | ||
893 | blocklen = 2048; | 905 | blocklen = 2048; |
894 | break; | 906 | break; |
895 | } | 907 | } |
diff --git a/drivers/ide/ide-devsets.c b/drivers/ide/ide-devsets.c index 5bf958e5b1d5..1099bf7cf968 100644 --- a/drivers/ide/ide-devsets.c +++ b/drivers/ide/ide-devsets.c | |||
@@ -183,6 +183,6 @@ ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq) | |||
183 | err = setfunc(drive, *(int *)&rq->cmd[1]); | 183 | err = setfunc(drive, *(int *)&rq->cmd[1]); |
184 | if (err) | 184 | if (err) |
185 | rq->errors = err; | 185 | rq->errors = err; |
186 | ide_complete_rq(drive, err, ide_rq_bytes(rq)); | 186 | ide_complete_rq(drive, err, blk_rq_bytes(rq)); |
187 | return ide_stopped; | 187 | return ide_stopped; |
188 | } | 188 | } |
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 219e6fb78dc6..ee58c88dee5a 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c | |||
@@ -361,9 +361,6 @@ static int ide_tune_dma(ide_drive_t *drive) | |||
361 | if (__ide_dma_bad_drive(drive)) | 361 | if (__ide_dma_bad_drive(drive)) |
362 | return 0; | 362 | return 0; |
363 | 363 | ||
364 | if (ide_id_dma_bug(drive)) | ||
365 | return 0; | ||
366 | |||
367 | if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) | 364 | if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) |
368 | return config_drive_for_dma(drive); | 365 | return config_drive_for_dma(drive); |
369 | 366 | ||
@@ -394,24 +391,6 @@ static int ide_dma_check(ide_drive_t *drive) | |||
394 | return -1; | 391 | return -1; |
395 | } | 392 | } |
396 | 393 | ||
397 | int ide_id_dma_bug(ide_drive_t *drive) | ||
398 | { | ||
399 | u16 *id = drive->id; | ||
400 | |||
401 | if (id[ATA_ID_FIELD_VALID] & 4) { | ||
402 | if ((id[ATA_ID_UDMA_MODES] >> 8) && | ||
403 | (id[ATA_ID_MWDMA_MODES] >> 8)) | ||
404 | goto err_out; | ||
405 | } else if ((id[ATA_ID_MWDMA_MODES] >> 8) && | ||
406 | (id[ATA_ID_SWDMA_MODES] >> 8)) | ||
407 | goto err_out; | ||
408 | |||
409 | return 0; | ||
410 | err_out: | ||
411 | printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name); | ||
412 | return 1; | ||
413 | } | ||
414 | |||
415 | int ide_set_dma(ide_drive_t *drive) | 394 | int ide_set_dma(ide_drive_t *drive) |
416 | { | 395 | { |
417 | int rc; | 396 | int rc; |
diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c index 2b9141979613..e9abf2c3c335 100644 --- a/drivers/ide/ide-eh.c +++ b/drivers/ide/ide-eh.c | |||
@@ -149,7 +149,7 @@ static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) | |||
149 | if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) { | 149 | if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) { |
150 | if (err <= 0 && rq->errors == 0) | 150 | if (err <= 0 && rq->errors == 0) |
151 | rq->errors = -EIO; | 151 | rq->errors = -EIO; |
152 | ide_complete_rq(drive, err ? err : 0, ide_rq_bytes(rq)); | 152 | ide_complete_rq(drive, err ? err : 0, blk_rq_bytes(rq)); |
153 | } | 153 | } |
154 | } | 154 | } |
155 | 155 | ||
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 8b3f204f7d73..fefbdfc8db06 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -293,7 +293,7 @@ out_end: | |||
293 | drive->failed_pc = NULL; | 293 | drive->failed_pc = NULL; |
294 | if (blk_fs_request(rq) == 0 && rq->errors == 0) | 294 | if (blk_fs_request(rq) == 0 && rq->errors == 0) |
295 | rq->errors = -EIO; | 295 | rq->errors = -EIO; |
296 | ide_complete_rq(drive, -EIO, ide_rq_bytes(rq)); | 296 | ide_complete_rq(drive, -EIO, blk_rq_bytes(rq)); |
297 | return ide_stopped; | 297 | return ide_stopped; |
298 | } | 298 | } |
299 | 299 | ||
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 1059f809b809..d5f3c77beadd 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -112,16 +112,6 @@ void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err) | |||
112 | } | 112 | } |
113 | } | 113 | } |
114 | 114 | ||
115 | /* obsolete, blk_rq_bytes() should be used instead */ | ||
116 | unsigned int ide_rq_bytes(struct request *rq) | ||
117 | { | ||
118 | if (blk_pc_request(rq)) | ||
119 | return blk_rq_bytes(rq); | ||
120 | else | ||
121 | return blk_rq_cur_sectors(rq) << 9; | ||
122 | } | ||
123 | EXPORT_SYMBOL_GPL(ide_rq_bytes); | ||
124 | |||
125 | int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes) | 115 | int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes) |
126 | { | 116 | { |
127 | ide_hwif_t *hwif = drive->hwif; | 117 | ide_hwif_t *hwif = drive->hwif; |
@@ -152,14 +142,14 @@ void ide_kill_rq(ide_drive_t *drive, struct request *rq) | |||
152 | 142 | ||
153 | if ((media == ide_floppy || media == ide_tape) && drv_req) { | 143 | if ((media == ide_floppy || media == ide_tape) && drv_req) { |
154 | rq->errors = 0; | 144 | rq->errors = 0; |
155 | ide_complete_rq(drive, 0, blk_rq_bytes(rq)); | ||
156 | } else { | 145 | } else { |
157 | if (media == ide_tape) | 146 | if (media == ide_tape) |
158 | rq->errors = IDE_DRV_ERROR_GENERAL; | 147 | rq->errors = IDE_DRV_ERROR_GENERAL; |
159 | else if (blk_fs_request(rq) == 0 && rq->errors == 0) | 148 | else if (blk_fs_request(rq) == 0 && rq->errors == 0) |
160 | rq->errors = -EIO; | 149 | rq->errors = -EIO; |
161 | ide_complete_rq(drive, -EIO, ide_rq_bytes(rq)); | ||
162 | } | 150 | } |
151 | |||
152 | ide_complete_rq(drive, -EIO, blk_rq_bytes(rq)); | ||
163 | } | 153 | } |
164 | 154 | ||
165 | static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) | 155 | static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) |
@@ -476,10 +466,14 @@ void do_ide_request(struct request_queue *q) | |||
476 | 466 | ||
477 | if (!ide_lock_port(hwif)) { | 467 | if (!ide_lock_port(hwif)) { |
478 | ide_hwif_t *prev_port; | 468 | ide_hwif_t *prev_port; |
479 | |||
480 | WARN_ON_ONCE(hwif->rq); | ||
481 | repeat: | 469 | repeat: |
482 | prev_port = hwif->host->cur_port; | 470 | prev_port = hwif->host->cur_port; |
471 | |||
472 | if (drive->dev_flags & IDE_DFLAG_BLOCKED) | ||
473 | rq = hwif->rq; | ||
474 | else | ||
475 | WARN_ON_ONCE(hwif->rq); | ||
476 | |||
483 | if (drive->dev_flags & IDE_DFLAG_SLEEPING && | 477 | if (drive->dev_flags & IDE_DFLAG_SLEEPING && |
484 | time_after(drive->sleep, jiffies)) { | 478 | time_after(drive->sleep, jiffies)) { |
485 | ide_unlock_port(hwif); | 479 | ide_unlock_port(hwif); |
@@ -506,43 +500,29 @@ repeat: | |||
506 | hwif->cur_dev = drive; | 500 | hwif->cur_dev = drive; |
507 | drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); | 501 | drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); |
508 | 502 | ||
509 | spin_unlock_irq(&hwif->lock); | 503 | if (rq == NULL) { |
510 | spin_lock_irq(q->queue_lock); | 504 | spin_unlock_irq(&hwif->lock); |
511 | /* | 505 | spin_lock_irq(q->queue_lock); |
512 | * we know that the queue isn't empty, but this can happen | 506 | /* |
513 | * if the q->prep_rq_fn() decides to kill a request | 507 | * we know that the queue isn't empty, but this can |
514 | */ | 508 | * happen if ->prep_rq_fn() decides to kill a request |
515 | if (!rq) | 509 | */ |
516 | rq = blk_fetch_request(drive->queue); | 510 | rq = blk_fetch_request(drive->queue); |
511 | spin_unlock_irq(q->queue_lock); | ||
512 | spin_lock_irq(&hwif->lock); | ||
517 | 513 | ||
518 | spin_unlock_irq(q->queue_lock); | 514 | if (rq == NULL) { |
519 | spin_lock_irq(&hwif->lock); | 515 | ide_unlock_port(hwif); |
520 | 516 | goto out; | |
521 | if (!rq) { | 517 | } |
522 | ide_unlock_port(hwif); | ||
523 | goto out; | ||
524 | } | 518 | } |
525 | 519 | ||
526 | /* | 520 | /* |
527 | * Sanity: don't accept a request that isn't a PM request | 521 | * Sanity: don't accept a request that isn't a PM request |
528 | * if we are currently power managed. This is very important as | 522 | * if we are currently power managed. |
529 | * blk_stop_queue() doesn't prevent the blk_fetch_request() | ||
530 | * above to return us whatever is in the queue. Since we call | ||
531 | * ide_do_request() ourselves, we end up taking requests while | ||
532 | * the queue is blocked... | ||
533 | * | ||
534 | * We let requests forced at head of queue with ide-preempt | ||
535 | * though. I hope that doesn't happen too much, hopefully not | ||
536 | * unless the subdriver triggers such a thing in its own PM | ||
537 | * state machine. | ||
538 | */ | 523 | */ |
539 | if ((drive->dev_flags & IDE_DFLAG_BLOCKED) && | 524 | BUG_ON((drive->dev_flags & IDE_DFLAG_BLOCKED) && |
540 | blk_pm_request(rq) == 0 && | 525 | blk_pm_request(rq) == 0); |
541 | (rq->cmd_flags & REQ_PREEMPT) == 0) { | ||
542 | /* there should be no pending command at this point */ | ||
543 | ide_unlock_port(hwif); | ||
544 | goto plug_device; | ||
545 | } | ||
546 | 526 | ||
547 | hwif->rq = rq; | 527 | hwif->rq = rq; |
548 | 528 | ||
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c index 82f252c3ee6e..e246d3d3fbcc 100644 --- a/drivers/ide/ide-ioctls.c +++ b/drivers/ide/ide-ioctls.c | |||
@@ -64,7 +64,8 @@ static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, | |||
64 | goto out; | 64 | goto out; |
65 | } | 65 | } |
66 | 66 | ||
67 | id = kmalloc(size, GFP_KERNEL); | 67 | /* ata_id_to_hd_driveid() relies on 'id' to be fully allocated. */ |
68 | id = kmalloc(ATA_ID_WORDS * 2, GFP_KERNEL); | ||
68 | if (id == NULL) { | 69 | if (id == NULL) { |
69 | rc = -ENOMEM; | 70 | rc = -ENOMEM; |
70 | goto out; | 71 | goto out; |
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index fa047150a1c6..2892b242bbe1 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
@@ -210,6 +210,7 @@ EXPORT_SYMBOL_GPL(ide_in_drive_list); | |||
210 | */ | 210 | */ |
211 | static const struct drive_list_entry ivb_list[] = { | 211 | static const struct drive_list_entry ivb_list[] = { |
212 | { "QUANTUM FIREBALLlct10 05" , "A03.0900" }, | 212 | { "QUANTUM FIREBALLlct10 05" , "A03.0900" }, |
213 | { "QUANTUM FIREBALLlct20 30" , "APL.0900" }, | ||
213 | { "TSSTcorp CDDVDW SH-S202J" , "SB00" }, | 214 | { "TSSTcorp CDDVDW SH-S202J" , "SB00" }, |
214 | { "TSSTcorp CDDVDW SH-S202J" , "SB01" }, | 215 | { "TSSTcorp CDDVDW SH-S202J" , "SB01" }, |
215 | { "TSSTcorp CDDVDW SH-S202N" , "SB00" }, | 216 | { "TSSTcorp CDDVDW SH-S202N" , "SB00" }, |
@@ -329,9 +330,6 @@ int ide_driveid_update(ide_drive_t *drive) | |||
329 | 330 | ||
330 | kfree(id); | 331 | kfree(id); |
331 | 332 | ||
332 | if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive)) | ||
333 | ide_dma_off(drive); | ||
334 | |||
335 | return 1; | 333 | return 1; |
336 | out_err: | 334 | out_err: |
337 | if (rc == 2) | 335 | if (rc == 2) |
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c index c14ca144cffe..ad7be2669dcb 100644 --- a/drivers/ide/ide-pm.c +++ b/drivers/ide/ide-pm.c | |||
@@ -10,9 +10,11 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) | |||
10 | struct request_pm_state rqpm; | 10 | struct request_pm_state rqpm; |
11 | int ret; | 11 | int ret; |
12 | 12 | ||
13 | /* call ACPI _GTM only once */ | 13 | if (ide_port_acpi(hwif)) { |
14 | if ((drive->dn & 1) == 0 || pair == NULL) | 14 | /* call ACPI _GTM only once */ |
15 | ide_acpi_get_timing(hwif); | 15 | if ((drive->dn & 1) == 0 || pair == NULL) |
16 | ide_acpi_get_timing(hwif); | ||
17 | } | ||
16 | 18 | ||
17 | memset(&rqpm, 0, sizeof(rqpm)); | 19 | memset(&rqpm, 0, sizeof(rqpm)); |
18 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 20 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); |
@@ -26,9 +28,11 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) | |||
26 | ret = blk_execute_rq(drive->queue, NULL, rq, 0); | 28 | ret = blk_execute_rq(drive->queue, NULL, rq, 0); |
27 | blk_put_request(rq); | 29 | blk_put_request(rq); |
28 | 30 | ||
29 | /* call ACPI _PS3 only after both devices are suspended */ | 31 | if (ret == 0 && ide_port_acpi(hwif)) { |
30 | if (ret == 0 && ((drive->dn & 1) || pair == NULL)) | 32 | /* call ACPI _PS3 only after both devices are suspended */ |
31 | ide_acpi_set_state(hwif, 0); | 33 | if ((drive->dn & 1) || pair == NULL) |
34 | ide_acpi_set_state(hwif, 0); | ||
35 | } | ||
32 | 36 | ||
33 | return ret; | 37 | return ret; |
34 | } | 38 | } |
@@ -42,13 +46,15 @@ int generic_ide_resume(struct device *dev) | |||
42 | struct request_pm_state rqpm; | 46 | struct request_pm_state rqpm; |
43 | int err; | 47 | int err; |
44 | 48 | ||
45 | /* call ACPI _PS0 / _STM only once */ | 49 | if (ide_port_acpi(hwif)) { |
46 | if ((drive->dn & 1) == 0 || pair == NULL) { | 50 | /* call ACPI _PS0 / _STM only once */ |
47 | ide_acpi_set_state(hwif, 1); | 51 | if ((drive->dn & 1) == 0 || pair == NULL) { |
48 | ide_acpi_push_timing(hwif); | 52 | ide_acpi_set_state(hwif, 1); |
49 | } | 53 | ide_acpi_push_timing(hwif); |
54 | } | ||
50 | 55 | ||
51 | ide_acpi_exec_tfs(drive); | 56 | ide_acpi_exec_tfs(drive); |
57 | } | ||
52 | 58 | ||
53 | memset(&rqpm, 0, sizeof(rqpm)); | 59 | memset(&rqpm, 0, sizeof(rqpm)); |
54 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 60 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); |
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 51af4eea0d36..1bb106f6221a 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -818,6 +818,24 @@ static int ide_port_setup_devices(ide_hwif_t *hwif) | |||
818 | return j; | 818 | return j; |
819 | } | 819 | } |
820 | 820 | ||
821 | static void ide_host_enable_irqs(struct ide_host *host) | ||
822 | { | ||
823 | ide_hwif_t *hwif; | ||
824 | int i; | ||
825 | |||
826 | ide_host_for_each_port(i, hwif, host) { | ||
827 | if (hwif == NULL) | ||
828 | continue; | ||
829 | |||
830 | /* clear any pending IRQs */ | ||
831 | hwif->tp_ops->read_status(hwif); | ||
832 | |||
833 | /* unmask IRQs */ | ||
834 | if (hwif->io_ports.ctl_addr) | ||
835 | hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); | ||
836 | } | ||
837 | } | ||
838 | |||
821 | /* | 839 | /* |
822 | * This routine sets up the IRQ for an IDE interface. | 840 | * This routine sets up the IRQ for an IDE interface. |
823 | */ | 841 | */ |
@@ -831,9 +849,6 @@ static int init_irq (ide_hwif_t *hwif) | |||
831 | if (irq_handler == NULL) | 849 | if (irq_handler == NULL) |
832 | irq_handler = ide_intr; | 850 | irq_handler = ide_intr; |
833 | 851 | ||
834 | if (io_ports->ctl_addr) | ||
835 | hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); | ||
836 | |||
837 | if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) | 852 | if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) |
838 | goto out_up; | 853 | goto out_up; |
839 | 854 | ||
@@ -1404,6 +1419,8 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, | |||
1404 | ide_port_tune_devices(hwif); | 1419 | ide_port_tune_devices(hwif); |
1405 | } | 1420 | } |
1406 | 1421 | ||
1422 | ide_host_enable_irqs(host); | ||
1423 | |||
1407 | ide_host_for_each_port(i, hwif, host) { | 1424 | ide_host_for_each_port(i, hwif, host) { |
1408 | if (hwif == NULL) | 1425 | if (hwif == NULL) |
1409 | continue; | 1426 | continue; |
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index 2adf9cb265da..d114d3a9e1e9 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Cobalt button interface driver. | 2 | * Cobalt button interface driver. |
3 | * | 3 | * |
4 | * Copyright (C) 2007-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2007-2008 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -148,7 +148,7 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev) | |||
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | 150 | ||
151 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 151 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
152 | MODULE_DESCRIPTION("Cobalt button interface driver"); | 152 | MODULE_DESCRIPTION("Cobalt button interface driver"); |
153 | MODULE_LICENSE("GPL"); | 153 | MODULE_LICENSE("GPL"); |
154 | /* work with hotplug and coldplug */ | 154 | /* work with hotplug and coldplug */ |
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 9b60b6b684d9..7c8e7122aaa9 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -75,6 +75,7 @@ config LEDS_ALIX2 | |||
75 | depends on LEDS_CLASS && X86 && EXPERIMENTAL | 75 | depends on LEDS_CLASS && X86 && EXPERIMENTAL |
76 | help | 76 | help |
77 | This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs. | 77 | This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs. |
78 | You have to set leds-alix2.force=1 for boards with Award BIOS. | ||
78 | 79 | ||
79 | config LEDS_H1940 | 80 | config LEDS_H1940 |
80 | tristate "LED Support for iPAQ H1940 device" | 81 | tristate "LED Support for iPAQ H1940 device" |
@@ -145,15 +146,16 @@ config LEDS_GPIO_OF | |||
145 | of_platform devices. For instance, LEDs which are listed in a "dts" | 146 | of_platform devices. For instance, LEDs which are listed in a "dts" |
146 | file. | 147 | file. |
147 | 148 | ||
148 | config LEDS_LP5521 | 149 | config LEDS_LP3944 |
149 | tristate "LED Support for the LP5521 LEDs" | 150 | tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip" |
150 | depends on LEDS_CLASS && I2C | 151 | depends on LEDS_CLASS && I2C |
151 | help | 152 | help |
152 | If you say 'Y' here you get support for the National Semiconductor | 153 | This option enables support for LEDs connected to the National |
153 | LP5521 LED driver used in n8x0 boards. | 154 | Semiconductor LP3944 Lighting Management Unit (LMU) also known as |
155 | Fun Light Chip. | ||
154 | 156 | ||
155 | This driver can be built as a module by choosing 'M'. The module | 157 | To compile this driver as a module, choose M here: the |
156 | will be called leds-lp5521. | 158 | module will be called leds-lp3944. |
157 | 159 | ||
158 | config LEDS_CLEVO_MAIL | 160 | config LEDS_CLEVO_MAIL |
159 | tristate "Mail LED on Clevo notebook" | 161 | tristate "Mail LED on Clevo notebook" |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 2d41c4dcf92f..e8cdcf77a4c3 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
@@ -20,6 +20,7 @@ obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o | |||
20 | obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o | 20 | obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o |
21 | obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o | 21 | obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o |
22 | obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o | 22 | obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o |
23 | obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o | ||
23 | obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o | 24 | obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o |
24 | obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o | 25 | obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o |
25 | obj-$(CONFIG_LEDS_FSG) += leds-fsg.o | 26 | obj-$(CONFIG_LEDS_FSG) += leds-fsg.o |
diff --git a/drivers/leds/leds-alix2.c b/drivers/leds/leds-alix2.c index ddbd7730dfc8..731d4eef3425 100644 --- a/drivers/leds/leds-alix2.c +++ b/drivers/leds/leds-alix2.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | static int force = 0; | 15 | static int force = 0; |
16 | module_param(force, bool, 0444); | 16 | module_param(force, bool, 0444); |
17 | MODULE_PARM_DESC(force, "Assume system has ALIX.2 style LEDs"); | 17 | MODULE_PARM_DESC(force, "Assume system has ALIX.2/ALIX.3 style LEDs"); |
18 | 18 | ||
19 | struct alix_led { | 19 | struct alix_led { |
20 | struct led_classdev cdev; | 20 | struct led_classdev cdev; |
@@ -155,6 +155,11 @@ static int __init alix_led_init(void) | |||
155 | goto out; | 155 | goto out; |
156 | } | 156 | } |
157 | 157 | ||
158 | /* enable output on GPIO for LED 1,2,3 */ | ||
159 | outl(1 << 6, 0x6104); | ||
160 | outl(1 << 9, 0x6184); | ||
161 | outl(1 << 11, 0x6184); | ||
162 | |||
158 | pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0); | 163 | pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0); |
159 | if (!IS_ERR(pdev)) { | 164 | if (!IS_ERR(pdev)) { |
160 | ret = platform_driver_probe(&alix_led_driver, alix_led_probe); | 165 | ret = platform_driver_probe(&alix_led_driver, alix_led_probe); |
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 4149ecb3a9b2..779d7f262c04 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c | |||
@@ -97,6 +97,10 @@ struct bd2802_led { | |||
97 | enum led_ids led_id; | 97 | enum led_ids led_id; |
98 | enum led_colors color; | 98 | enum led_colors color; |
99 | enum led_bits state; | 99 | enum led_bits state; |
100 | |||
101 | /* General attributes of RGB LEDs */ | ||
102 | int wave_pattern; | ||
103 | int rgb_current; | ||
100 | }; | 104 | }; |
101 | 105 | ||
102 | 106 | ||
@@ -254,7 +258,7 @@ static void bd2802_set_on(struct bd2802_led *led, enum led_ids id, | |||
254 | bd2802_reset_cancel(led); | 258 | bd2802_reset_cancel(led); |
255 | 259 | ||
256 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); | 260 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); |
257 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_032); | 261 | bd2802_write_byte(led->client, reg, led->rgb_current); |
258 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); | 262 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); |
259 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); | 263 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); |
260 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); | 264 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); |
@@ -275,9 +279,9 @@ static void bd2802_set_blink(struct bd2802_led *led, enum led_ids id, | |||
275 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); | 279 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); |
276 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); | 280 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); |
277 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); | 281 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); |
278 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_032); | 282 | bd2802_write_byte(led->client, reg, led->rgb_current); |
279 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); | 283 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); |
280 | bd2802_write_byte(led->client, reg, BD2802_PATTERN_HALF); | 284 | bd2802_write_byte(led->client, reg, led->wave_pattern); |
281 | 285 | ||
282 | bd2802_enable(led, id); | 286 | bd2802_enable(led, id); |
283 | bd2802_update_state(led, id, color, BD2802_BLINK); | 287 | bd2802_update_state(led, id, color, BD2802_BLINK); |
@@ -406,7 +410,7 @@ static void bd2802_enable_adv_conf(struct bd2802_led *led) | |||
406 | ret = device_create_file(&led->client->dev, | 410 | ret = device_create_file(&led->client->dev, |
407 | bd2802_addr_attributes[i]); | 411 | bd2802_addr_attributes[i]); |
408 | if (ret) { | 412 | if (ret) { |
409 | dev_err(&led->client->dev, "failed to sysfs file %s\n", | 413 | dev_err(&led->client->dev, "failed: sysfs file %s\n", |
410 | bd2802_addr_attributes[i]->attr.name); | 414 | bd2802_addr_attributes[i]->attr.name); |
411 | goto failed_remove_files; | 415 | goto failed_remove_files; |
412 | } | 416 | } |
@@ -483,6 +487,52 @@ static struct device_attribute bd2802_adv_conf_attr = { | |||
483 | .store = bd2802_store_adv_conf, | 487 | .store = bd2802_store_adv_conf, |
484 | }; | 488 | }; |
485 | 489 | ||
490 | #define BD2802_CONTROL_ATTR(attr_name, name_str) \ | ||
491 | static ssize_t bd2802_show_##attr_name(struct device *dev, \ | ||
492 | struct device_attribute *attr, char *buf) \ | ||
493 | { \ | ||
494 | struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\ | ||
495 | ssize_t ret; \ | ||
496 | down_read(&led->rwsem); \ | ||
497 | ret = sprintf(buf, "0x%02x\n", led->attr_name); \ | ||
498 | up_read(&led->rwsem); \ | ||
499 | return ret; \ | ||
500 | } \ | ||
501 | static ssize_t bd2802_store_##attr_name(struct device *dev, \ | ||
502 | struct device_attribute *attr, const char *buf, size_t count) \ | ||
503 | { \ | ||
504 | struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\ | ||
505 | unsigned long val; \ | ||
506 | int ret; \ | ||
507 | if (!count) \ | ||
508 | return -EINVAL; \ | ||
509 | ret = strict_strtoul(buf, 16, &val); \ | ||
510 | if (ret) \ | ||
511 | return ret; \ | ||
512 | down_write(&led->rwsem); \ | ||
513 | led->attr_name = val; \ | ||
514 | up_write(&led->rwsem); \ | ||
515 | return count; \ | ||
516 | } \ | ||
517 | static struct device_attribute bd2802_##attr_name##_attr = { \ | ||
518 | .attr = { \ | ||
519 | .name = name_str, \ | ||
520 | .mode = 0644, \ | ||
521 | .owner = THIS_MODULE \ | ||
522 | }, \ | ||
523 | .show = bd2802_show_##attr_name, \ | ||
524 | .store = bd2802_store_##attr_name, \ | ||
525 | }; | ||
526 | |||
527 | BD2802_CONTROL_ATTR(wave_pattern, "wave_pattern"); | ||
528 | BD2802_CONTROL_ATTR(rgb_current, "rgb_current"); | ||
529 | |||
530 | static struct device_attribute *bd2802_attributes[] = { | ||
531 | &bd2802_adv_conf_attr, | ||
532 | &bd2802_wave_pattern_attr, | ||
533 | &bd2802_rgb_current_attr, | ||
534 | }; | ||
535 | |||
486 | static void bd2802_led_work(struct work_struct *work) | 536 | static void bd2802_led_work(struct work_struct *work) |
487 | { | 537 | { |
488 | struct bd2802_led *led = container_of(work, struct bd2802_led, work); | 538 | struct bd2802_led *led = container_of(work, struct bd2802_led, work); |
@@ -538,7 +588,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
538 | led->cdev_led1r.brightness = LED_OFF; | 588 | led->cdev_led1r.brightness = LED_OFF; |
539 | led->cdev_led1r.brightness_set = bd2802_set_led1r_brightness; | 589 | led->cdev_led1r.brightness_set = bd2802_set_led1r_brightness; |
540 | led->cdev_led1r.blink_set = bd2802_set_led1r_blink; | 590 | led->cdev_led1r.blink_set = bd2802_set_led1r_blink; |
541 | led->cdev_led1r.flags |= LED_CORE_SUSPENDRESUME; | ||
542 | 591 | ||
543 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1r); | 592 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1r); |
544 | if (ret < 0) { | 593 | if (ret < 0) { |
@@ -551,7 +600,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
551 | led->cdev_led1g.brightness = LED_OFF; | 600 | led->cdev_led1g.brightness = LED_OFF; |
552 | led->cdev_led1g.brightness_set = bd2802_set_led1g_brightness; | 601 | led->cdev_led1g.brightness_set = bd2802_set_led1g_brightness; |
553 | led->cdev_led1g.blink_set = bd2802_set_led1g_blink; | 602 | led->cdev_led1g.blink_set = bd2802_set_led1g_blink; |
554 | led->cdev_led1g.flags |= LED_CORE_SUSPENDRESUME; | ||
555 | 603 | ||
556 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1g); | 604 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1g); |
557 | if (ret < 0) { | 605 | if (ret < 0) { |
@@ -564,7 +612,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
564 | led->cdev_led1b.brightness = LED_OFF; | 612 | led->cdev_led1b.brightness = LED_OFF; |
565 | led->cdev_led1b.brightness_set = bd2802_set_led1b_brightness; | 613 | led->cdev_led1b.brightness_set = bd2802_set_led1b_brightness; |
566 | led->cdev_led1b.blink_set = bd2802_set_led1b_blink; | 614 | led->cdev_led1b.blink_set = bd2802_set_led1b_blink; |
567 | led->cdev_led1b.flags |= LED_CORE_SUSPENDRESUME; | ||
568 | 615 | ||
569 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1b); | 616 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1b); |
570 | if (ret < 0) { | 617 | if (ret < 0) { |
@@ -577,7 +624,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
577 | led->cdev_led2r.brightness = LED_OFF; | 624 | led->cdev_led2r.brightness = LED_OFF; |
578 | led->cdev_led2r.brightness_set = bd2802_set_led2r_brightness; | 625 | led->cdev_led2r.brightness_set = bd2802_set_led2r_brightness; |
579 | led->cdev_led2r.blink_set = bd2802_set_led2r_blink; | 626 | led->cdev_led2r.blink_set = bd2802_set_led2r_blink; |
580 | led->cdev_led2r.flags |= LED_CORE_SUSPENDRESUME; | ||
581 | 627 | ||
582 | ret = led_classdev_register(&led->client->dev, &led->cdev_led2r); | 628 | ret = led_classdev_register(&led->client->dev, &led->cdev_led2r); |
583 | if (ret < 0) { | 629 | if (ret < 0) { |
@@ -590,7 +636,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
590 | led->cdev_led2g.brightness = LED_OFF; | 636 | led->cdev_led2g.brightness = LED_OFF; |
591 | led->cdev_led2g.brightness_set = bd2802_set_led2g_brightness; | 637 | led->cdev_led2g.brightness_set = bd2802_set_led2g_brightness; |
592 | led->cdev_led2g.blink_set = bd2802_set_led2g_blink; | 638 | led->cdev_led2g.blink_set = bd2802_set_led2g_blink; |
593 | led->cdev_led2g.flags |= LED_CORE_SUSPENDRESUME; | ||
594 | 639 | ||
595 | ret = led_classdev_register(&led->client->dev, &led->cdev_led2g); | 640 | ret = led_classdev_register(&led->client->dev, &led->cdev_led2g); |
596 | if (ret < 0) { | 641 | if (ret < 0) { |
@@ -640,7 +685,7 @@ static int __devinit bd2802_probe(struct i2c_client *client, | |||
640 | { | 685 | { |
641 | struct bd2802_led *led; | 686 | struct bd2802_led *led; |
642 | struct bd2802_led_platform_data *pdata; | 687 | struct bd2802_led_platform_data *pdata; |
643 | int ret; | 688 | int ret, i; |
644 | 689 | ||
645 | led = kzalloc(sizeof(struct bd2802_led), GFP_KERNEL); | 690 | led = kzalloc(sizeof(struct bd2802_led), GFP_KERNEL); |
646 | if (!led) { | 691 | if (!led) { |
@@ -670,13 +715,20 @@ static int __devinit bd2802_probe(struct i2c_client *client, | |||
670 | /* To save the power, reset BD2802 after detecting */ | 715 | /* To save the power, reset BD2802 after detecting */ |
671 | gpio_set_value(led->pdata->reset_gpio, 0); | 716 | gpio_set_value(led->pdata->reset_gpio, 0); |
672 | 717 | ||
718 | /* Default attributes */ | ||
719 | led->wave_pattern = BD2802_PATTERN_HALF; | ||
720 | led->rgb_current = BD2802_CURRENT_032; | ||
721 | |||
673 | init_rwsem(&led->rwsem); | 722 | init_rwsem(&led->rwsem); |
674 | 723 | ||
675 | ret = device_create_file(&client->dev, &bd2802_adv_conf_attr); | 724 | for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) { |
676 | if (ret) { | 725 | ret = device_create_file(&led->client->dev, |
677 | dev_err(&client->dev, "failed to create sysfs file %s\n", | 726 | bd2802_attributes[i]); |
678 | bd2802_adv_conf_attr.attr.name); | 727 | if (ret) { |
679 | goto failed_free; | 728 | dev_err(&led->client->dev, "failed: sysfs file %s\n", |
729 | bd2802_attributes[i]->attr.name); | ||
730 | goto failed_unregister_dev_file; | ||
731 | } | ||
680 | } | 732 | } |
681 | 733 | ||
682 | ret = bd2802_register_led_classdev(led); | 734 | ret = bd2802_register_led_classdev(led); |
@@ -686,7 +738,8 @@ static int __devinit bd2802_probe(struct i2c_client *client, | |||
686 | return 0; | 738 | return 0; |
687 | 739 | ||
688 | failed_unregister_dev_file: | 740 | failed_unregister_dev_file: |
689 | device_remove_file(&client->dev, &bd2802_adv_conf_attr); | 741 | for (i--; i >= 0; i--) |
742 | device_remove_file(&led->client->dev, bd2802_attributes[i]); | ||
690 | failed_free: | 743 | failed_free: |
691 | i2c_set_clientdata(client, NULL); | 744 | i2c_set_clientdata(client, NULL); |
692 | kfree(led); | 745 | kfree(led); |
@@ -697,12 +750,14 @@ failed_free: | |||
697 | static int __exit bd2802_remove(struct i2c_client *client) | 750 | static int __exit bd2802_remove(struct i2c_client *client) |
698 | { | 751 | { |
699 | struct bd2802_led *led = i2c_get_clientdata(client); | 752 | struct bd2802_led *led = i2c_get_clientdata(client); |
753 | int i; | ||
700 | 754 | ||
701 | bd2802_unregister_led_classdev(led); | ||
702 | gpio_set_value(led->pdata->reset_gpio, 0); | 755 | gpio_set_value(led->pdata->reset_gpio, 0); |
756 | bd2802_unregister_led_classdev(led); | ||
703 | if (led->adf_on) | 757 | if (led->adf_on) |
704 | bd2802_disable_adv_conf(led); | 758 | bd2802_disable_adv_conf(led); |
705 | device_remove_file(&client->dev, &bd2802_adv_conf_attr); | 759 | for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) |
760 | device_remove_file(&led->client->dev, bd2802_attributes[i]); | ||
706 | i2c_set_clientdata(client, NULL); | 761 | i2c_set_clientdata(client, NULL); |
707 | kfree(led); | 762 | kfree(led); |
708 | 763 | ||
@@ -723,8 +778,7 @@ static int bd2802_resume(struct i2c_client *client) | |||
723 | struct bd2802_led *led = i2c_get_clientdata(client); | 778 | struct bd2802_led *led = i2c_get_clientdata(client); |
724 | 779 | ||
725 | if (!bd2802_is_all_off(led) || led->adf_on) { | 780 | if (!bd2802_is_all_off(led) || led->adf_on) { |
726 | gpio_set_value(led->pdata->reset_gpio, 1); | 781 | bd2802_reset_cancel(led); |
727 | udelay(100); | ||
728 | bd2802_restore_state(led); | 782 | bd2802_restore_state(led); |
729 | } | 783 | } |
730 | 784 | ||
@@ -762,4 +816,4 @@ module_exit(bd2802_exit); | |||
762 | 816 | ||
763 | MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); | 817 | MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); |
764 | MODULE_DESCRIPTION("BD2802 LED driver"); | 818 | MODULE_DESCRIPTION("BD2802 LED driver"); |
765 | MODULE_LICENSE("GPL"); | 819 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c index ff0e8c3fbf9b..5f1ce810815f 100644 --- a/drivers/leds/leds-cobalt-raq.c +++ b/drivers/leds/leds-cobalt-raq.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * LEDs driver for the Cobalt Raq series. | 2 | * LEDs driver for the Cobalt Raq series. |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index d2109054de85..6b06638eb5b4 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c | |||
@@ -76,7 +76,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template, | |||
76 | struct gpio_led_data *led_dat, struct device *parent, | 76 | struct gpio_led_data *led_dat, struct device *parent, |
77 | int (*blink_set)(unsigned, unsigned long *, unsigned long *)) | 77 | int (*blink_set)(unsigned, unsigned long *, unsigned long *)) |
78 | { | 78 | { |
79 | int ret; | 79 | int ret, state; |
80 | 80 | ||
81 | /* skip leds that aren't available */ | 81 | /* skip leds that aren't available */ |
82 | if (!gpio_is_valid(template->gpio)) { | 82 | if (!gpio_is_valid(template->gpio)) { |
@@ -99,11 +99,15 @@ static int __devinit create_gpio_led(const struct gpio_led *template, | |||
99 | led_dat->cdev.blink_set = gpio_blink_set; | 99 | led_dat->cdev.blink_set = gpio_blink_set; |
100 | } | 100 | } |
101 | led_dat->cdev.brightness_set = gpio_led_set; | 101 | led_dat->cdev.brightness_set = gpio_led_set; |
102 | led_dat->cdev.brightness = LED_OFF; | 102 | if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) |
103 | state = !!gpio_get_value(led_dat->gpio) ^ led_dat->active_low; | ||
104 | else | ||
105 | state = (template->default_state == LEDS_GPIO_DEFSTATE_ON); | ||
106 | led_dat->cdev.brightness = state ? LED_FULL : LED_OFF; | ||
103 | if (!template->retain_state_suspended) | 107 | if (!template->retain_state_suspended) |
104 | led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; | 108 | led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; |
105 | 109 | ||
106 | ret = gpio_direction_output(led_dat->gpio, led_dat->active_low); | 110 | ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state); |
107 | if (ret < 0) | 111 | if (ret < 0) |
108 | goto err; | 112 | goto err; |
109 | 113 | ||
@@ -129,7 +133,7 @@ static void delete_gpio_led(struct gpio_led_data *led) | |||
129 | } | 133 | } |
130 | 134 | ||
131 | #ifdef CONFIG_LEDS_GPIO_PLATFORM | 135 | #ifdef CONFIG_LEDS_GPIO_PLATFORM |
132 | static int gpio_led_probe(struct platform_device *pdev) | 136 | static int __devinit gpio_led_probe(struct platform_device *pdev) |
133 | { | 137 | { |
134 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; | 138 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; |
135 | struct gpio_led_data *leds_data; | 139 | struct gpio_led_data *leds_data; |
@@ -223,12 +227,22 @@ static int __devinit of_gpio_leds_probe(struct of_device *ofdev, | |||
223 | memset(&led, 0, sizeof(led)); | 227 | memset(&led, 0, sizeof(led)); |
224 | for_each_child_of_node(np, child) { | 228 | for_each_child_of_node(np, child) { |
225 | enum of_gpio_flags flags; | 229 | enum of_gpio_flags flags; |
230 | const char *state; | ||
226 | 231 | ||
227 | led.gpio = of_get_gpio_flags(child, 0, &flags); | 232 | led.gpio = of_get_gpio_flags(child, 0, &flags); |
228 | led.active_low = flags & OF_GPIO_ACTIVE_LOW; | 233 | led.active_low = flags & OF_GPIO_ACTIVE_LOW; |
229 | led.name = of_get_property(child, "label", NULL) ? : child->name; | 234 | led.name = of_get_property(child, "label", NULL) ? : child->name; |
230 | led.default_trigger = | 235 | led.default_trigger = |
231 | of_get_property(child, "linux,default-trigger", NULL); | 236 | of_get_property(child, "linux,default-trigger", NULL); |
237 | state = of_get_property(child, "default-state", NULL); | ||
238 | if (state) { | ||
239 | if (!strcmp(state, "keep")) | ||
240 | led.default_state = LEDS_GPIO_DEFSTATE_KEEP; | ||
241 | else if(!strcmp(state, "on")) | ||
242 | led.default_state = LEDS_GPIO_DEFSTATE_ON; | ||
243 | else | ||
244 | led.default_state = LEDS_GPIO_DEFSTATE_OFF; | ||
245 | } | ||
232 | 246 | ||
233 | ret = create_gpio_led(&led, &pdata->led_data[pdata->num_leds++], | 247 | ret = create_gpio_led(&led, &pdata->led_data[pdata->num_leds++], |
234 | &ofdev->dev, NULL); | 248 | &ofdev->dev, NULL); |
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c new file mode 100644 index 000000000000..5946208ba26e --- /dev/null +++ b/drivers/leds/leds-lp3944.c | |||
@@ -0,0 +1,466 @@ | |||
1 | /* | ||
2 | * leds-lp3944.c - driver for National Semiconductor LP3944 Funlight Chip | ||
3 | * | ||
4 | * Copyright (C) 2009 Antonio Ospite <ospite@studenti.unina.it> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | * I2C driver for National Semiconductor LP3944 Funlight Chip | ||
14 | * http://www.national.com/pf/LP/LP3944.html | ||
15 | * | ||
16 | * This helper chip can drive up to 8 leds, with two programmable DIM modes; | ||
17 | * it could even be used as a gpio expander but this driver assumes it is used | ||
18 | * as a led controller. | ||
19 | * | ||
20 | * The DIM modes are used to set _blink_ patterns for leds, the pattern is | ||
21 | * specified supplying two parameters: | ||
22 | * - period: from 0s to 1.6s | ||
23 | * - duty cycle: percentage of the period the led is on, from 0 to 100 | ||
24 | * | ||
25 | * LP3944 can be found on Motorola A910 smartphone, where it drives the rgb | ||
26 | * leds, the camera flash light and the displays backlights. | ||
27 | */ | ||
28 | |||
29 | #include <linux/module.h> | ||
30 | #include <linux/i2c.h> | ||
31 | #include <linux/leds.h> | ||
32 | #include <linux/mutex.h> | ||
33 | #include <linux/workqueue.h> | ||
34 | #include <linux/leds-lp3944.h> | ||
35 | |||
36 | /* Read Only Registers */ | ||
37 | #define LP3944_REG_INPUT1 0x00 /* LEDs 0-7 InputRegister (Read Only) */ | ||
38 | #define LP3944_REG_REGISTER1 0x01 /* None (Read Only) */ | ||
39 | |||
40 | #define LP3944_REG_PSC0 0x02 /* Frequency Prescaler 0 (R/W) */ | ||
41 | #define LP3944_REG_PWM0 0x03 /* PWM Register 0 (R/W) */ | ||
42 | #define LP3944_REG_PSC1 0x04 /* Frequency Prescaler 1 (R/W) */ | ||
43 | #define LP3944_REG_PWM1 0x05 /* PWM Register 1 (R/W) */ | ||
44 | #define LP3944_REG_LS0 0x06 /* LEDs 0-3 Selector (R/W) */ | ||
45 | #define LP3944_REG_LS1 0x07 /* LEDs 4-7 Selector (R/W) */ | ||
46 | |||
47 | /* These registers are not used to control leds in LP3944, they can store | ||
48 | * arbitrary values which the chip will ignore. | ||
49 | */ | ||
50 | #define LP3944_REG_REGISTER8 0x08 | ||
51 | #define LP3944_REG_REGISTER9 0x09 | ||
52 | |||
53 | #define LP3944_DIM0 0 | ||
54 | #define LP3944_DIM1 1 | ||
55 | |||
56 | /* period in ms */ | ||
57 | #define LP3944_PERIOD_MIN 0 | ||
58 | #define LP3944_PERIOD_MAX 1600 | ||
59 | |||
60 | /* duty cycle is a percentage */ | ||
61 | #define LP3944_DUTY_CYCLE_MIN 0 | ||
62 | #define LP3944_DUTY_CYCLE_MAX 100 | ||
63 | |||
64 | #define ldev_to_led(c) container_of(c, struct lp3944_led_data, ldev) | ||
65 | |||
66 | /* Saved data */ | ||
67 | struct lp3944_led_data { | ||
68 | u8 id; | ||
69 | enum lp3944_type type; | ||
70 | enum lp3944_status status; | ||
71 | struct led_classdev ldev; | ||
72 | struct i2c_client *client; | ||
73 | struct work_struct work; | ||
74 | }; | ||
75 | |||
76 | struct lp3944_data { | ||
77 | struct mutex lock; | ||
78 | struct i2c_client *client; | ||
79 | struct lp3944_led_data leds[LP3944_LEDS_MAX]; | ||
80 | }; | ||
81 | |||
82 | static int lp3944_reg_read(struct i2c_client *client, u8 reg, u8 *value) | ||
83 | { | ||
84 | int tmp; | ||
85 | |||
86 | tmp = i2c_smbus_read_byte_data(client, reg); | ||
87 | if (tmp < 0) | ||
88 | return -EINVAL; | ||
89 | |||
90 | *value = tmp; | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static int lp3944_reg_write(struct i2c_client *client, u8 reg, u8 value) | ||
96 | { | ||
97 | return i2c_smbus_write_byte_data(client, reg, value); | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * Set the period for DIM status | ||
102 | * | ||
103 | * @client: the i2c client | ||
104 | * @dim: either LP3944_DIM0 or LP3944_DIM1 | ||
105 | * @period: period of a blink, that is a on/off cycle, expressed in ms. | ||
106 | */ | ||
107 | static int lp3944_dim_set_period(struct i2c_client *client, u8 dim, u16 period) | ||
108 | { | ||
109 | u8 psc_reg; | ||
110 | u8 psc_value; | ||
111 | int err; | ||
112 | |||
113 | if (dim == LP3944_DIM0) | ||
114 | psc_reg = LP3944_REG_PSC0; | ||
115 | else if (dim == LP3944_DIM1) | ||
116 | psc_reg = LP3944_REG_PSC1; | ||
117 | else | ||
118 | return -EINVAL; | ||
119 | |||
120 | /* Convert period to Prescaler value */ | ||
121 | if (period > LP3944_PERIOD_MAX) | ||
122 | return -EINVAL; | ||
123 | |||
124 | psc_value = (period * 255) / LP3944_PERIOD_MAX; | ||
125 | |||
126 | err = lp3944_reg_write(client, psc_reg, psc_value); | ||
127 | |||
128 | return err; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * Set the duty cycle for DIM status | ||
133 | * | ||
134 | * @client: the i2c client | ||
135 | * @dim: either LP3944_DIM0 or LP3944_DIM1 | ||
136 | * @duty_cycle: percentage of a period during which a led is ON | ||
137 | */ | ||
138 | static int lp3944_dim_set_dutycycle(struct i2c_client *client, u8 dim, | ||
139 | u8 duty_cycle) | ||
140 | { | ||
141 | u8 pwm_reg; | ||
142 | u8 pwm_value; | ||
143 | int err; | ||
144 | |||
145 | if (dim == LP3944_DIM0) | ||
146 | pwm_reg = LP3944_REG_PWM0; | ||
147 | else if (dim == LP3944_DIM1) | ||
148 | pwm_reg = LP3944_REG_PWM1; | ||
149 | else | ||
150 | return -EINVAL; | ||
151 | |||
152 | /* Convert duty cycle to PWM value */ | ||
153 | if (duty_cycle > LP3944_DUTY_CYCLE_MAX) | ||
154 | return -EINVAL; | ||
155 | |||
156 | pwm_value = (duty_cycle * 255) / LP3944_DUTY_CYCLE_MAX; | ||
157 | |||
158 | err = lp3944_reg_write(client, pwm_reg, pwm_value); | ||
159 | |||
160 | return err; | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * Set the led status | ||
165 | * | ||
166 | * @led: a lp3944_led_data structure | ||
167 | * @status: one of LP3944_LED_STATUS_OFF | ||
168 | * LP3944_LED_STATUS_ON | ||
169 | * LP3944_LED_STATUS_DIM0 | ||
170 | * LP3944_LED_STATUS_DIM1 | ||
171 | */ | ||
172 | static int lp3944_led_set(struct lp3944_led_data *led, u8 status) | ||
173 | { | ||
174 | struct lp3944_data *data = i2c_get_clientdata(led->client); | ||
175 | u8 id = led->id; | ||
176 | u8 reg; | ||
177 | u8 val = 0; | ||
178 | int err; | ||
179 | |||
180 | dev_dbg(&led->client->dev, "%s: %s, status before normalization:%d\n", | ||
181 | __func__, led->ldev.name, status); | ||
182 | |||
183 | switch (id) { | ||
184 | case LP3944_LED0: | ||
185 | case LP3944_LED1: | ||
186 | case LP3944_LED2: | ||
187 | case LP3944_LED3: | ||
188 | reg = LP3944_REG_LS0; | ||
189 | break; | ||
190 | case LP3944_LED4: | ||
191 | case LP3944_LED5: | ||
192 | case LP3944_LED6: | ||
193 | case LP3944_LED7: | ||
194 | id -= LP3944_LED4; | ||
195 | reg = LP3944_REG_LS1; | ||
196 | break; | ||
197 | default: | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | |||
201 | if (status > LP3944_LED_STATUS_DIM1) | ||
202 | return -EINVAL; | ||
203 | |||
204 | /* invert only 0 and 1, leave unchanged the other values, | ||
205 | * remember we are abusing status to set blink patterns | ||
206 | */ | ||
207 | if (led->type == LP3944_LED_TYPE_LED_INVERTED && status < 2) | ||
208 | status = 1 - status; | ||
209 | |||
210 | mutex_lock(&data->lock); | ||
211 | lp3944_reg_read(led->client, reg, &val); | ||
212 | |||
213 | val &= ~(LP3944_LED_STATUS_MASK << (id << 1)); | ||
214 | val |= (status << (id << 1)); | ||
215 | |||
216 | dev_dbg(&led->client->dev, "%s: %s, reg:%d id:%d status:%d val:%#x\n", | ||
217 | __func__, led->ldev.name, reg, id, status, val); | ||
218 | |||
219 | /* set led status */ | ||
220 | err = lp3944_reg_write(led->client, reg, val); | ||
221 | mutex_unlock(&data->lock); | ||
222 | |||
223 | return err; | ||
224 | } | ||
225 | |||
226 | static int lp3944_led_set_blink(struct led_classdev *led_cdev, | ||
227 | unsigned long *delay_on, | ||
228 | unsigned long *delay_off) | ||
229 | { | ||
230 | struct lp3944_led_data *led = ldev_to_led(led_cdev); | ||
231 | u16 period; | ||
232 | u8 duty_cycle; | ||
233 | int err; | ||
234 | |||
235 | /* units are in ms */ | ||
236 | if (*delay_on + *delay_off > LP3944_PERIOD_MAX) | ||
237 | return -EINVAL; | ||
238 | |||
239 | if (*delay_on == 0 && *delay_off == 0) { | ||
240 | /* Special case: the leds subsystem requires a default user | ||
241 | * friendly blink pattern for the LED. Let's blink the led | ||
242 | * slowly (1Hz). | ||
243 | */ | ||
244 | *delay_on = 500; | ||
245 | *delay_off = 500; | ||
246 | } | ||
247 | |||
248 | period = (*delay_on) + (*delay_off); | ||
249 | |||
250 | /* duty_cycle is the percentage of period during which the led is ON */ | ||
251 | duty_cycle = 100 * (*delay_on) / period; | ||
252 | |||
253 | /* invert duty cycle for inverted leds, this has the same effect of | ||
254 | * swapping delay_on and delay_off | ||
255 | */ | ||
256 | if (led->type == LP3944_LED_TYPE_LED_INVERTED) | ||
257 | duty_cycle = 100 - duty_cycle; | ||
258 | |||
259 | /* NOTE: using always the first DIM mode, this means that all leds | ||
260 | * will have the same blinking pattern. | ||
261 | * | ||
262 | * We could find a way later to have two leds blinking in hardware | ||
263 | * with different patterns at the same time, falling back to software | ||
264 | * control for the other ones. | ||
265 | */ | ||
266 | err = lp3944_dim_set_period(led->client, LP3944_DIM0, period); | ||
267 | if (err) | ||
268 | return err; | ||
269 | |||
270 | err = lp3944_dim_set_dutycycle(led->client, LP3944_DIM0, duty_cycle); | ||
271 | if (err) | ||
272 | return err; | ||
273 | |||
274 | dev_dbg(&led->client->dev, "%s: OK hardware accelerated blink!\n", | ||
275 | __func__); | ||
276 | |||
277 | led->status = LP3944_LED_STATUS_DIM0; | ||
278 | schedule_work(&led->work); | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static void lp3944_led_set_brightness(struct led_classdev *led_cdev, | ||
284 | enum led_brightness brightness) | ||
285 | { | ||
286 | struct lp3944_led_data *led = ldev_to_led(led_cdev); | ||
287 | |||
288 | dev_dbg(&led->client->dev, "%s: %s, %d\n", | ||
289 | __func__, led_cdev->name, brightness); | ||
290 | |||
291 | led->status = brightness; | ||
292 | schedule_work(&led->work); | ||
293 | } | ||
294 | |||
295 | static void lp3944_led_work(struct work_struct *work) | ||
296 | { | ||
297 | struct lp3944_led_data *led; | ||
298 | |||
299 | led = container_of(work, struct lp3944_led_data, work); | ||
300 | lp3944_led_set(led, led->status); | ||
301 | } | ||
302 | |||
303 | static int lp3944_configure(struct i2c_client *client, | ||
304 | struct lp3944_data *data, | ||
305 | struct lp3944_platform_data *pdata) | ||
306 | { | ||
307 | int i, err = 0; | ||
308 | |||
309 | for (i = 0; i < pdata->leds_size; i++) { | ||
310 | struct lp3944_led *pled = &pdata->leds[i]; | ||
311 | struct lp3944_led_data *led = &data->leds[i]; | ||
312 | led->client = client; | ||
313 | led->id = i; | ||
314 | |||
315 | switch (pled->type) { | ||
316 | |||
317 | case LP3944_LED_TYPE_LED: | ||
318 | case LP3944_LED_TYPE_LED_INVERTED: | ||
319 | led->type = pled->type; | ||
320 | led->status = pled->status; | ||
321 | led->ldev.name = pled->name; | ||
322 | led->ldev.max_brightness = 1; | ||
323 | led->ldev.brightness_set = lp3944_led_set_brightness; | ||
324 | led->ldev.blink_set = lp3944_led_set_blink; | ||
325 | led->ldev.flags = LED_CORE_SUSPENDRESUME; | ||
326 | |||
327 | INIT_WORK(&led->work, lp3944_led_work); | ||
328 | err = led_classdev_register(&client->dev, &led->ldev); | ||
329 | if (err < 0) { | ||
330 | dev_err(&client->dev, | ||
331 | "couldn't register LED %s\n", | ||
332 | led->ldev.name); | ||
333 | goto exit; | ||
334 | } | ||
335 | |||
336 | /* to expose the default value to userspace */ | ||
337 | led->ldev.brightness = led->status; | ||
338 | |||
339 | /* Set the default led status */ | ||
340 | err = lp3944_led_set(led, led->status); | ||
341 | if (err < 0) { | ||
342 | dev_err(&client->dev, | ||
343 | "%s couldn't set STATUS %d\n", | ||
344 | led->ldev.name, led->status); | ||
345 | goto exit; | ||
346 | } | ||
347 | break; | ||
348 | |||
349 | case LP3944_LED_TYPE_NONE: | ||
350 | default: | ||
351 | break; | ||
352 | |||
353 | } | ||
354 | } | ||
355 | return 0; | ||
356 | |||
357 | exit: | ||
358 | if (i > 0) | ||
359 | for (i = i - 1; i >= 0; i--) | ||
360 | switch (pdata->leds[i].type) { | ||
361 | |||
362 | case LP3944_LED_TYPE_LED: | ||
363 | case LP3944_LED_TYPE_LED_INVERTED: | ||
364 | led_classdev_unregister(&data->leds[i].ldev); | ||
365 | cancel_work_sync(&data->leds[i].work); | ||
366 | break; | ||
367 | |||
368 | case LP3944_LED_TYPE_NONE: | ||
369 | default: | ||
370 | break; | ||
371 | } | ||
372 | |||
373 | return err; | ||
374 | } | ||
375 | |||
376 | static int __devinit lp3944_probe(struct i2c_client *client, | ||
377 | const struct i2c_device_id *id) | ||
378 | { | ||
379 | struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data; | ||
380 | struct lp3944_data *data; | ||
381 | |||
382 | if (lp3944_pdata == NULL) { | ||
383 | dev_err(&client->dev, "no platform data\n"); | ||
384 | return -EINVAL; | ||
385 | } | ||
386 | |||
387 | /* Let's see whether this adapter can support what we need. */ | ||
388 | if (!i2c_check_functionality(client->adapter, | ||
389 | I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
390 | dev_err(&client->dev, "insufficient functionality!\n"); | ||
391 | return -ENODEV; | ||
392 | } | ||
393 | |||
394 | data = kzalloc(sizeof(struct lp3944_data), GFP_KERNEL); | ||
395 | if (!data) | ||
396 | return -ENOMEM; | ||
397 | |||
398 | data->client = client; | ||
399 | i2c_set_clientdata(client, data); | ||
400 | |||
401 | mutex_init(&data->lock); | ||
402 | |||
403 | dev_info(&client->dev, "lp3944 enabled\n"); | ||
404 | |||
405 | lp3944_configure(client, data, lp3944_pdata); | ||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | static int __devexit lp3944_remove(struct i2c_client *client) | ||
410 | { | ||
411 | struct lp3944_platform_data *pdata = client->dev.platform_data; | ||
412 | struct lp3944_data *data = i2c_get_clientdata(client); | ||
413 | int i; | ||
414 | |||
415 | for (i = 0; i < pdata->leds_size; i++) | ||
416 | switch (data->leds[i].type) { | ||
417 | case LP3944_LED_TYPE_LED: | ||
418 | case LP3944_LED_TYPE_LED_INVERTED: | ||
419 | led_classdev_unregister(&data->leds[i].ldev); | ||
420 | cancel_work_sync(&data->leds[i].work); | ||
421 | break; | ||
422 | |||
423 | case LP3944_LED_TYPE_NONE: | ||
424 | default: | ||
425 | break; | ||
426 | } | ||
427 | |||
428 | kfree(data); | ||
429 | i2c_set_clientdata(client, NULL); | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | /* lp3944 i2c driver struct */ | ||
435 | static const struct i2c_device_id lp3944_id[] = { | ||
436 | {"lp3944", 0}, | ||
437 | {} | ||
438 | }; | ||
439 | |||
440 | MODULE_DEVICE_TABLE(i2c, lp3944_id); | ||
441 | |||
442 | static struct i2c_driver lp3944_driver = { | ||
443 | .driver = { | ||
444 | .name = "lp3944", | ||
445 | }, | ||
446 | .probe = lp3944_probe, | ||
447 | .remove = __devexit_p(lp3944_remove), | ||
448 | .id_table = lp3944_id, | ||
449 | }; | ||
450 | |||
451 | static int __init lp3944_module_init(void) | ||
452 | { | ||
453 | return i2c_add_driver(&lp3944_driver); | ||
454 | } | ||
455 | |||
456 | static void __exit lp3944_module_exit(void) | ||
457 | { | ||
458 | i2c_del_driver(&lp3944_driver); | ||
459 | } | ||
460 | |||
461 | module_init(lp3944_module_init); | ||
462 | module_exit(lp3944_module_exit); | ||
463 | |||
464 | MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); | ||
465 | MODULE_DESCRIPTION("LP3944 Fun Light Chip"); | ||
466 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index 3937244fdcab..dba8921240f2 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c | |||
@@ -35,7 +35,7 @@ struct pca9532_data { | |||
35 | struct pca9532_led leds[16]; | 35 | struct pca9532_led leds[16]; |
36 | struct mutex update_lock; | 36 | struct mutex update_lock; |
37 | struct input_dev *idev; | 37 | struct input_dev *idev; |
38 | struct work_struct work; | 38 | struct work_struct work; |
39 | u8 pwm[2]; | 39 | u8 pwm[2]; |
40 | u8 psc[2]; | 40 | u8 psc[2]; |
41 | }; | 41 | }; |
@@ -87,14 +87,14 @@ static int pca9532_calcpwm(struct i2c_client *client, int pwm, int blink, | |||
87 | if (b > 0xFF) | 87 | if (b > 0xFF) |
88 | return -EINVAL; | 88 | return -EINVAL; |
89 | data->pwm[pwm] = b; | 89 | data->pwm[pwm] = b; |
90 | data->psc[pwm] = blink; | 90 | data->psc[pwm] = blink; |
91 | return 0; | 91 | return 0; |
92 | } | 92 | } |
93 | 93 | ||
94 | static int pca9532_setpwm(struct i2c_client *client, int pwm) | 94 | static int pca9532_setpwm(struct i2c_client *client, int pwm) |
95 | { | 95 | { |
96 | struct pca9532_data *data = i2c_get_clientdata(client); | 96 | struct pca9532_data *data = i2c_get_clientdata(client); |
97 | mutex_lock(&data->update_lock); | 97 | mutex_lock(&data->update_lock); |
98 | i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(pwm), | 98 | i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(pwm), |
99 | data->pwm[pwm]); | 99 | data->pwm[pwm]); |
100 | i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(pwm), | 100 | i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(pwm), |
@@ -132,11 +132,11 @@ static void pca9532_set_brightness(struct led_classdev *led_cdev, | |||
132 | led->state = PCA9532_ON; | 132 | led->state = PCA9532_ON; |
133 | else { | 133 | else { |
134 | led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */ | 134 | led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */ |
135 | err = pca9532_calcpwm(led->client, 0, 0, value); | 135 | err = pca9532_calcpwm(led->client, 0, 0, value); |
136 | if (err) | 136 | if (err) |
137 | return; /* XXX: led api doesn't allow error code? */ | 137 | return; /* XXX: led api doesn't allow error code? */ |
138 | } | 138 | } |
139 | schedule_work(&led->work); | 139 | schedule_work(&led->work); |
140 | } | 140 | } |
141 | 141 | ||
142 | static int pca9532_set_blink(struct led_classdev *led_cdev, | 142 | static int pca9532_set_blink(struct led_classdev *led_cdev, |
@@ -145,7 +145,7 @@ static int pca9532_set_blink(struct led_classdev *led_cdev, | |||
145 | struct pca9532_led *led = ldev_to_led(led_cdev); | 145 | struct pca9532_led *led = ldev_to_led(led_cdev); |
146 | struct i2c_client *client = led->client; | 146 | struct i2c_client *client = led->client; |
147 | int psc; | 147 | int psc; |
148 | int err = 0; | 148 | int err = 0; |
149 | 149 | ||
150 | if (*delay_on == 0 && *delay_off == 0) { | 150 | if (*delay_on == 0 && *delay_off == 0) { |
151 | /* led subsystem ask us for a blink rate */ | 151 | /* led subsystem ask us for a blink rate */ |
@@ -157,11 +157,11 @@ static int pca9532_set_blink(struct led_classdev *led_cdev, | |||
157 | 157 | ||
158 | /* Thecus specific: only use PSC/PWM 0 */ | 158 | /* Thecus specific: only use PSC/PWM 0 */ |
159 | psc = (*delay_on * 152-1)/1000; | 159 | psc = (*delay_on * 152-1)/1000; |
160 | err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness); | 160 | err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness); |
161 | if (err) | 161 | if (err) |
162 | return err; | 162 | return err; |
163 | schedule_work(&led->work); | 163 | schedule_work(&led->work); |
164 | return 0; | 164 | return 0; |
165 | } | 165 | } |
166 | 166 | ||
167 | static int pca9532_event(struct input_dev *dev, unsigned int type, | 167 | static int pca9532_event(struct input_dev *dev, unsigned int type, |
@@ -178,15 +178,15 @@ static int pca9532_event(struct input_dev *dev, unsigned int type, | |||
178 | else | 178 | else |
179 | data->pwm[1] = 0; | 179 | data->pwm[1] = 0; |
180 | 180 | ||
181 | schedule_work(&data->work); | 181 | schedule_work(&data->work); |
182 | 182 | ||
183 | return 0; | 183 | return 0; |
184 | } | 184 | } |
185 | 185 | ||
186 | static void pca9532_input_work(struct work_struct *work) | 186 | static void pca9532_input_work(struct work_struct *work) |
187 | { | 187 | { |
188 | struct pca9532_data *data; | 188 | struct pca9532_data *data; |
189 | data = container_of(work, struct pca9532_data, work); | 189 | data = container_of(work, struct pca9532_data, work); |
190 | mutex_lock(&data->update_lock); | 190 | mutex_lock(&data->update_lock); |
191 | i2c_smbus_write_byte_data(data->client, PCA9532_REG_PWM(1), | 191 | i2c_smbus_write_byte_data(data->client, PCA9532_REG_PWM(1), |
192 | data->pwm[1]); | 192 | data->pwm[1]); |
@@ -195,11 +195,11 @@ static void pca9532_input_work(struct work_struct *work) | |||
195 | 195 | ||
196 | static void pca9532_led_work(struct work_struct *work) | 196 | static void pca9532_led_work(struct work_struct *work) |
197 | { | 197 | { |
198 | struct pca9532_led *led; | 198 | struct pca9532_led *led; |
199 | led = container_of(work, struct pca9532_led, work); | 199 | led = container_of(work, struct pca9532_led, work); |
200 | if (led->state == PCA9532_PWM0) | 200 | if (led->state == PCA9532_PWM0) |
201 | pca9532_setpwm(led->client, 0); | 201 | pca9532_setpwm(led->client, 0); |
202 | pca9532_setled(led); | 202 | pca9532_setled(led); |
203 | } | 203 | } |
204 | 204 | ||
205 | static int pca9532_configure(struct i2c_client *client, | 205 | static int pca9532_configure(struct i2c_client *client, |
@@ -232,7 +232,7 @@ static int pca9532_configure(struct i2c_client *client, | |||
232 | led->ldev.brightness = LED_OFF; | 232 | led->ldev.brightness = LED_OFF; |
233 | led->ldev.brightness_set = pca9532_set_brightness; | 233 | led->ldev.brightness_set = pca9532_set_brightness; |
234 | led->ldev.blink_set = pca9532_set_blink; | 234 | led->ldev.blink_set = pca9532_set_blink; |
235 | INIT_WORK(&led->work, pca9532_led_work); | 235 | INIT_WORK(&led->work, pca9532_led_work); |
236 | err = led_classdev_register(&client->dev, &led->ldev); | 236 | err = led_classdev_register(&client->dev, &led->ldev); |
237 | if (err < 0) { | 237 | if (err < 0) { |
238 | dev_err(&client->dev, | 238 | dev_err(&client->dev, |
@@ -262,11 +262,11 @@ static int pca9532_configure(struct i2c_client *client, | |||
262 | BIT_MASK(SND_TONE); | 262 | BIT_MASK(SND_TONE); |
263 | data->idev->event = pca9532_event; | 263 | data->idev->event = pca9532_event; |
264 | input_set_drvdata(data->idev, data); | 264 | input_set_drvdata(data->idev, data); |
265 | INIT_WORK(&data->work, pca9532_input_work); | 265 | INIT_WORK(&data->work, pca9532_input_work); |
266 | err = input_register_device(data->idev); | 266 | err = input_register_device(data->idev); |
267 | if (err) { | 267 | if (err) { |
268 | input_free_device(data->idev); | 268 | input_free_device(data->idev); |
269 | cancel_work_sync(&data->work); | 269 | cancel_work_sync(&data->work); |
270 | data->idev = NULL; | 270 | data->idev = NULL; |
271 | goto exit; | 271 | goto exit; |
272 | } | 272 | } |
@@ -283,13 +283,13 @@ exit: | |||
283 | break; | 283 | break; |
284 | case PCA9532_TYPE_LED: | 284 | case PCA9532_TYPE_LED: |
285 | led_classdev_unregister(&data->leds[i].ldev); | 285 | led_classdev_unregister(&data->leds[i].ldev); |
286 | cancel_work_sync(&data->leds[i].work); | 286 | cancel_work_sync(&data->leds[i].work); |
287 | break; | 287 | break; |
288 | case PCA9532_TYPE_N2100_BEEP: | 288 | case PCA9532_TYPE_N2100_BEEP: |
289 | if (data->idev != NULL) { | 289 | if (data->idev != NULL) { |
290 | input_unregister_device(data->idev); | 290 | input_unregister_device(data->idev); |
291 | input_free_device(data->idev); | 291 | input_free_device(data->idev); |
292 | cancel_work_sync(&data->work); | 292 | cancel_work_sync(&data->work); |
293 | data->idev = NULL; | 293 | data->idev = NULL; |
294 | } | 294 | } |
295 | break; | 295 | break; |
@@ -340,13 +340,13 @@ static int pca9532_remove(struct i2c_client *client) | |||
340 | break; | 340 | break; |
341 | case PCA9532_TYPE_LED: | 341 | case PCA9532_TYPE_LED: |
342 | led_classdev_unregister(&data->leds[i].ldev); | 342 | led_classdev_unregister(&data->leds[i].ldev); |
343 | cancel_work_sync(&data->leds[i].work); | 343 | cancel_work_sync(&data->leds[i].work); |
344 | break; | 344 | break; |
345 | case PCA9532_TYPE_N2100_BEEP: | 345 | case PCA9532_TYPE_N2100_BEEP: |
346 | if (data->idev != NULL) { | 346 | if (data->idev != NULL) { |
347 | input_unregister_device(data->idev); | 347 | input_unregister_device(data->idev); |
348 | input_free_device(data->idev); | 348 | input_free_device(data->idev); |
349 | cancel_work_sync(&data->work); | 349 | cancel_work_sync(&data->work); |
350 | data->idev = NULL; | 350 | data->idev = NULL; |
351 | } | 351 | } |
352 | break; | 352 | break; |
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index d4e8979735cb..9c3138265f8e 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h | |||
@@ -82,7 +82,7 @@ struct lg_cpu { | |||
82 | 82 | ||
83 | struct lg_eventfd { | 83 | struct lg_eventfd { |
84 | unsigned long addr; | 84 | unsigned long addr; |
85 | struct file *event; | 85 | struct eventfd_ctx *event; |
86 | }; | 86 | }; |
87 | 87 | ||
88 | struct lg_eventfd_map { | 88 | struct lg_eventfd_map { |
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index 32e297121058..9f9a2953b383 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c | |||
@@ -50,7 +50,7 @@ static int add_eventfd(struct lguest *lg, unsigned long addr, int fd) | |||
50 | 50 | ||
51 | /* Now append new entry. */ | 51 | /* Now append new entry. */ |
52 | new->map[new->num].addr = addr; | 52 | new->map[new->num].addr = addr; |
53 | new->map[new->num].event = eventfd_fget(fd); | 53 | new->map[new->num].event = eventfd_ctx_fdget(fd); |
54 | if (IS_ERR(new->map[new->num].event)) { | 54 | if (IS_ERR(new->map[new->num].event)) { |
55 | kfree(new); | 55 | kfree(new); |
56 | return PTR_ERR(new->map[new->num].event); | 56 | return PTR_ERR(new->map[new->num].event); |
@@ -357,7 +357,7 @@ static int close(struct inode *inode, struct file *file) | |||
357 | 357 | ||
358 | /* Release any eventfds they registered. */ | 358 | /* Release any eventfds they registered. */ |
359 | for (i = 0; i < lg->eventfds->num; i++) | 359 | for (i = 0; i < lg->eventfds->num; i++) |
360 | fput(lg->eventfds->map[i].event); | 360 | eventfd_ctx_put(lg->eventfds->map[i].event); |
361 | kfree(lg->eventfds); | 361 | kfree(lg->eventfds); |
362 | 362 | ||
363 | /* If lg->dead doesn't contain an error code it will be NULL or a | 363 | /* If lg->dead doesn't contain an error code it will be NULL or a |
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 6e149f4a1fff..a0f68386c12f 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c | |||
@@ -378,6 +378,17 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, | |||
378 | dev->ofdev.dev.bus = &macio_bus_type; | 378 | dev->ofdev.dev.bus = &macio_bus_type; |
379 | dev->ofdev.dev.release = macio_release_dev; | 379 | dev->ofdev.dev.release = macio_release_dev; |
380 | 380 | ||
381 | #ifdef CONFIG_PCI | ||
382 | /* Set the DMA ops to the ones from the PCI device, this could be | ||
383 | * fishy if we didn't know that on PowerMac it's always direct ops | ||
384 | * or iommu ops that will work fine | ||
385 | */ | ||
386 | dev->ofdev.dev.archdata.dma_ops = | ||
387 | chip->lbus.pdev->dev.archdata.dma_ops; | ||
388 | dev->ofdev.dev.archdata.dma_data = | ||
389 | chip->lbus.pdev->dev.archdata.dma_data; | ||
390 | #endif /* CONFIG_PCI */ | ||
391 | |||
381 | #ifdef DEBUG | 392 | #ifdef DEBUG |
382 | printk("preparing mdev @%p, ofdev @%p, dev @%p, kobj @%p\n", | 393 | printk("preparing mdev @%p, ofdev @%p, dev @%p, kobj @%p\n", |
383 | dev, &dev->ofdev, &dev->ofdev.dev, &dev->ofdev.dev.kobj); | 394 | dev, &dev->ofdev, &dev->ofdev.dev, &dev->ofdev.dev.kobj); |
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index c3ae51584b12..3710ff88fc10 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c | |||
@@ -195,7 +195,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, | |||
195 | struct dm_exception_store **store) | 195 | struct dm_exception_store **store) |
196 | { | 196 | { |
197 | int r = 0; | 197 | int r = 0; |
198 | struct dm_exception_store_type *type; | 198 | struct dm_exception_store_type *type = NULL; |
199 | struct dm_exception_store *tmp_store; | 199 | struct dm_exception_store *tmp_store; |
200 | char persistent; | 200 | char persistent; |
201 | 201 | ||
@@ -211,12 +211,15 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, | |||
211 | } | 211 | } |
212 | 212 | ||
213 | persistent = toupper(*argv[1]); | 213 | persistent = toupper(*argv[1]); |
214 | if (persistent != 'P' && persistent != 'N') { | 214 | if (persistent == 'P') |
215 | type = get_type("P"); | ||
216 | else if (persistent == 'N') | ||
217 | type = get_type("N"); | ||
218 | else { | ||
215 | ti->error = "Persistent flag is not P or N"; | 219 | ti->error = "Persistent flag is not P or N"; |
216 | return -EINVAL; | 220 | return -EINVAL; |
217 | } | 221 | } |
218 | 222 | ||
219 | type = get_type(&persistent); | ||
220 | if (!type) { | 223 | if (!type) { |
221 | ti->error = "Exception store type not recognised"; | 224 | ti->error = "Exception store type not recognised"; |
222 | r = -EINVAL; | 225 | r = -EINVAL; |
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 4899ebe767c8..2cba557d9e61 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -495,7 +495,7 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev, | |||
495 | return 0; | 495 | return 0; |
496 | } | 496 | } |
497 | 497 | ||
498 | if (blk_stack_limits(limits, &q->limits, start) < 0) | 498 | if (blk_stack_limits(limits, &q->limits, start << 9) < 0) |
499 | DMWARN("%s: target device %s is misaligned", | 499 | DMWARN("%s: target device %s is misaligned", |
500 | dm_device_name(ti->table->md), bdevname(bdev, b)); | 500 | dm_device_name(ti->table->md), bdevname(bdev, b)); |
501 | 501 | ||
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 3c6d4ee8921d..9acd54a5cffb 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -1017,7 +1017,7 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector, | |||
1017 | clone->bi_flags |= 1 << BIO_CLONED; | 1017 | clone->bi_flags |= 1 << BIO_CLONED; |
1018 | 1018 | ||
1019 | if (bio_integrity(bio)) { | 1019 | if (bio_integrity(bio)) { |
1020 | bio_integrity_clone(clone, bio, GFP_NOIO); | 1020 | bio_integrity_clone(clone, bio, GFP_NOIO, bs); |
1021 | bio_integrity_trim(clone, | 1021 | bio_integrity_trim(clone, |
1022 | bio_sector_offset(bio, idx, offset), len); | 1022 | bio_sector_offset(bio, idx, offset), len); |
1023 | } | 1023 | } |
@@ -1045,7 +1045,7 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector, | |||
1045 | clone->bi_flags &= ~(1 << BIO_SEG_VALID); | 1045 | clone->bi_flags &= ~(1 << BIO_SEG_VALID); |
1046 | 1046 | ||
1047 | if (bio_integrity(bio)) { | 1047 | if (bio_integrity(bio)) { |
1048 | bio_integrity_clone(clone, bio, GFP_NOIO); | 1048 | bio_integrity_clone(clone, bio, GFP_NOIO, bs); |
1049 | 1049 | ||
1050 | if (idx != bio->bi_idx || clone->bi_size < bio->bi_size) | 1050 | if (idx != bio->bi_idx || clone->bi_size < bio->bi_size) |
1051 | bio_integrity_trim(clone, | 1051 | bio_integrity_trim(clone, |
diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 15c8b7b25a9b..5810fa906af0 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c | |||
@@ -166,8 +166,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | |||
166 | rdev->sectors = sectors * mddev->chunk_sectors; | 166 | rdev->sectors = sectors * mddev->chunk_sectors; |
167 | } | 167 | } |
168 | 168 | ||
169 | blk_queue_stack_limits(mddev->queue, | 169 | disk_stack_limits(mddev->gendisk, rdev->bdev, |
170 | rdev->bdev->bd_disk->queue); | 170 | rdev->data_offset << 9); |
171 | /* as we don't honour merge_bvec_fn, we must never risk | 171 | /* as we don't honour merge_bvec_fn, we must never risk |
172 | * violating it, so limit ->max_sector to one PAGE, as | 172 | * violating it, so limit ->max_sector to one PAGE, as |
173 | * a one page request is never in violation. | 173 | * a one page request is never in violation. |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 09be637d52cb..0f4a70c43ffc 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -3573,7 +3573,8 @@ suspend_lo_store(mddev_t *mddev, const char *buf, size_t len) | |||
3573 | char *e; | 3573 | char *e; |
3574 | unsigned long long new = simple_strtoull(buf, &e, 10); | 3574 | unsigned long long new = simple_strtoull(buf, &e, 10); |
3575 | 3575 | ||
3576 | if (mddev->pers->quiesce == NULL) | 3576 | if (mddev->pers == NULL || |
3577 | mddev->pers->quiesce == NULL) | ||
3577 | return -EINVAL; | 3578 | return -EINVAL; |
3578 | if (buf == e || (*e && *e != '\n')) | 3579 | if (buf == e || (*e && *e != '\n')) |
3579 | return -EINVAL; | 3580 | return -EINVAL; |
@@ -3601,7 +3602,8 @@ suspend_hi_store(mddev_t *mddev, const char *buf, size_t len) | |||
3601 | char *e; | 3602 | char *e; |
3602 | unsigned long long new = simple_strtoull(buf, &e, 10); | 3603 | unsigned long long new = simple_strtoull(buf, &e, 10); |
3603 | 3604 | ||
3604 | if (mddev->pers->quiesce == NULL) | 3605 | if (mddev->pers == NULL || |
3606 | mddev->pers->quiesce == NULL) | ||
3605 | return -EINVAL; | 3607 | return -EINVAL; |
3606 | if (buf == e || (*e && *e != '\n')) | 3608 | if (buf == e || (*e && *e != '\n')) |
3607 | return -EINVAL; | 3609 | return -EINVAL; |
@@ -3844,11 +3846,9 @@ static int md_alloc(dev_t dev, char *name) | |||
3844 | flush_scheduled_work(); | 3846 | flush_scheduled_work(); |
3845 | 3847 | ||
3846 | mutex_lock(&disks_mutex); | 3848 | mutex_lock(&disks_mutex); |
3847 | if (mddev->gendisk) { | 3849 | error = -EEXIST; |
3848 | mutex_unlock(&disks_mutex); | 3850 | if (mddev->gendisk) |
3849 | mddev_put(mddev); | 3851 | goto abort; |
3850 | return -EEXIST; | ||
3851 | } | ||
3852 | 3852 | ||
3853 | if (name) { | 3853 | if (name) { |
3854 | /* Need to ensure that 'name' is not a duplicate. | 3854 | /* Need to ensure that 'name' is not a duplicate. |
@@ -3860,17 +3860,15 @@ static int md_alloc(dev_t dev, char *name) | |||
3860 | if (mddev2->gendisk && | 3860 | if (mddev2->gendisk && |
3861 | strcmp(mddev2->gendisk->disk_name, name) == 0) { | 3861 | strcmp(mddev2->gendisk->disk_name, name) == 0) { |
3862 | spin_unlock(&all_mddevs_lock); | 3862 | spin_unlock(&all_mddevs_lock); |
3863 | return -EEXIST; | 3863 | goto abort; |
3864 | } | 3864 | } |
3865 | spin_unlock(&all_mddevs_lock); | 3865 | spin_unlock(&all_mddevs_lock); |
3866 | } | 3866 | } |
3867 | 3867 | ||
3868 | error = -ENOMEM; | ||
3868 | mddev->queue = blk_alloc_queue(GFP_KERNEL); | 3869 | mddev->queue = blk_alloc_queue(GFP_KERNEL); |
3869 | if (!mddev->queue) { | 3870 | if (!mddev->queue) |
3870 | mutex_unlock(&disks_mutex); | 3871 | goto abort; |
3871 | mddev_put(mddev); | ||
3872 | return -ENOMEM; | ||
3873 | } | ||
3874 | mddev->queue->queuedata = mddev; | 3872 | mddev->queue->queuedata = mddev; |
3875 | 3873 | ||
3876 | /* Can be unlocked because the queue is new: no concurrency */ | 3874 | /* Can be unlocked because the queue is new: no concurrency */ |
@@ -3880,11 +3878,9 @@ static int md_alloc(dev_t dev, char *name) | |||
3880 | 3878 | ||
3881 | disk = alloc_disk(1 << shift); | 3879 | disk = alloc_disk(1 << shift); |
3882 | if (!disk) { | 3880 | if (!disk) { |
3883 | mutex_unlock(&disks_mutex); | ||
3884 | blk_cleanup_queue(mddev->queue); | 3881 | blk_cleanup_queue(mddev->queue); |
3885 | mddev->queue = NULL; | 3882 | mddev->queue = NULL; |
3886 | mddev_put(mddev); | 3883 | goto abort; |
3887 | return -ENOMEM; | ||
3888 | } | 3884 | } |
3889 | disk->major = MAJOR(mddev->unit); | 3885 | disk->major = MAJOR(mddev->unit); |
3890 | disk->first_minor = unit << shift; | 3886 | disk->first_minor = unit << shift; |
@@ -3906,16 +3902,22 @@ static int md_alloc(dev_t dev, char *name) | |||
3906 | mddev->gendisk = disk; | 3902 | mddev->gendisk = disk; |
3907 | error = kobject_init_and_add(&mddev->kobj, &md_ktype, | 3903 | error = kobject_init_and_add(&mddev->kobj, &md_ktype, |
3908 | &disk_to_dev(disk)->kobj, "%s", "md"); | 3904 | &disk_to_dev(disk)->kobj, "%s", "md"); |
3909 | mutex_unlock(&disks_mutex); | 3905 | if (error) { |
3910 | if (error) | 3906 | /* This isn't possible, but as kobject_init_and_add is marked |
3907 | * __must_check, we must do something with the result | ||
3908 | */ | ||
3911 | printk(KERN_WARNING "md: cannot register %s/md - name in use\n", | 3909 | printk(KERN_WARNING "md: cannot register %s/md - name in use\n", |
3912 | disk->disk_name); | 3910 | disk->disk_name); |
3913 | else { | 3911 | error = 0; |
3912 | } | ||
3913 | abort: | ||
3914 | mutex_unlock(&disks_mutex); | ||
3915 | if (!error) { | ||
3914 | kobject_uevent(&mddev->kobj, KOBJ_ADD); | 3916 | kobject_uevent(&mddev->kobj, KOBJ_ADD); |
3915 | mddev->sysfs_state = sysfs_get_dirent(mddev->kobj.sd, "array_state"); | 3917 | mddev->sysfs_state = sysfs_get_dirent(mddev->kobj.sd, "array_state"); |
3916 | } | 3918 | } |
3917 | mddev_put(mddev); | 3919 | mddev_put(mddev); |
3918 | return 0; | 3920 | return error; |
3919 | } | 3921 | } |
3920 | 3922 | ||
3921 | static struct kobject *md_probe(dev_t dev, int *part, void *data) | 3923 | static struct kobject *md_probe(dev_t dev, int *part, void *data) |
@@ -6334,10 +6336,16 @@ void md_do_sync(mddev_t *mddev) | |||
6334 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); | 6336 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); |
6335 | } | 6337 | } |
6336 | 6338 | ||
6337 | if (j >= mddev->resync_max) | 6339 | while (j >= mddev->resync_max && !kthread_should_stop()) { |
6338 | wait_event(mddev->recovery_wait, | 6340 | /* As this condition is controlled by user-space, |
6339 | mddev->resync_max > j | 6341 | * we can block indefinitely, so use '_interruptible' |
6340 | || kthread_should_stop()); | 6342 | * to avoid triggering warnings. |
6343 | */ | ||
6344 | flush_signals(current); /* just in case */ | ||
6345 | wait_event_interruptible(mddev->recovery_wait, | ||
6346 | mddev->resync_max > j | ||
6347 | || kthread_should_stop()); | ||
6348 | } | ||
6341 | 6349 | ||
6342 | if (kthread_should_stop()) | 6350 | if (kthread_should_stop()) |
6343 | goto interrupted; | 6351 | goto interrupted; |
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index cbe368fa6598..237fe3fd235c 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c | |||
@@ -294,7 +294,8 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
294 | for (path = first; path <= last; path++) | 294 | for (path = first; path <= last; path++) |
295 | if ((p=conf->multipaths+path)->rdev == NULL) { | 295 | if ((p=conf->multipaths+path)->rdev == NULL) { |
296 | q = rdev->bdev->bd_disk->queue; | 296 | q = rdev->bdev->bd_disk->queue; |
297 | blk_queue_stack_limits(mddev->queue, q); | 297 | disk_stack_limits(mddev->gendisk, rdev->bdev, |
298 | rdev->data_offset << 9); | ||
298 | 299 | ||
299 | /* as we don't honour merge_bvec_fn, we must never risk | 300 | /* as we don't honour merge_bvec_fn, we must never risk |
300 | * violating it, so limit ->max_sector to one PAGE, as | 301 | * violating it, so limit ->max_sector to one PAGE, as |
@@ -463,9 +464,9 @@ static int multipath_run (mddev_t *mddev) | |||
463 | 464 | ||
464 | disk = conf->multipaths + disk_idx; | 465 | disk = conf->multipaths + disk_idx; |
465 | disk->rdev = rdev; | 466 | disk->rdev = rdev; |
467 | disk_stack_limits(mddev->gendisk, rdev->bdev, | ||
468 | rdev->data_offset << 9); | ||
466 | 469 | ||
467 | blk_queue_stack_limits(mddev->queue, | ||
468 | rdev->bdev->bd_disk->queue); | ||
469 | /* as we don't honour merge_bvec_fn, we must never risk | 470 | /* as we don't honour merge_bvec_fn, we must never risk |
470 | * violating it, not that we ever expect a device with | 471 | * violating it, not that we ever expect a device with |
471 | * a merge_bvec_fn to be involved in multipath */ | 472 | * a merge_bvec_fn to be involved in multipath */ |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index ab4a489d8695..335f490dcad6 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
@@ -170,8 +170,8 @@ static int create_strip_zones(mddev_t *mddev) | |||
170 | } | 170 | } |
171 | dev[j] = rdev1; | 171 | dev[j] = rdev1; |
172 | 172 | ||
173 | blk_queue_stack_limits(mddev->queue, | 173 | disk_stack_limits(mddev->gendisk, rdev1->bdev, |
174 | rdev1->bdev->bd_disk->queue); | 174 | rdev1->data_offset << 9); |
175 | /* as we don't honour merge_bvec_fn, we must never risk | 175 | /* as we don't honour merge_bvec_fn, we must never risk |
176 | * violating it, so limit ->max_sector to one PAGE, as | 176 | * violating it, so limit ->max_sector to one PAGE, as |
177 | * a one page request is never in violation. | 177 | * a one page request is never in violation. |
@@ -250,6 +250,11 @@ static int create_strip_zones(mddev_t *mddev) | |||
250 | mddev->chunk_sectors << 9); | 250 | mddev->chunk_sectors << 9); |
251 | goto abort; | 251 | goto abort; |
252 | } | 252 | } |
253 | |||
254 | blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9); | ||
255 | blk_queue_io_opt(mddev->queue, | ||
256 | (mddev->chunk_sectors << 9) * mddev->raid_disks); | ||
257 | |||
253 | printk(KERN_INFO "raid0: done.\n"); | 258 | printk(KERN_INFO "raid0: done.\n"); |
254 | mddev->private = conf; | 259 | mddev->private = conf; |
255 | return 0; | 260 | return 0; |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 89939a7aef57..0569efba0c02 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -1123,8 +1123,8 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1123 | for (mirror = first; mirror <= last; mirror++) | 1123 | for (mirror = first; mirror <= last; mirror++) |
1124 | if ( !(p=conf->mirrors+mirror)->rdev) { | 1124 | if ( !(p=conf->mirrors+mirror)->rdev) { |
1125 | 1125 | ||
1126 | blk_queue_stack_limits(mddev->queue, | 1126 | disk_stack_limits(mddev->gendisk, rdev->bdev, |
1127 | rdev->bdev->bd_disk->queue); | 1127 | rdev->data_offset << 9); |
1128 | /* as we don't honour merge_bvec_fn, we must never risk | 1128 | /* as we don't honour merge_bvec_fn, we must never risk |
1129 | * violating it, so limit ->max_sector to one PAGE, as | 1129 | * violating it, so limit ->max_sector to one PAGE, as |
1130 | * a one page request is never in violation. | 1130 | * a one page request is never in violation. |
@@ -1988,9 +1988,8 @@ static int run(mddev_t *mddev) | |||
1988 | disk = conf->mirrors + disk_idx; | 1988 | disk = conf->mirrors + disk_idx; |
1989 | 1989 | ||
1990 | disk->rdev = rdev; | 1990 | disk->rdev = rdev; |
1991 | 1991 | disk_stack_limits(mddev->gendisk, rdev->bdev, | |
1992 | blk_queue_stack_limits(mddev->queue, | 1992 | rdev->data_offset << 9); |
1993 | rdev->bdev->bd_disk->queue); | ||
1994 | /* as we don't honour merge_bvec_fn, we must never risk | 1993 | /* as we don't honour merge_bvec_fn, we must never risk |
1995 | * violating it, so limit ->max_sector to one PAGE, as | 1994 | * violating it, so limit ->max_sector to one PAGE, as |
1996 | * a one page request is never in violation. | 1995 | * a one page request is never in violation. |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index ae12ceafe10c..7298a5e5a183 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1151,8 +1151,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1151 | for ( ; mirror <= last ; mirror++) | 1151 | for ( ; mirror <= last ; mirror++) |
1152 | if ( !(p=conf->mirrors+mirror)->rdev) { | 1152 | if ( !(p=conf->mirrors+mirror)->rdev) { |
1153 | 1153 | ||
1154 | blk_queue_stack_limits(mddev->queue, | 1154 | disk_stack_limits(mddev->gendisk, rdev->bdev, |
1155 | rdev->bdev->bd_disk->queue); | 1155 | rdev->data_offset << 9); |
1156 | /* as we don't honour merge_bvec_fn, we must never risk | 1156 | /* as we don't honour merge_bvec_fn, we must never risk |
1157 | * violating it, so limit ->max_sector to one PAGE, as | 1157 | * violating it, so limit ->max_sector to one PAGE, as |
1158 | * a one page request is never in violation. | 1158 | * a one page request is never in violation. |
@@ -2044,7 +2044,7 @@ raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks) | |||
2044 | static int run(mddev_t *mddev) | 2044 | static int run(mddev_t *mddev) |
2045 | { | 2045 | { |
2046 | conf_t *conf; | 2046 | conf_t *conf; |
2047 | int i, disk_idx; | 2047 | int i, disk_idx, chunk_size; |
2048 | mirror_info_t *disk; | 2048 | mirror_info_t *disk; |
2049 | mdk_rdev_t *rdev; | 2049 | mdk_rdev_t *rdev; |
2050 | int nc, fc, fo; | 2050 | int nc, fc, fo; |
@@ -2130,6 +2130,14 @@ static int run(mddev_t *mddev) | |||
2130 | spin_lock_init(&conf->device_lock); | 2130 | spin_lock_init(&conf->device_lock); |
2131 | mddev->queue->queue_lock = &conf->device_lock; | 2131 | mddev->queue->queue_lock = &conf->device_lock; |
2132 | 2132 | ||
2133 | chunk_size = mddev->chunk_sectors << 9; | ||
2134 | blk_queue_io_min(mddev->queue, chunk_size); | ||
2135 | if (conf->raid_disks % conf->near_copies) | ||
2136 | blk_queue_io_opt(mddev->queue, chunk_size * conf->raid_disks); | ||
2137 | else | ||
2138 | blk_queue_io_opt(mddev->queue, chunk_size * | ||
2139 | (conf->raid_disks / conf->near_copies)); | ||
2140 | |||
2133 | list_for_each_entry(rdev, &mddev->disks, same_set) { | 2141 | list_for_each_entry(rdev, &mddev->disks, same_set) { |
2134 | disk_idx = rdev->raid_disk; | 2142 | disk_idx = rdev->raid_disk; |
2135 | if (disk_idx >= mddev->raid_disks | 2143 | if (disk_idx >= mddev->raid_disks |
@@ -2138,9 +2146,8 @@ static int run(mddev_t *mddev) | |||
2138 | disk = conf->mirrors + disk_idx; | 2146 | disk = conf->mirrors + disk_idx; |
2139 | 2147 | ||
2140 | disk->rdev = rdev; | 2148 | disk->rdev = rdev; |
2141 | 2149 | disk_stack_limits(mddev->gendisk, rdev->bdev, | |
2142 | blk_queue_stack_limits(mddev->queue, | 2150 | rdev->data_offset << 9); |
2143 | rdev->bdev->bd_disk->queue); | ||
2144 | /* as we don't honour merge_bvec_fn, we must never risk | 2151 | /* as we don't honour merge_bvec_fn, we must never risk |
2145 | * violating it, so limit ->max_sector to one PAGE, as | 2152 | * violating it, so limit ->max_sector to one PAGE, as |
2146 | * a one page request is never in violation. | 2153 | * a one page request is never in violation. |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index f9f991e6e138..37835538b58e 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -3699,13 +3699,21 @@ static int make_request(struct request_queue *q, struct bio * bi) | |||
3699 | goto retry; | 3699 | goto retry; |
3700 | } | 3700 | } |
3701 | } | 3701 | } |
3702 | /* FIXME what if we get a false positive because these | 3702 | |
3703 | * are being updated. | 3703 | if (bio_data_dir(bi) == WRITE && |
3704 | */ | 3704 | logical_sector >= mddev->suspend_lo && |
3705 | if (logical_sector >= mddev->suspend_lo && | ||
3706 | logical_sector < mddev->suspend_hi) { | 3705 | logical_sector < mddev->suspend_hi) { |
3707 | release_stripe(sh); | 3706 | release_stripe(sh); |
3708 | schedule(); | 3707 | /* As the suspend_* range is controlled by |
3708 | * userspace, we want an interruptible | ||
3709 | * wait. | ||
3710 | */ | ||
3711 | flush_signals(current); | ||
3712 | prepare_to_wait(&conf->wait_for_overlap, | ||
3713 | &w, TASK_INTERRUPTIBLE); | ||
3714 | if (logical_sector >= mddev->suspend_lo && | ||
3715 | logical_sector < mddev->suspend_hi) | ||
3716 | schedule(); | ||
3709 | goto retry; | 3717 | goto retry; |
3710 | } | 3718 | } |
3711 | 3719 | ||
@@ -4452,7 +4460,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev) | |||
4452 | static int run(mddev_t *mddev) | 4460 | static int run(mddev_t *mddev) |
4453 | { | 4461 | { |
4454 | raid5_conf_t *conf; | 4462 | raid5_conf_t *conf; |
4455 | int working_disks = 0; | 4463 | int working_disks = 0, chunk_size; |
4456 | mdk_rdev_t *rdev; | 4464 | mdk_rdev_t *rdev; |
4457 | 4465 | ||
4458 | if (mddev->recovery_cp != MaxSector) | 4466 | if (mddev->recovery_cp != MaxSector) |
@@ -4607,6 +4615,14 @@ static int run(mddev_t *mddev) | |||
4607 | md_set_array_sectors(mddev, raid5_size(mddev, 0, 0)); | 4615 | md_set_array_sectors(mddev, raid5_size(mddev, 0, 0)); |
4608 | 4616 | ||
4609 | blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec); | 4617 | blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec); |
4618 | chunk_size = mddev->chunk_sectors << 9; | ||
4619 | blk_queue_io_min(mddev->queue, chunk_size); | ||
4620 | blk_queue_io_opt(mddev->queue, chunk_size * | ||
4621 | (conf->raid_disks - conf->max_degraded)); | ||
4622 | |||
4623 | list_for_each_entry(rdev, &mddev->disks, same_set) | ||
4624 | disk_stack_limits(mddev->gendisk, rdev->bdev, | ||
4625 | rdev->data_offset << 9); | ||
4610 | 4626 | ||
4611 | return 0; | 4627 | return 0; |
4612 | abort: | 4628 | abort: |
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 671a7efe86a8..c1de4afa89a6 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c | |||
@@ -238,8 +238,10 @@ static irqreturn_t pcap_adc_irq(int irq, void *_pcap) | |||
238 | mutex_lock(&pcap->adc_mutex); | 238 | mutex_lock(&pcap->adc_mutex); |
239 | req = pcap->adc_queue[pcap->adc_head]; | 239 | req = pcap->adc_queue[pcap->adc_head]; |
240 | 240 | ||
241 | if (WARN(!req, KERN_WARNING "adc irq without pending request\n")) | 241 | if (WARN(!req, KERN_WARNING "adc irq without pending request\n")) { |
242 | mutex_unlock(&pcap->adc_mutex); | ||
242 | return IRQ_HANDLED; | 243 | return IRQ_HANDLED; |
244 | } | ||
243 | 245 | ||
244 | /* read requested channels results */ | 246 | /* read requested channels results */ |
245 | ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp); | 247 | ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp); |
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 4c7b7962f6b8..0cc5eeff5ee8 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c | |||
@@ -367,7 +367,8 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to) | |||
367 | break; | 367 | break; |
368 | 368 | ||
369 | default: | 369 | default: |
370 | return -1; | 370 | gate = -1; |
371 | goto already; | ||
371 | } | 372 | } |
372 | 373 | ||
373 | writel(mode, sm->regs + SM501_POWER_MODE_CONTROL); | 374 | writel(mode, sm->regs + SM501_POWER_MODE_CONTROL); |
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 240608cc7ae9..a461017ce5ce 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
@@ -1313,6 +1313,12 @@ static int mmc_spi_probe(struct spi_device *spi) | |||
1313 | struct mmc_spi_host *host; | 1313 | struct mmc_spi_host *host; |
1314 | int status; | 1314 | int status; |
1315 | 1315 | ||
1316 | /* We rely on full duplex transfers, mostly to reduce | ||
1317 | * per-transfer overheads (by making fewer transfers). | ||
1318 | */ | ||
1319 | if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) | ||
1320 | return -EINVAL; | ||
1321 | |||
1316 | /* MMC and SD specs only seem to care that sampling is on the | 1322 | /* MMC and SD specs only seem to care that sampling is on the |
1317 | * rising edge ... meaning SPI modes 0 or 3. So either SPI mode | 1323 | * rising edge ... meaning SPI modes 0 or 3. So either SPI mode |
1318 | * should be legit. We'll use mode 0 since the steady state is 0, | 1324 | * should be legit. We'll use mode 0 since the steady state is 0, |
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 5011fa73f918..1479da6d3aa6 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c | |||
@@ -194,7 +194,7 @@ static struct mtd_partition * newpart(char *s, | |||
194 | parts[this_part].name = extra_mem; | 194 | parts[this_part].name = extra_mem; |
195 | extra_mem += name_len + 1; | 195 | extra_mem += name_len + 1; |
196 | 196 | ||
197 | dbg(("partition %d: name <%s>, offset %x, size %x, mask flags %x\n", | 197 | dbg(("partition %d: name <%s>, offset %llx, size %llx, mask flags %x\n", |
198 | this_part, | 198 | this_part, |
199 | parts[this_part].name, | 199 | parts[this_part].name, |
200 | parts[this_part].offset, | 200 | parts[this_part].offset, |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 59c46126a5ce..ae5fe91867e1 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -54,7 +54,7 @@ | |||
54 | #define SR_SRWD 0x80 /* SR write protect */ | 54 | #define SR_SRWD 0x80 /* SR write protect */ |
55 | 55 | ||
56 | /* Define max times to check status register before we give up. */ | 56 | /* Define max times to check status register before we give up. */ |
57 | #define MAX_READY_WAIT_JIFFIES (10 * HZ) /* eg. M25P128 specs 6s max sector erase */ | 57 | #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ |
58 | #define CMD_SIZE 4 | 58 | #define CMD_SIZE 4 |
59 | 59 | ||
60 | #ifdef CONFIG_M25PXX_USE_FAST_READ | 60 | #ifdef CONFIG_M25PXX_USE_FAST_READ |
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 73f05227dc8c..d8cf29c01cc4 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c | |||
@@ -226,7 +226,7 @@ static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate) | |||
226 | if (!desperate && inftl->numfreeEUNs < 2) { | 226 | if (!desperate && inftl->numfreeEUNs < 2) { |
227 | DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free " | 227 | DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free " |
228 | "EUNs (%d)\n", inftl->numfreeEUNs); | 228 | "EUNs (%d)\n", inftl->numfreeEUNs); |
229 | return 0xffff; | 229 | return BLOCK_NIL; |
230 | } | 230 | } |
231 | 231 | ||
232 | /* Scan for a free block */ | 232 | /* Scan for a free block */ |
@@ -281,7 +281,8 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned | |||
281 | silly = MAX_LOOPS; | 281 | silly = MAX_LOOPS; |
282 | while (thisEUN < inftl->nb_blocks) { | 282 | while (thisEUN < inftl->nb_blocks) { |
283 | for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) { | 283 | for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) { |
284 | if ((BlockMap[block] != 0xffff) || BlockDeleted[block]) | 284 | if ((BlockMap[block] != BLOCK_NIL) || |
285 | BlockDeleted[block]) | ||
285 | continue; | 286 | continue; |
286 | 287 | ||
287 | if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) | 288 | if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) |
@@ -525,7 +526,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) | |||
525 | if (!silly--) { | 526 | if (!silly--) { |
526 | printk(KERN_WARNING "INFTL: infinite loop in " | 527 | printk(KERN_WARNING "INFTL: infinite loop in " |
527 | "Virtual Unit Chain 0x%x\n", thisVUC); | 528 | "Virtual Unit Chain 0x%x\n", thisVUC); |
528 | return 0xffff; | 529 | return BLOCK_NIL; |
529 | } | 530 | } |
530 | 531 | ||
531 | /* Skip to next block in chain */ | 532 | /* Skip to next block in chain */ |
@@ -549,7 +550,7 @@ hitused: | |||
549 | * waiting to be picked up. We're going to have to fold | 550 | * waiting to be picked up. We're going to have to fold |
550 | * a chain to make room. | 551 | * a chain to make room. |
551 | */ | 552 | */ |
552 | thisEUN = INFTL_makefreeblock(inftl, 0xffff); | 553 | thisEUN = INFTL_makefreeblock(inftl, BLOCK_NIL); |
553 | 554 | ||
554 | /* | 555 | /* |
555 | * Hopefully we free something, lets try again. | 556 | * Hopefully we free something, lets try again. |
@@ -631,7 +632,7 @@ hitused: | |||
631 | 632 | ||
632 | printk(KERN_WARNING "INFTL: error folding to make room for Virtual " | 633 | printk(KERN_WARNING "INFTL: error folding to make room for Virtual " |
633 | "Unit Chain 0x%x\n", thisVUC); | 634 | "Unit Chain 0x%x\n", thisVUC); |
634 | return 0xffff; | 635 | return BLOCK_NIL; |
635 | } | 636 | } |
636 | 637 | ||
637 | /* | 638 | /* |
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c index b08a798ee254..2aac41bde8b3 100644 --- a/drivers/mtd/maps/integrator-flash.c +++ b/drivers/mtd/maps/integrator-flash.c | |||
@@ -42,10 +42,8 @@ | |||
42 | #include <mach/hardware.h> | 42 | #include <mach/hardware.h> |
43 | #include <asm/system.h> | 43 | #include <asm/system.h> |
44 | 44 | ||
45 | #define SUBDEV_NAME_SIZE (BUS_ID_SIZE + 2) | ||
46 | |||
47 | struct armflash_subdev_info { | 45 | struct armflash_subdev_info { |
48 | char name[SUBDEV_NAME_SIZE]; | 46 | char *name; |
49 | struct mtd_info *mtd; | 47 | struct mtd_info *mtd; |
50 | struct map_info map; | 48 | struct map_info map; |
51 | struct flash_platform_data *plat; | 49 | struct flash_platform_data *plat; |
@@ -134,6 +132,8 @@ static void armflash_subdev_remove(struct armflash_subdev_info *subdev) | |||
134 | map_destroy(subdev->mtd); | 132 | map_destroy(subdev->mtd); |
135 | if (subdev->map.virt) | 133 | if (subdev->map.virt) |
136 | iounmap(subdev->map.virt); | 134 | iounmap(subdev->map.virt); |
135 | kfree(subdev->name); | ||
136 | subdev->name = NULL; | ||
137 | release_mem_region(subdev->map.phys, subdev->map.size); | 137 | release_mem_region(subdev->map.phys, subdev->map.size); |
138 | } | 138 | } |
139 | 139 | ||
@@ -177,16 +177,22 @@ static int armflash_probe(struct platform_device *dev) | |||
177 | 177 | ||
178 | if (nr == 1) | 178 | if (nr == 1) |
179 | /* No MTD concatenation, just use the default name */ | 179 | /* No MTD concatenation, just use the default name */ |
180 | snprintf(subdev->name, SUBDEV_NAME_SIZE, "%s", | 180 | subdev->name = kstrdup(dev_name(&dev->dev), GFP_KERNEL); |
181 | dev_name(&dev->dev)); | ||
182 | else | 181 | else |
183 | snprintf(subdev->name, SUBDEV_NAME_SIZE, "%s-%d", | 182 | subdev->name = kasprintf(GFP_KERNEL, "%s-%d", |
184 | dev_name(&dev->dev), i); | 183 | dev_name(&dev->dev), i); |
184 | if (!subdev->name) { | ||
185 | err = -ENOMEM; | ||
186 | break; | ||
187 | } | ||
185 | subdev->plat = plat; | 188 | subdev->plat = plat; |
186 | 189 | ||
187 | err = armflash_subdev_probe(subdev, res); | 190 | err = armflash_subdev_probe(subdev, res); |
188 | if (err) | 191 | if (err) { |
192 | kfree(subdev->name); | ||
193 | subdev->name = NULL; | ||
189 | break; | 194 | break; |
195 | } | ||
190 | } | 196 | } |
191 | info->nr_subdev = i; | 197 | info->nr_subdev = i; |
192 | 198 | ||
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 2802992b39da..20c828ba9405 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -534,7 +534,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
534 | &num_partitions); | 534 | &num_partitions); |
535 | 535 | ||
536 | if ((!partitions) || (num_partitions == 0)) { | 536 | if ((!partitions) || (num_partitions == 0)) { |
537 | printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n"); | 537 | printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n"); |
538 | res = ENXIO; | 538 | res = ENXIO; |
539 | goto err_no_partitions; | 539 | goto err_no_partitions; |
540 | } | 540 | } |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 0cd76f89f4b0..ebd07e95b814 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -11,6 +11,8 @@ | |||
11 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
12 | #include <linux/dma-mapping.h> | 12 | #include <linux/dma-mapping.h> |
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/jiffies.h> | ||
15 | #include <linux/sched.h> | ||
14 | #include <linux/mtd/mtd.h> | 16 | #include <linux/mtd/mtd.h> |
15 | #include <linux/mtd/nand.h> | 17 | #include <linux/mtd/nand.h> |
16 | #include <linux/mtd/partitions.h> | 18 | #include <linux/mtd/partitions.h> |
@@ -541,7 +543,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
541 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | 543 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, |
542 | mtd); | 544 | mtd); |
543 | unsigned long timeo = jiffies; | 545 | unsigned long timeo = jiffies; |
544 | int status, state = this->state; | 546 | int status = NAND_STATUS_FAIL, state = this->state; |
545 | 547 | ||
546 | if (state == FL_ERASING) | 548 | if (state == FL_ERASING) |
547 | timeo += (HZ * 400) / 1000; | 549 | timeo += (HZ * 400) / 1000; |
@@ -556,8 +558,9 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
556 | 558 | ||
557 | while (time_before(jiffies, timeo)) { | 559 | while (time_before(jiffies, timeo)) { |
558 | status = __raw_readb(this->IO_ADDR_R); | 560 | status = __raw_readb(this->IO_ADDR_R); |
559 | if (!(status & 0x40)) | 561 | if (status & NAND_STATUS_READY) |
560 | break; | 562 | break; |
563 | cond_resched(); | ||
561 | } | 564 | } |
562 | return status; | 565 | return status; |
563 | } | 566 | } |
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index e3f8495a94c2..fb86cacd5bdb 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c | |||
@@ -208,7 +208,7 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) | |||
208 | /* Normally, we force a fold to happen before we run out of free blocks completely */ | 208 | /* Normally, we force a fold to happen before we run out of free blocks completely */ |
209 | if (!desperate && nftl->numfreeEUNs < 2) { | 209 | if (!desperate && nftl->numfreeEUNs < 2) { |
210 | DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n"); | 210 | DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n"); |
211 | return 0xffff; | 211 | return BLOCK_NIL; |
212 | } | 212 | } |
213 | 213 | ||
214 | /* Scan for a free block */ | 214 | /* Scan for a free block */ |
@@ -230,11 +230,11 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) | |||
230 | printk("Argh! No free blocks found! LastFreeEUN = %d, " | 230 | printk("Argh! No free blocks found! LastFreeEUN = %d, " |
231 | "FirstEUN = %d\n", nftl->LastFreeEUN, | 231 | "FirstEUN = %d\n", nftl->LastFreeEUN, |
232 | le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN)); | 232 | le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN)); |
233 | return 0xffff; | 233 | return BLOCK_NIL; |
234 | } | 234 | } |
235 | } while (pot != nftl->LastFreeEUN); | 235 | } while (pot != nftl->LastFreeEUN); |
236 | 236 | ||
237 | return 0xffff; | 237 | return BLOCK_NIL; |
238 | } | 238 | } |
239 | 239 | ||
240 | static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ) | 240 | static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ) |
@@ -431,7 +431,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p | |||
431 | 431 | ||
432 | /* add the header so that it is now a valid chain */ | 432 | /* add the header so that it is now a valid chain */ |
433 | oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); | 433 | oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); |
434 | oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; | 434 | oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = BLOCK_NIL; |
435 | 435 | ||
436 | nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8, | 436 | nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8, |
437 | 8, &retlen, (char *)&oob.u); | 437 | 8, &retlen, (char *)&oob.u); |
@@ -515,7 +515,7 @@ static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock) | |||
515 | if (ChainLength < 2) { | 515 | if (ChainLength < 2) { |
516 | printk(KERN_WARNING "No Virtual Unit Chains available for folding. " | 516 | printk(KERN_WARNING "No Virtual Unit Chains available for folding. " |
517 | "Failing request\n"); | 517 | "Failing request\n"); |
518 | return 0xffff; | 518 | return BLOCK_NIL; |
519 | } | 519 | } |
520 | 520 | ||
521 | return NFTL_foldchain (nftl, LongestChain, pendingblock); | 521 | return NFTL_foldchain (nftl, LongestChain, pendingblock); |
@@ -578,7 +578,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
578 | printk(KERN_WARNING | 578 | printk(KERN_WARNING |
579 | "Infinite loop in Virtual Unit Chain 0x%x\n", | 579 | "Infinite loop in Virtual Unit Chain 0x%x\n", |
580 | thisVUC); | 580 | thisVUC); |
581 | return 0xffff; | 581 | return BLOCK_NIL; |
582 | } | 582 | } |
583 | 583 | ||
584 | /* Skip to next block in chain */ | 584 | /* Skip to next block in chain */ |
@@ -601,7 +601,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
601 | //u16 startEUN = nftl->EUNtable[thisVUC]; | 601 | //u16 startEUN = nftl->EUNtable[thisVUC]; |
602 | 602 | ||
603 | //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC); | 603 | //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC); |
604 | writeEUN = NFTL_makefreeblock(nftl, 0xffff); | 604 | writeEUN = NFTL_makefreeblock(nftl, BLOCK_NIL); |
605 | 605 | ||
606 | if (writeEUN == BLOCK_NIL) { | 606 | if (writeEUN == BLOCK_NIL) { |
607 | /* OK, we accept that the above comment is | 607 | /* OK, we accept that the above comment is |
@@ -673,7 +673,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
673 | 673 | ||
674 | printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n", | 674 | printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n", |
675 | thisVUC); | 675 | thisVUC); |
676 | return 0xffff; | 676 | return BLOCK_NIL; |
677 | } | 677 | } |
678 | 678 | ||
679 | static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, | 679 | static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, |
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 5d610cbcfe80..0f0e0b919ef4 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c | |||
@@ -1134,7 +1134,7 @@ static const struct file_operations ccio_proc_bitmap_fops = { | |||
1134 | .llseek = seq_lseek, | 1134 | .llseek = seq_lseek, |
1135 | .release = single_release, | 1135 | .release = single_release, |
1136 | }; | 1136 | }; |
1137 | #endif | 1137 | #endif /* CONFIG_PROC_FS */ |
1138 | 1138 | ||
1139 | /** | 1139 | /** |
1140 | * ccio_find_ioc - Find the ioc in the ioc_list | 1140 | * ccio_find_ioc - Find the ioc in the ioc_list |
@@ -1568,14 +1568,15 @@ static int __init ccio_probe(struct parisc_device *dev) | |||
1568 | /* if this fails, no I/O cards will work, so may as well bug */ | 1568 | /* if this fails, no I/O cards will work, so may as well bug */ |
1569 | BUG_ON(dev->dev.platform_data == NULL); | 1569 | BUG_ON(dev->dev.platform_data == NULL); |
1570 | HBA_DATA(dev->dev.platform_data)->iommu = ioc; | 1570 | HBA_DATA(dev->dev.platform_data)->iommu = ioc; |
1571 | 1571 | ||
1572 | #ifdef CONFIG_PROC_FS | ||
1572 | if (ioc_count == 0) { | 1573 | if (ioc_count == 0) { |
1573 | proc_create(MODULE_NAME, 0, proc_runway_root, | 1574 | proc_create(MODULE_NAME, 0, proc_runway_root, |
1574 | &ccio_proc_info_fops); | 1575 | &ccio_proc_info_fops); |
1575 | proc_create(MODULE_NAME"-bitmap", 0, proc_runway_root, | 1576 | proc_create(MODULE_NAME"-bitmap", 0, proc_runway_root, |
1576 | &ccio_proc_bitmap_fops); | 1577 | &ccio_proc_bitmap_fops); |
1577 | } | 1578 | } |
1578 | 1579 | #endif | |
1579 | ioc_count++; | 1580 | ioc_count++; |
1580 | 1581 | ||
1581 | parisc_has_iommu(); | 1582 | parisc_has_iommu(); |
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 52ae0b1d470c..c590974e9815 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c | |||
@@ -353,7 +353,7 @@ static unsigned int dino_startup_irq(unsigned int irq) | |||
353 | return 0; | 353 | return 0; |
354 | } | 354 | } |
355 | 355 | ||
356 | static struct hw_interrupt_type dino_interrupt_type = { | 356 | static struct irq_chip dino_interrupt_type = { |
357 | .typename = "GSC-PCI", | 357 | .typename = "GSC-PCI", |
358 | .startup = dino_startup_irq, | 358 | .startup = dino_startup_irq, |
359 | .shutdown = dino_disable_irq, | 359 | .shutdown = dino_disable_irq, |
@@ -1019,22 +1019,22 @@ static int __init dino_probe(struct parisc_device *dev) | |||
1019 | ** It's not used to avoid chicken/egg problems | 1019 | ** It's not used to avoid chicken/egg problems |
1020 | ** with configuration accessor functions. | 1020 | ** with configuration accessor functions. |
1021 | */ | 1021 | */ |
1022 | bus = pci_scan_bus_parented(&dev->dev, dino_current_bus, | 1022 | dino_dev->hba.hba_bus = bus = pci_scan_bus_parented(&dev->dev, |
1023 | &dino_cfg_ops, NULL); | 1023 | dino_current_bus, &dino_cfg_ops, NULL); |
1024 | |||
1024 | if(bus) { | 1025 | if(bus) { |
1025 | pci_bus_add_devices(bus); | ||
1026 | /* This code *depends* on scanning being single threaded | 1026 | /* This code *depends* on scanning being single threaded |
1027 | * if it isn't, this global bus number count will fail | 1027 | * if it isn't, this global bus number count will fail |
1028 | */ | 1028 | */ |
1029 | dino_current_bus = bus->subordinate + 1; | 1029 | dino_current_bus = bus->subordinate + 1; |
1030 | pci_bus_assign_resources(bus); | 1030 | pci_bus_assign_resources(bus); |
1031 | pci_bus_add_devices(bus); | ||
1031 | } else { | 1032 | } else { |
1032 | printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", | 1033 | printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n", |
1033 | dev_name(&dev->dev), dino_current_bus); | 1034 | dev_name(&dev->dev), dino_current_bus); |
1034 | /* increment the bus number in case of duplicates */ | 1035 | /* increment the bus number in case of duplicates */ |
1035 | dino_current_bus++; | 1036 | dino_current_bus++; |
1036 | } | 1037 | } |
1037 | dino_dev->hba.hba_bus = bus; | ||
1038 | return 0; | 1038 | return 0; |
1039 | } | 1039 | } |
1040 | 1040 | ||
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index 5b89f404e668..51220749cb65 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c | |||
@@ -188,7 +188,7 @@ static unsigned int eisa_startup_irq(unsigned int irq) | |||
188 | return 0; | 188 | return 0; |
189 | } | 189 | } |
190 | 190 | ||
191 | static struct hw_interrupt_type eisa_interrupt_type = { | 191 | static struct irq_chip eisa_interrupt_type = { |
192 | .typename = "EISA", | 192 | .typename = "EISA", |
193 | .startup = eisa_startup_irq, | 193 | .startup = eisa_startup_irq, |
194 | .shutdown = eisa_disable_irq, | 194 | .shutdown = eisa_disable_irq, |
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index d33632917696..647adc9f85ad 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c | |||
@@ -148,7 +148,7 @@ static unsigned int gsc_asic_startup_irq(unsigned int irq) | |||
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | 150 | ||
151 | static struct hw_interrupt_type gsc_asic_interrupt_type = { | 151 | static struct irq_chip gsc_asic_interrupt_type = { |
152 | .typename = "GSC-ASIC", | 152 | .typename = "GSC-ASIC", |
153 | .startup = gsc_asic_startup_irq, | 153 | .startup = gsc_asic_startup_irq, |
154 | .shutdown = gsc_asic_disable_irq, | 154 | .shutdown = gsc_asic_disable_irq, |
@@ -158,7 +158,7 @@ static struct hw_interrupt_type gsc_asic_interrupt_type = { | |||
158 | .end = no_end_irq, | 158 | .end = no_end_irq, |
159 | }; | 159 | }; |
160 | 160 | ||
161 | int gsc_assign_irq(struct hw_interrupt_type *type, void *data) | 161 | int gsc_assign_irq(struct irq_chip *type, void *data) |
162 | { | 162 | { |
163 | static int irq = GSC_IRQ_BASE; | 163 | static int irq = GSC_IRQ_BASE; |
164 | struct irq_desc *desc; | 164 | struct irq_desc *desc; |
diff --git a/drivers/parisc/gsc.h b/drivers/parisc/gsc.h index 762a1babad60..b9d7bfb68e24 100644 --- a/drivers/parisc/gsc.h +++ b/drivers/parisc/gsc.h | |||
@@ -38,7 +38,7 @@ struct gsc_asic { | |||
38 | int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic); | 38 | int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic); |
39 | int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */ | 39 | int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */ |
40 | int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */ | 40 | int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */ |
41 | int gsc_assign_irq(struct hw_interrupt_type *type, void *data); | 41 | int gsc_assign_irq(struct irq_chip *type, void *data); |
42 | int gsc_find_local_irq(unsigned int irq, int *global_irq, int limit); | 42 | int gsc_find_local_irq(unsigned int irq, int *global_irq, int limit); |
43 | void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl, | 43 | void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl, |
44 | void (*choose)(struct parisc_device *child, void *ctrl)); | 44 | void (*choose)(struct parisc_device *child, void *ctrl)); |
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 4a9cc92d4d18..88e333553212 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c | |||
@@ -729,7 +729,7 @@ static int iosapic_set_affinity_irq(unsigned int irq, | |||
729 | } | 729 | } |
730 | #endif | 730 | #endif |
731 | 731 | ||
732 | static struct hw_interrupt_type iosapic_interrupt_type = { | 732 | static struct irq_chip iosapic_interrupt_type = { |
733 | .typename = "IO-SAPIC-level", | 733 | .typename = "IO-SAPIC-level", |
734 | .startup = iosapic_startup_irq, | 734 | .startup = iosapic_startup_irq, |
735 | .shutdown = iosapic_disable_irq, | 735 | .shutdown = iosapic_disable_irq, |
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 59fbbf128365..ede614616f8e 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c | |||
@@ -980,28 +980,38 @@ static void | |||
980 | lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) | 980 | lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) |
981 | { | 981 | { |
982 | unsigned long bytecnt; | 982 | unsigned long bytecnt; |
983 | pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; /* PA_VIEW */ | ||
984 | pdc_pat_cell_mod_maddr_block_t io_pdc_cell; /* IO_VIEW */ | ||
985 | long io_count; | 983 | long io_count; |
986 | long status; /* PDC return status */ | 984 | long status; /* PDC return status */ |
987 | long pa_count; | 985 | long pa_count; |
986 | pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; /* PA_VIEW */ | ||
987 | pdc_pat_cell_mod_maddr_block_t *io_pdc_cell; /* IO_VIEW */ | ||
988 | int i; | 988 | int i; |
989 | 989 | ||
990 | pa_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL); | ||
991 | if (!pa_pdc_cell) | ||
992 | return; | ||
993 | |||
994 | io_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL); | ||
995 | if (!pa_pdc_cell) { | ||
996 | kfree(pa_pdc_cell); | ||
997 | return; | ||
998 | } | ||
999 | |||
990 | /* return cell module (IO view) */ | 1000 | /* return cell module (IO view) */ |
991 | status = pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, | 1001 | status = pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, |
992 | PA_VIEW, & pa_pdc_cell); | 1002 | PA_VIEW, pa_pdc_cell); |
993 | pa_count = pa_pdc_cell.mod[1]; | 1003 | pa_count = pa_pdc_cell->mod[1]; |
994 | 1004 | ||
995 | status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, | 1005 | status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, |
996 | IO_VIEW, &io_pdc_cell); | 1006 | IO_VIEW, io_pdc_cell); |
997 | io_count = io_pdc_cell.mod[1]; | 1007 | io_count = io_pdc_cell->mod[1]; |
998 | 1008 | ||
999 | /* We've already done this once for device discovery...*/ | 1009 | /* We've already done this once for device discovery...*/ |
1000 | if (status != PDC_OK) { | 1010 | if (status != PDC_OK) { |
1001 | panic("pdc_pat_cell_module() call failed for LBA!\n"); | 1011 | panic("pdc_pat_cell_module() call failed for LBA!\n"); |
1002 | } | 1012 | } |
1003 | 1013 | ||
1004 | if (PAT_GET_ENTITY(pa_pdc_cell.mod_info) != PAT_ENTITY_LBA) { | 1014 | if (PAT_GET_ENTITY(pa_pdc_cell->mod_info) != PAT_ENTITY_LBA) { |
1005 | panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n"); | 1015 | panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n"); |
1006 | } | 1016 | } |
1007 | 1017 | ||
@@ -1016,8 +1026,8 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) | |||
1016 | } *p, *io; | 1026 | } *p, *io; |
1017 | struct resource *r; | 1027 | struct resource *r; |
1018 | 1028 | ||
1019 | p = (void *) &(pa_pdc_cell.mod[2+i*3]); | 1029 | p = (void *) &(pa_pdc_cell->mod[2+i*3]); |
1020 | io = (void *) &(io_pdc_cell.mod[2+i*3]); | 1030 | io = (void *) &(io_pdc_cell->mod[2+i*3]); |
1021 | 1031 | ||
1022 | /* Convert the PAT range data to PCI "struct resource" */ | 1032 | /* Convert the PAT range data to PCI "struct resource" */ |
1023 | switch(p->type & 0xff) { | 1033 | switch(p->type & 0xff) { |
@@ -1096,6 +1106,9 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) | |||
1096 | break; | 1106 | break; |
1097 | } | 1107 | } |
1098 | } | 1108 | } |
1109 | |||
1110 | kfree(pa_pdc_cell); | ||
1111 | kfree(io_pdc_cell); | ||
1099 | } | 1112 | } |
1100 | #else | 1113 | #else |
1101 | /* keep compiler from complaining about missing declarations */ | 1114 | /* keep compiler from complaining about missing declarations */ |
@@ -1509,10 +1522,6 @@ lba_driver_probe(struct parisc_device *dev) | |||
1509 | lba_bus = lba_dev->hba.hba_bus = | 1522 | lba_bus = lba_dev->hba.hba_bus = |
1510 | pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start, | 1523 | pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start, |
1511 | cfg_ops, NULL); | 1524 | cfg_ops, NULL); |
1512 | if (lba_bus) { | ||
1513 | lba_next_bus = lba_bus->subordinate + 1; | ||
1514 | pci_bus_add_devices(lba_bus); | ||
1515 | } | ||
1516 | 1525 | ||
1517 | /* This is in lieu of calling pci_assign_unassigned_resources() */ | 1526 | /* This is in lieu of calling pci_assign_unassigned_resources() */ |
1518 | if (is_pdc_pat()) { | 1527 | if (is_pdc_pat()) { |
@@ -1533,7 +1542,6 @@ lba_driver_probe(struct parisc_device *dev) | |||
1533 | } | 1542 | } |
1534 | pci_enable_bridges(lba_bus); | 1543 | pci_enable_bridges(lba_bus); |
1535 | 1544 | ||
1536 | |||
1537 | /* | 1545 | /* |
1538 | ** Once PCI register ops has walked the bus, access to config | 1546 | ** Once PCI register ops has walked the bus, access to config |
1539 | ** space is restricted. Avoids master aborts on config cycles. | 1547 | ** space is restricted. Avoids master aborts on config cycles. |
@@ -1543,6 +1551,11 @@ lba_driver_probe(struct parisc_device *dev) | |||
1543 | lba_dev->flags |= LBA_FLAG_SKIP_PROBE; | 1551 | lba_dev->flags |= LBA_FLAG_SKIP_PROBE; |
1544 | } | 1552 | } |
1545 | 1553 | ||
1554 | if (lba_bus) { | ||
1555 | lba_next_bus = lba_bus->subordinate + 1; | ||
1556 | pci_bus_add_devices(lba_bus); | ||
1557 | } | ||
1558 | |||
1546 | /* Whew! Finally done! Tell services we got this one covered. */ | 1559 | /* Whew! Finally done! Tell services we got this one covered. */ |
1547 | return 0; | 1560 | return 0; |
1548 | } | 1561 | } |
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index d46dd57450ac..123d8fe3427d 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c | |||
@@ -2057,6 +2057,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) | |||
2057 | r->start = (base & ~1UL) | PCI_F_EXTEND; | 2057 | r->start = (base & ~1UL) | PCI_F_EXTEND; |
2058 | size = ~ READ_REG32(reg + LMMIO_DIRECT0_MASK); | 2058 | size = ~ READ_REG32(reg + LMMIO_DIRECT0_MASK); |
2059 | r->end = r->start + size; | 2059 | r->end = r->start + size; |
2060 | r->flags = IORESOURCE_MEM; | ||
2060 | } | 2061 | } |
2061 | } | 2062 | } |
2062 | 2063 | ||
@@ -2093,4 +2094,5 @@ void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r ) | |||
2093 | size = (~READ_REG32(sba->sba_hpa + LMMIO_DIST_MASK)) / ROPES_PER_IOC; | 2094 | size = (~READ_REG32(sba->sba_hpa + LMMIO_DIST_MASK)) / ROPES_PER_IOC; |
2094 | r->start += rope * (size + 1); /* adjust base for this rope */ | 2095 | r->start += rope * (size + 1); /* adjust base for this rope */ |
2095 | r->end = r->start + size; | 2096 | r->end = r->start + size; |
2097 | r->flags = IORESOURCE_MEM; | ||
2096 | } | 2098 | } |
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index 33e5ade774ca..675f04e6597a 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c | |||
@@ -325,7 +325,7 @@ static unsigned int superio_startup_irq(unsigned int irq) | |||
325 | return 0; | 325 | return 0; |
326 | } | 326 | } |
327 | 327 | ||
328 | static struct hw_interrupt_type superio_interrupt_type = { | 328 | static struct irq_chip superio_interrupt_type = { |
329 | .typename = SUPERIO, | 329 | .typename = SUPERIO, |
330 | .startup = superio_startup_irq, | 330 | .startup = superio_startup_irq, |
331 | .shutdown = superio_disable_irq, | 331 | .shutdown = superio_disable_irq, |
@@ -434,8 +434,8 @@ static void __init superio_parport_init(void) | |||
434 | 0 /*base_hi*/, | 434 | 0 /*base_hi*/, |
435 | PAR_IRQ, | 435 | PAR_IRQ, |
436 | PARPORT_DMA_NONE /* dma */, | 436 | PARPORT_DMA_NONE /* dma */, |
437 | NULL /*struct pci_dev* */), | 437 | NULL /*struct pci_dev* */, |
438 | 0 /* shared irq flags */ ) | 438 | 0 /* shared irq flags */)) |
439 | 439 | ||
440 | printk(KERN_WARNING PFX "Probing parallel port failed.\n"); | 440 | printk(KERN_WARNING PFX "Probing parallel port failed.\n"); |
441 | #endif /* CONFIG_PARPORT_PC */ | 441 | #endif /* CONFIG_PARPORT_PC */ |
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 1032d5fdbd42..2597145a066e 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
@@ -2907,6 +2907,7 @@ enum parport_pc_pci_cards { | |||
2907 | netmos_9755, | 2907 | netmos_9755, |
2908 | netmos_9805, | 2908 | netmos_9805, |
2909 | netmos_9815, | 2909 | netmos_9815, |
2910 | netmos_9901, | ||
2910 | quatech_sppxp100, | 2911 | quatech_sppxp100, |
2911 | }; | 2912 | }; |
2912 | 2913 | ||
@@ -2987,7 +2988,7 @@ static struct parport_pc_pci { | |||
2987 | /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, | 2988 | /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, |
2988 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, | 2989 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, |
2989 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, | 2990 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, |
2990 | 2991 | /* netmos_9901 */ { 1, { { 0, -1 }, } }, | |
2991 | /* quatech_sppxp100 */ { 1, { { 0, 1 }, } }, | 2992 | /* quatech_sppxp100 */ { 1, { { 0, 1 }, } }, |
2992 | }; | 2993 | }; |
2993 | 2994 | ||
@@ -3089,6 +3090,8 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { | |||
3089 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 }, | 3090 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 }, |
3090 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815, | 3091 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815, |
3091 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, | 3092 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, |
3093 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, | ||
3094 | 0xA000, 0x2000, 0, 0, netmos_9901 }, | ||
3092 | /* Quatech SPPXP-100 Parallel port PCI ExpressCard */ | 3095 | /* Quatech SPPXP-100 Parallel port PCI ExpressCard */ |
3093 | { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100, | 3096 | { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100, |
3094 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 }, | 3097 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 }, |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index e53eacd75c8d..53075424a434 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <linux/sysdev.h> | 39 | #include <linux/sysdev.h> |
40 | #include <asm/cacheflush.h> | 40 | #include <asm/cacheflush.h> |
41 | #include <asm/iommu.h> | 41 | #include <asm/iommu.h> |
42 | #include <asm/e820.h> | ||
43 | #include "pci.h" | 42 | #include "pci.h" |
44 | 43 | ||
45 | #define ROOT_SIZE VTD_PAGE_SIZE | 44 | #define ROOT_SIZE VTD_PAGE_SIZE |
@@ -57,14 +56,32 @@ | |||
57 | #define MAX_AGAW_WIDTH 64 | 56 | #define MAX_AGAW_WIDTH 64 |
58 | 57 | ||
59 | #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) | 58 | #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) |
59 | #define DOMAIN_MAX_PFN(gaw) ((((u64)1) << (gaw-VTD_PAGE_SHIFT)) - 1) | ||
60 | 60 | ||
61 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) | 61 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) |
62 | #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) | 62 | #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) |
63 | #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) | 63 | #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) |
64 | 64 | ||
65 | #ifndef PHYSICAL_PAGE_MASK | 65 | |
66 | #define PHYSICAL_PAGE_MASK PAGE_MASK | 66 | /* VT-d pages must always be _smaller_ than MM pages. Otherwise things |
67 | #endif | 67 | are never going to work. */ |
68 | static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn) | ||
69 | { | ||
70 | return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT); | ||
71 | } | ||
72 | |||
73 | static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn) | ||
74 | { | ||
75 | return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT); | ||
76 | } | ||
77 | static inline unsigned long page_to_dma_pfn(struct page *pg) | ||
78 | { | ||
79 | return mm_to_dma_pfn(page_to_pfn(pg)); | ||
80 | } | ||
81 | static inline unsigned long virt_to_dma_pfn(void *p) | ||
82 | { | ||
83 | return page_to_dma_pfn(virt_to_page(p)); | ||
84 | } | ||
68 | 85 | ||
69 | /* global iommu list, set NULL for ignored DMAR units */ | 86 | /* global iommu list, set NULL for ignored DMAR units */ |
70 | static struct intel_iommu **g_iommus; | 87 | static struct intel_iommu **g_iommus; |
@@ -205,12 +222,17 @@ static inline void dma_set_pte_prot(struct dma_pte *pte, unsigned long prot) | |||
205 | 222 | ||
206 | static inline u64 dma_pte_addr(struct dma_pte *pte) | 223 | static inline u64 dma_pte_addr(struct dma_pte *pte) |
207 | { | 224 | { |
208 | return (pte->val & VTD_PAGE_MASK); | 225 | #ifdef CONFIG_64BIT |
226 | return pte->val & VTD_PAGE_MASK; | ||
227 | #else | ||
228 | /* Must have a full atomic 64-bit read */ | ||
229 | return __cmpxchg64(pte, 0ULL, 0ULL) & VTD_PAGE_MASK; | ||
230 | #endif | ||
209 | } | 231 | } |
210 | 232 | ||
211 | static inline void dma_set_pte_addr(struct dma_pte *pte, u64 addr) | 233 | static inline void dma_set_pte_pfn(struct dma_pte *pte, unsigned long pfn) |
212 | { | 234 | { |
213 | pte->val |= (addr & VTD_PAGE_MASK); | 235 | pte->val |= (uint64_t)pfn << VTD_PAGE_SHIFT; |
214 | } | 236 | } |
215 | 237 | ||
216 | static inline bool dma_pte_present(struct dma_pte *pte) | 238 | static inline bool dma_pte_present(struct dma_pte *pte) |
@@ -218,6 +240,11 @@ static inline bool dma_pte_present(struct dma_pte *pte) | |||
218 | return (pte->val & 3) != 0; | 240 | return (pte->val & 3) != 0; |
219 | } | 241 | } |
220 | 242 | ||
243 | static inline int first_pte_in_page(struct dma_pte *pte) | ||
244 | { | ||
245 | return !((unsigned long)pte & ~VTD_PAGE_MASK); | ||
246 | } | ||
247 | |||
221 | /* | 248 | /* |
222 | * This domain is a statically identity mapping domain. | 249 | * This domain is a statically identity mapping domain. |
223 | * 1. This domain creats a static 1:1 mapping to all usable memory. | 250 | * 1. This domain creats a static 1:1 mapping to all usable memory. |
@@ -245,7 +272,6 @@ struct dmar_domain { | |||
245 | struct iova_domain iovad; /* iova's that belong to this domain */ | 272 | struct iova_domain iovad; /* iova's that belong to this domain */ |
246 | 273 | ||
247 | struct dma_pte *pgd; /* virtual address */ | 274 | struct dma_pte *pgd; /* virtual address */ |
248 | spinlock_t mapping_lock; /* page table lock */ | ||
249 | int gaw; /* max guest address width */ | 275 | int gaw; /* max guest address width */ |
250 | 276 | ||
251 | /* adjusted guest address width, 0 is level 2 30-bit */ | 277 | /* adjusted guest address width, 0 is level 2 30-bit */ |
@@ -649,80 +675,78 @@ static inline int width_to_agaw(int width) | |||
649 | 675 | ||
650 | static inline unsigned int level_to_offset_bits(int level) | 676 | static inline unsigned int level_to_offset_bits(int level) |
651 | { | 677 | { |
652 | return (12 + (level - 1) * LEVEL_STRIDE); | 678 | return (level - 1) * LEVEL_STRIDE; |
653 | } | 679 | } |
654 | 680 | ||
655 | static inline int address_level_offset(u64 addr, int level) | 681 | static inline int pfn_level_offset(unsigned long pfn, int level) |
656 | { | 682 | { |
657 | return ((addr >> level_to_offset_bits(level)) & LEVEL_MASK); | 683 | return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; |
658 | } | 684 | } |
659 | 685 | ||
660 | static inline u64 level_mask(int level) | 686 | static inline unsigned long level_mask(int level) |
661 | { | 687 | { |
662 | return ((u64)-1 << level_to_offset_bits(level)); | 688 | return -1UL << level_to_offset_bits(level); |
663 | } | 689 | } |
664 | 690 | ||
665 | static inline u64 level_size(int level) | 691 | static inline unsigned long level_size(int level) |
666 | { | 692 | { |
667 | return ((u64)1 << level_to_offset_bits(level)); | 693 | return 1UL << level_to_offset_bits(level); |
668 | } | 694 | } |
669 | 695 | ||
670 | static inline u64 align_to_level(u64 addr, int level) | 696 | static inline unsigned long align_to_level(unsigned long pfn, int level) |
671 | { | 697 | { |
672 | return ((addr + level_size(level) - 1) & level_mask(level)); | 698 | return (pfn + level_size(level) - 1) & level_mask(level); |
673 | } | 699 | } |
674 | 700 | ||
675 | static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr) | 701 | static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, |
702 | unsigned long pfn) | ||
676 | { | 703 | { |
677 | int addr_width = agaw_to_width(domain->agaw); | 704 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
678 | struct dma_pte *parent, *pte = NULL; | 705 | struct dma_pte *parent, *pte = NULL; |
679 | int level = agaw_to_level(domain->agaw); | 706 | int level = agaw_to_level(domain->agaw); |
680 | int offset; | 707 | int offset; |
681 | unsigned long flags; | ||
682 | 708 | ||
683 | BUG_ON(!domain->pgd); | 709 | BUG_ON(!domain->pgd); |
684 | 710 | BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width); | |
685 | addr &= (((u64)1) << addr_width) - 1; | ||
686 | parent = domain->pgd; | 711 | parent = domain->pgd; |
687 | 712 | ||
688 | spin_lock_irqsave(&domain->mapping_lock, flags); | ||
689 | while (level > 0) { | 713 | while (level > 0) { |
690 | void *tmp_page; | 714 | void *tmp_page; |
691 | 715 | ||
692 | offset = address_level_offset(addr, level); | 716 | offset = pfn_level_offset(pfn, level); |
693 | pte = &parent[offset]; | 717 | pte = &parent[offset]; |
694 | if (level == 1) | 718 | if (level == 1) |
695 | break; | 719 | break; |
696 | 720 | ||
697 | if (!dma_pte_present(pte)) { | 721 | if (!dma_pte_present(pte)) { |
722 | uint64_t pteval; | ||
723 | |||
698 | tmp_page = alloc_pgtable_page(); | 724 | tmp_page = alloc_pgtable_page(); |
699 | 725 | ||
700 | if (!tmp_page) { | 726 | if (!tmp_page) |
701 | spin_unlock_irqrestore(&domain->mapping_lock, | ||
702 | flags); | ||
703 | return NULL; | 727 | return NULL; |
728 | |||
729 | domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE); | ||
730 | pteval = (virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE; | ||
731 | if (cmpxchg64(&pte->val, 0ULL, pteval)) { | ||
732 | /* Someone else set it while we were thinking; use theirs. */ | ||
733 | free_pgtable_page(tmp_page); | ||
734 | } else { | ||
735 | dma_pte_addr(pte); | ||
736 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
704 | } | 737 | } |
705 | domain_flush_cache(domain, tmp_page, PAGE_SIZE); | ||
706 | dma_set_pte_addr(pte, virt_to_phys(tmp_page)); | ||
707 | /* | ||
708 | * high level table always sets r/w, last level page | ||
709 | * table control read/write | ||
710 | */ | ||
711 | dma_set_pte_readable(pte); | ||
712 | dma_set_pte_writable(pte); | ||
713 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
714 | } | 738 | } |
715 | parent = phys_to_virt(dma_pte_addr(pte)); | 739 | parent = phys_to_virt(dma_pte_addr(pte)); |
716 | level--; | 740 | level--; |
717 | } | 741 | } |
718 | 742 | ||
719 | spin_unlock_irqrestore(&domain->mapping_lock, flags); | ||
720 | return pte; | 743 | return pte; |
721 | } | 744 | } |
722 | 745 | ||
723 | /* return address's pte at specific level */ | 746 | /* return address's pte at specific level */ |
724 | static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, | 747 | static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain, |
725 | int level) | 748 | unsigned long pfn, |
749 | int level) | ||
726 | { | 750 | { |
727 | struct dma_pte *parent, *pte = NULL; | 751 | struct dma_pte *parent, *pte = NULL; |
728 | int total = agaw_to_level(domain->agaw); | 752 | int total = agaw_to_level(domain->agaw); |
@@ -730,7 +754,7 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, | |||
730 | 754 | ||
731 | parent = domain->pgd; | 755 | parent = domain->pgd; |
732 | while (level <= total) { | 756 | while (level <= total) { |
733 | offset = address_level_offset(addr, total); | 757 | offset = pfn_level_offset(pfn, total); |
734 | pte = &parent[offset]; | 758 | pte = &parent[offset]; |
735 | if (level == total) | 759 | if (level == total) |
736 | return pte; | 760 | return pte; |
@@ -743,74 +767,82 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, | |||
743 | return NULL; | 767 | return NULL; |
744 | } | 768 | } |
745 | 769 | ||
746 | /* clear one page's page table */ | ||
747 | static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr) | ||
748 | { | ||
749 | struct dma_pte *pte = NULL; | ||
750 | |||
751 | /* get last level pte */ | ||
752 | pte = dma_addr_level_pte(domain, addr, 1); | ||
753 | |||
754 | if (pte) { | ||
755 | dma_clear_pte(pte); | ||
756 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
757 | } | ||
758 | } | ||
759 | |||
760 | /* clear last level pte, a tlb flush should be followed */ | 770 | /* clear last level pte, a tlb flush should be followed */ |
761 | static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end) | 771 | static void dma_pte_clear_range(struct dmar_domain *domain, |
772 | unsigned long start_pfn, | ||
773 | unsigned long last_pfn) | ||
762 | { | 774 | { |
763 | int addr_width = agaw_to_width(domain->agaw); | 775 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
764 | int npages; | 776 | struct dma_pte *first_pte, *pte; |
777 | |||
778 | BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); | ||
779 | BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); | ||
765 | 780 | ||
766 | start &= (((u64)1) << addr_width) - 1; | 781 | /* we don't need lock here; nobody else touches the iova range */ |
767 | end &= (((u64)1) << addr_width) - 1; | 782 | while (start_pfn <= last_pfn) { |
768 | /* in case it's partial page */ | 783 | first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1); |
769 | start &= PAGE_MASK; | 784 | if (!pte) { |
770 | end = PAGE_ALIGN(end); | 785 | start_pfn = align_to_level(start_pfn + 1, 2); |
771 | npages = (end - start) / VTD_PAGE_SIZE; | 786 | continue; |
787 | } | ||
788 | do { | ||
789 | dma_clear_pte(pte); | ||
790 | start_pfn++; | ||
791 | pte++; | ||
792 | } while (start_pfn <= last_pfn && !first_pte_in_page(pte)); | ||
772 | 793 | ||
773 | /* we don't need lock here, nobody else touches the iova range */ | 794 | domain_flush_cache(domain, first_pte, |
774 | while (npages--) { | 795 | (void *)pte - (void *)first_pte); |
775 | dma_pte_clear_one(domain, start); | ||
776 | start += VTD_PAGE_SIZE; | ||
777 | } | 796 | } |
778 | } | 797 | } |
779 | 798 | ||
780 | /* free page table pages. last level pte should already be cleared */ | 799 | /* free page table pages. last level pte should already be cleared */ |
781 | static void dma_pte_free_pagetable(struct dmar_domain *domain, | 800 | static void dma_pte_free_pagetable(struct dmar_domain *domain, |
782 | u64 start, u64 end) | 801 | unsigned long start_pfn, |
802 | unsigned long last_pfn) | ||
783 | { | 803 | { |
784 | int addr_width = agaw_to_width(domain->agaw); | 804 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
785 | struct dma_pte *pte; | 805 | struct dma_pte *first_pte, *pte; |
786 | int total = agaw_to_level(domain->agaw); | 806 | int total = agaw_to_level(domain->agaw); |
787 | int level; | 807 | int level; |
788 | u64 tmp; | 808 | unsigned long tmp; |
789 | 809 | ||
790 | start &= (((u64)1) << addr_width) - 1; | 810 | BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); |
791 | end &= (((u64)1) << addr_width) - 1; | 811 | BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); |
792 | 812 | ||
793 | /* we don't need lock here, nobody else touches the iova range */ | 813 | /* We don't need lock here; nobody else touches the iova range */ |
794 | level = 2; | 814 | level = 2; |
795 | while (level <= total) { | 815 | while (level <= total) { |
796 | tmp = align_to_level(start, level); | 816 | tmp = align_to_level(start_pfn, level); |
797 | if (tmp >= end || (tmp + level_size(level) > end)) | 817 | |
818 | /* If we can't even clear one PTE at this level, we're done */ | ||
819 | if (tmp + level_size(level) - 1 > last_pfn) | ||
798 | return; | 820 | return; |
799 | 821 | ||
800 | while (tmp < end) { | 822 | while (tmp + level_size(level) - 1 <= last_pfn) { |
801 | pte = dma_addr_level_pte(domain, tmp, level); | 823 | first_pte = pte = dma_pfn_level_pte(domain, tmp, level); |
802 | if (pte) { | 824 | if (!pte) { |
803 | free_pgtable_page( | 825 | tmp = align_to_level(tmp + 1, level + 1); |
804 | phys_to_virt(dma_pte_addr(pte))); | 826 | continue; |
805 | dma_clear_pte(pte); | ||
806 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
807 | } | 827 | } |
808 | tmp += level_size(level); | 828 | do { |
829 | if (dma_pte_present(pte)) { | ||
830 | free_pgtable_page(phys_to_virt(dma_pte_addr(pte))); | ||
831 | dma_clear_pte(pte); | ||
832 | } | ||
833 | pte++; | ||
834 | tmp += level_size(level); | ||
835 | } while (!first_pte_in_page(pte) && | ||
836 | tmp + level_size(level) - 1 <= last_pfn); | ||
837 | |||
838 | domain_flush_cache(domain, first_pte, | ||
839 | (void *)pte - (void *)first_pte); | ||
840 | |||
809 | } | 841 | } |
810 | level++; | 842 | level++; |
811 | } | 843 | } |
812 | /* free pgd */ | 844 | /* free pgd */ |
813 | if (start == 0 && end >= ((((u64)1) << addr_width) - 1)) { | 845 | if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) { |
814 | free_pgtable_page(domain->pgd); | 846 | free_pgtable_page(domain->pgd); |
815 | domain->pgd = NULL; | 847 | domain->pgd = NULL; |
816 | } | 848 | } |
@@ -1036,11 +1068,11 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain, | |||
1036 | } | 1068 | } |
1037 | 1069 | ||
1038 | static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, | 1070 | static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, |
1039 | u64 addr, unsigned int pages) | 1071 | unsigned long pfn, unsigned int pages) |
1040 | { | 1072 | { |
1041 | unsigned int mask = ilog2(__roundup_pow_of_two(pages)); | 1073 | unsigned int mask = ilog2(__roundup_pow_of_two(pages)); |
1074 | uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT; | ||
1042 | 1075 | ||
1043 | BUG_ON(addr & (~VTD_PAGE_MASK)); | ||
1044 | BUG_ON(pages == 0); | 1076 | BUG_ON(pages == 0); |
1045 | 1077 | ||
1046 | /* | 1078 | /* |
@@ -1055,7 +1087,12 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, | |||
1055 | else | 1087 | else |
1056 | iommu->flush.flush_iotlb(iommu, did, addr, mask, | 1088 | iommu->flush.flush_iotlb(iommu, did, addr, mask, |
1057 | DMA_TLB_PSI_FLUSH); | 1089 | DMA_TLB_PSI_FLUSH); |
1058 | if (did) | 1090 | |
1091 | /* | ||
1092 | * In caching mode, domain ID 0 is reserved for non-present to present | ||
1093 | * mapping flush. Device IOTLB doesn't need to be flushed in this case. | ||
1094 | */ | ||
1095 | if (!cap_caching_mode(iommu->cap) || did) | ||
1059 | iommu_flush_dev_iotlb(iommu->domains[did], addr, mask); | 1096 | iommu_flush_dev_iotlb(iommu->domains[did], addr, mask); |
1060 | } | 1097 | } |
1061 | 1098 | ||
@@ -1280,7 +1317,6 @@ static void dmar_init_reserved_ranges(void) | |||
1280 | struct pci_dev *pdev = NULL; | 1317 | struct pci_dev *pdev = NULL; |
1281 | struct iova *iova; | 1318 | struct iova *iova; |
1282 | int i; | 1319 | int i; |
1283 | u64 addr, size; | ||
1284 | 1320 | ||
1285 | init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); | 1321 | init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); |
1286 | 1322 | ||
@@ -1303,12 +1339,9 @@ static void dmar_init_reserved_ranges(void) | |||
1303 | r = &pdev->resource[i]; | 1339 | r = &pdev->resource[i]; |
1304 | if (!r->flags || !(r->flags & IORESOURCE_MEM)) | 1340 | if (!r->flags || !(r->flags & IORESOURCE_MEM)) |
1305 | continue; | 1341 | continue; |
1306 | addr = r->start; | 1342 | iova = reserve_iova(&reserved_iova_list, |
1307 | addr &= PHYSICAL_PAGE_MASK; | 1343 | IOVA_PFN(r->start), |
1308 | size = r->end - addr; | 1344 | IOVA_PFN(r->end)); |
1309 | size = PAGE_ALIGN(size); | ||
1310 | iova = reserve_iova(&reserved_iova_list, IOVA_PFN(addr), | ||
1311 | IOVA_PFN(size + addr) - 1); | ||
1312 | if (!iova) | 1345 | if (!iova) |
1313 | printk(KERN_ERR "Reserve iova failed\n"); | 1346 | printk(KERN_ERR "Reserve iova failed\n"); |
1314 | } | 1347 | } |
@@ -1342,7 +1375,6 @@ static int domain_init(struct dmar_domain *domain, int guest_width) | |||
1342 | unsigned long sagaw; | 1375 | unsigned long sagaw; |
1343 | 1376 | ||
1344 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); | 1377 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); |
1345 | spin_lock_init(&domain->mapping_lock); | ||
1346 | spin_lock_init(&domain->iommu_lock); | 1378 | spin_lock_init(&domain->iommu_lock); |
1347 | 1379 | ||
1348 | domain_reserve_special_ranges(domain); | 1380 | domain_reserve_special_ranges(domain); |
@@ -1389,7 +1421,6 @@ static void domain_exit(struct dmar_domain *domain) | |||
1389 | { | 1421 | { |
1390 | struct dmar_drhd_unit *drhd; | 1422 | struct dmar_drhd_unit *drhd; |
1391 | struct intel_iommu *iommu; | 1423 | struct intel_iommu *iommu; |
1392 | u64 end; | ||
1393 | 1424 | ||
1394 | /* Domain 0 is reserved, so dont process it */ | 1425 | /* Domain 0 is reserved, so dont process it */ |
1395 | if (!domain) | 1426 | if (!domain) |
@@ -1398,14 +1429,12 @@ static void domain_exit(struct dmar_domain *domain) | |||
1398 | domain_remove_dev_info(domain); | 1429 | domain_remove_dev_info(domain); |
1399 | /* destroy iovas */ | 1430 | /* destroy iovas */ |
1400 | put_iova_domain(&domain->iovad); | 1431 | put_iova_domain(&domain->iovad); |
1401 | end = DOMAIN_MAX_ADDR(domain->gaw); | ||
1402 | end = end & (~PAGE_MASK); | ||
1403 | 1432 | ||
1404 | /* clear ptes */ | 1433 | /* clear ptes */ |
1405 | dma_pte_clear_range(domain, 0, end); | 1434 | dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
1406 | 1435 | ||
1407 | /* free page tables */ | 1436 | /* free page tables */ |
1408 | dma_pte_free_pagetable(domain, 0, end); | 1437 | dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
1409 | 1438 | ||
1410 | for_each_active_iommu(iommu, drhd) | 1439 | for_each_active_iommu(iommu, drhd) |
1411 | if (test_bit(iommu->seq_id, &domain->iommu_bmp)) | 1440 | if (test_bit(iommu->seq_id, &domain->iommu_bmp)) |
@@ -1619,42 +1648,86 @@ static int domain_context_mapped(struct pci_dev *pdev) | |||
1619 | tmp->devfn); | 1648 | tmp->devfn); |
1620 | } | 1649 | } |
1621 | 1650 | ||
1622 | static int | 1651 | static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, |
1623 | domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, | 1652 | struct scatterlist *sg, unsigned long phys_pfn, |
1624 | u64 hpa, size_t size, int prot) | 1653 | unsigned long nr_pages, int prot) |
1625 | { | 1654 | { |
1626 | u64 start_pfn, end_pfn; | 1655 | struct dma_pte *first_pte = NULL, *pte = NULL; |
1627 | struct dma_pte *pte; | 1656 | phys_addr_t uninitialized_var(pteval); |
1628 | int index; | 1657 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
1629 | int addr_width = agaw_to_width(domain->agaw); | 1658 | unsigned long sg_res; |
1630 | 1659 | ||
1631 | hpa &= (((u64)1) << addr_width) - 1; | 1660 | BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width); |
1632 | 1661 | ||
1633 | if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) | 1662 | if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) |
1634 | return -EINVAL; | 1663 | return -EINVAL; |
1635 | iova &= PAGE_MASK; | 1664 | |
1636 | start_pfn = ((u64)hpa) >> VTD_PAGE_SHIFT; | 1665 | prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; |
1637 | end_pfn = (VTD_PAGE_ALIGN(((u64)hpa) + size)) >> VTD_PAGE_SHIFT; | 1666 | |
1638 | index = 0; | 1667 | if (sg) |
1639 | while (start_pfn < end_pfn) { | 1668 | sg_res = 0; |
1640 | pte = addr_to_dma_pte(domain, iova + VTD_PAGE_SIZE * index); | 1669 | else { |
1641 | if (!pte) | 1670 | sg_res = nr_pages + 1; |
1642 | return -ENOMEM; | 1671 | pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot; |
1672 | } | ||
1673 | |||
1674 | while (nr_pages--) { | ||
1675 | uint64_t tmp; | ||
1676 | |||
1677 | if (!sg_res) { | ||
1678 | sg_res = (sg->offset + sg->length + VTD_PAGE_SIZE - 1) >> VTD_PAGE_SHIFT; | ||
1679 | sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset; | ||
1680 | sg->dma_length = sg->length; | ||
1681 | pteval = page_to_phys(sg_page(sg)) | prot; | ||
1682 | } | ||
1683 | if (!pte) { | ||
1684 | first_pte = pte = pfn_to_dma_pte(domain, iov_pfn); | ||
1685 | if (!pte) | ||
1686 | return -ENOMEM; | ||
1687 | } | ||
1643 | /* We don't need lock here, nobody else | 1688 | /* We don't need lock here, nobody else |
1644 | * touches the iova range | 1689 | * touches the iova range |
1645 | */ | 1690 | */ |
1646 | BUG_ON(dma_pte_addr(pte)); | 1691 | tmp = cmpxchg64_local(&pte->val, 0ULL, pteval); |
1647 | dma_set_pte_addr(pte, start_pfn << VTD_PAGE_SHIFT); | 1692 | if (tmp) { |
1648 | dma_set_pte_prot(pte, prot); | 1693 | static int dumps = 5; |
1649 | if (prot & DMA_PTE_SNP) | 1694 | printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n", |
1650 | dma_set_pte_snp(pte); | 1695 | iov_pfn, tmp, (unsigned long long)pteval); |
1651 | domain_flush_cache(domain, pte, sizeof(*pte)); | 1696 | if (dumps) { |
1652 | start_pfn++; | 1697 | dumps--; |
1653 | index++; | 1698 | debug_dma_dump_mappings(NULL); |
1699 | } | ||
1700 | WARN_ON(1); | ||
1701 | } | ||
1702 | pte++; | ||
1703 | if (!nr_pages || first_pte_in_page(pte)) { | ||
1704 | domain_flush_cache(domain, first_pte, | ||
1705 | (void *)pte - (void *)first_pte); | ||
1706 | pte = NULL; | ||
1707 | } | ||
1708 | iov_pfn++; | ||
1709 | pteval += VTD_PAGE_SIZE; | ||
1710 | sg_res--; | ||
1711 | if (!sg_res) | ||
1712 | sg = sg_next(sg); | ||
1654 | } | 1713 | } |
1655 | return 0; | 1714 | return 0; |
1656 | } | 1715 | } |
1657 | 1716 | ||
1717 | static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn, | ||
1718 | struct scatterlist *sg, unsigned long nr_pages, | ||
1719 | int prot) | ||
1720 | { | ||
1721 | return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot); | ||
1722 | } | ||
1723 | |||
1724 | static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn, | ||
1725 | unsigned long phys_pfn, unsigned long nr_pages, | ||
1726 | int prot) | ||
1727 | { | ||
1728 | return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot); | ||
1729 | } | ||
1730 | |||
1658 | static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn) | 1731 | static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn) |
1659 | { | 1732 | { |
1660 | if (!iommu) | 1733 | if (!iommu) |
@@ -1845,58 +1918,61 @@ error: | |||
1845 | 1918 | ||
1846 | static int iommu_identity_mapping; | 1919 | static int iommu_identity_mapping; |
1847 | 1920 | ||
1921 | static int iommu_domain_identity_map(struct dmar_domain *domain, | ||
1922 | unsigned long long start, | ||
1923 | unsigned long long end) | ||
1924 | { | ||
1925 | unsigned long first_vpfn = start >> VTD_PAGE_SHIFT; | ||
1926 | unsigned long last_vpfn = end >> VTD_PAGE_SHIFT; | ||
1927 | |||
1928 | if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn), | ||
1929 | dma_to_mm_pfn(last_vpfn))) { | ||
1930 | printk(KERN_ERR "IOMMU: reserve iova failed\n"); | ||
1931 | return -ENOMEM; | ||
1932 | } | ||
1933 | |||
1934 | pr_debug("Mapping reserved region %llx-%llx for domain %d\n", | ||
1935 | start, end, domain->id); | ||
1936 | /* | ||
1937 | * RMRR range might have overlap with physical memory range, | ||
1938 | * clear it first | ||
1939 | */ | ||
1940 | dma_pte_clear_range(domain, first_vpfn, last_vpfn); | ||
1941 | |||
1942 | return domain_pfn_mapping(domain, first_vpfn, first_vpfn, | ||
1943 | last_vpfn - first_vpfn + 1, | ||
1944 | DMA_PTE_READ|DMA_PTE_WRITE); | ||
1945 | } | ||
1946 | |||
1848 | static int iommu_prepare_identity_map(struct pci_dev *pdev, | 1947 | static int iommu_prepare_identity_map(struct pci_dev *pdev, |
1849 | unsigned long long start, | 1948 | unsigned long long start, |
1850 | unsigned long long end) | 1949 | unsigned long long end) |
1851 | { | 1950 | { |
1852 | struct dmar_domain *domain; | 1951 | struct dmar_domain *domain; |
1853 | unsigned long size; | ||
1854 | unsigned long long base; | ||
1855 | int ret; | 1952 | int ret; |
1856 | 1953 | ||
1857 | printk(KERN_INFO | 1954 | printk(KERN_INFO |
1858 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", | 1955 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", |
1859 | pci_name(pdev), start, end); | 1956 | pci_name(pdev), start, end); |
1860 | if (iommu_identity_mapping) | 1957 | |
1861 | domain = si_domain; | 1958 | domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); |
1862 | else | ||
1863 | /* page table init */ | ||
1864 | domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); | ||
1865 | if (!domain) | 1959 | if (!domain) |
1866 | return -ENOMEM; | 1960 | return -ENOMEM; |
1867 | 1961 | ||
1868 | /* The address might not be aligned */ | 1962 | ret = iommu_domain_identity_map(domain, start, end); |
1869 | base = start & PAGE_MASK; | ||
1870 | size = end - base; | ||
1871 | size = PAGE_ALIGN(size); | ||
1872 | if (!reserve_iova(&domain->iovad, IOVA_PFN(base), | ||
1873 | IOVA_PFN(base + size) - 1)) { | ||
1874 | printk(KERN_ERR "IOMMU: reserve iova failed\n"); | ||
1875 | ret = -ENOMEM; | ||
1876 | goto error; | ||
1877 | } | ||
1878 | |||
1879 | pr_debug("Mapping reserved region %lx@%llx for %s\n", | ||
1880 | size, base, pci_name(pdev)); | ||
1881 | /* | ||
1882 | * RMRR range might have overlap with physical memory range, | ||
1883 | * clear it first | ||
1884 | */ | ||
1885 | dma_pte_clear_range(domain, base, base + size); | ||
1886 | |||
1887 | ret = domain_page_mapping(domain, base, base, size, | ||
1888 | DMA_PTE_READ|DMA_PTE_WRITE); | ||
1889 | if (ret) | 1963 | if (ret) |
1890 | goto error; | 1964 | goto error; |
1891 | 1965 | ||
1892 | /* context entry init */ | 1966 | /* context entry init */ |
1893 | ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL); | 1967 | ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL); |
1894 | if (!ret) | 1968 | if (ret) |
1895 | return 0; | 1969 | goto error; |
1896 | error: | 1970 | |
1971 | return 0; | ||
1972 | |||
1973 | error: | ||
1897 | domain_exit(domain); | 1974 | domain_exit(domain); |
1898 | return ret; | 1975 | return ret; |
1899 | |||
1900 | } | 1976 | } |
1901 | 1977 | ||
1902 | static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, | 1978 | static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, |
@@ -1908,64 +1984,6 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, | |||
1908 | rmrr->end_address + 1); | 1984 | rmrr->end_address + 1); |
1909 | } | 1985 | } |
1910 | 1986 | ||
1911 | #ifdef CONFIG_DMAR_GFX_WA | ||
1912 | struct iommu_prepare_data { | ||
1913 | struct pci_dev *pdev; | ||
1914 | int ret; | ||
1915 | }; | ||
1916 | |||
1917 | static int __init iommu_prepare_work_fn(unsigned long start_pfn, | ||
1918 | unsigned long end_pfn, void *datax) | ||
1919 | { | ||
1920 | struct iommu_prepare_data *data; | ||
1921 | |||
1922 | data = (struct iommu_prepare_data *)datax; | ||
1923 | |||
1924 | data->ret = iommu_prepare_identity_map(data->pdev, | ||
1925 | start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); | ||
1926 | return data->ret; | ||
1927 | |||
1928 | } | ||
1929 | |||
1930 | static int __init iommu_prepare_with_active_regions(struct pci_dev *pdev) | ||
1931 | { | ||
1932 | int nid; | ||
1933 | struct iommu_prepare_data data; | ||
1934 | |||
1935 | data.pdev = pdev; | ||
1936 | data.ret = 0; | ||
1937 | |||
1938 | for_each_online_node(nid) { | ||
1939 | work_with_active_regions(nid, iommu_prepare_work_fn, &data); | ||
1940 | if (data.ret) | ||
1941 | return data.ret; | ||
1942 | } | ||
1943 | return data.ret; | ||
1944 | } | ||
1945 | |||
1946 | static void __init iommu_prepare_gfx_mapping(void) | ||
1947 | { | ||
1948 | struct pci_dev *pdev = NULL; | ||
1949 | int ret; | ||
1950 | |||
1951 | for_each_pci_dev(pdev) { | ||
1952 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO || | ||
1953 | !IS_GFX_DEVICE(pdev)) | ||
1954 | continue; | ||
1955 | printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n", | ||
1956 | pci_name(pdev)); | ||
1957 | ret = iommu_prepare_with_active_regions(pdev); | ||
1958 | if (ret) | ||
1959 | printk(KERN_ERR "IOMMU: mapping reserved region failed\n"); | ||
1960 | } | ||
1961 | } | ||
1962 | #else /* !CONFIG_DMAR_GFX_WA */ | ||
1963 | static inline void iommu_prepare_gfx_mapping(void) | ||
1964 | { | ||
1965 | return; | ||
1966 | } | ||
1967 | #endif | ||
1968 | |||
1969 | #ifdef CONFIG_DMAR_FLOPPY_WA | 1987 | #ifdef CONFIG_DMAR_FLOPPY_WA |
1970 | static inline void iommu_prepare_isa(void) | 1988 | static inline void iommu_prepare_isa(void) |
1971 | { | 1989 | { |
@@ -1976,12 +1994,12 @@ static inline void iommu_prepare_isa(void) | |||
1976 | if (!pdev) | 1994 | if (!pdev) |
1977 | return; | 1995 | return; |
1978 | 1996 | ||
1979 | printk(KERN_INFO "IOMMU: Prepare 0-16M unity mapping for LPC\n"); | 1997 | printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n"); |
1980 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); | 1998 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); |
1981 | 1999 | ||
1982 | if (ret) | 2000 | if (ret) |
1983 | printk(KERN_ERR "IOMMU: Failed to create 0-64M identity map, " | 2001 | printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; " |
1984 | "floppy might not work\n"); | 2002 | "floppy might not work\n"); |
1985 | 2003 | ||
1986 | } | 2004 | } |
1987 | #else | 2005 | #else |
@@ -2009,16 +2027,30 @@ static int __init init_context_pass_through(void) | |||
2009 | } | 2027 | } |
2010 | 2028 | ||
2011 | static int md_domain_init(struct dmar_domain *domain, int guest_width); | 2029 | static int md_domain_init(struct dmar_domain *domain, int guest_width); |
2030 | |||
2031 | static int __init si_domain_work_fn(unsigned long start_pfn, | ||
2032 | unsigned long end_pfn, void *datax) | ||
2033 | { | ||
2034 | int *ret = datax; | ||
2035 | |||
2036 | *ret = iommu_domain_identity_map(si_domain, | ||
2037 | (uint64_t)start_pfn << PAGE_SHIFT, | ||
2038 | (uint64_t)end_pfn << PAGE_SHIFT); | ||
2039 | return *ret; | ||
2040 | |||
2041 | } | ||
2042 | |||
2012 | static int si_domain_init(void) | 2043 | static int si_domain_init(void) |
2013 | { | 2044 | { |
2014 | struct dmar_drhd_unit *drhd; | 2045 | struct dmar_drhd_unit *drhd; |
2015 | struct intel_iommu *iommu; | 2046 | struct intel_iommu *iommu; |
2016 | int ret = 0; | 2047 | int nid, ret = 0; |
2017 | 2048 | ||
2018 | si_domain = alloc_domain(); | 2049 | si_domain = alloc_domain(); |
2019 | if (!si_domain) | 2050 | if (!si_domain) |
2020 | return -EFAULT; | 2051 | return -EFAULT; |
2021 | 2052 | ||
2053 | pr_debug("Identity mapping domain is domain %d\n", si_domain->id); | ||
2022 | 2054 | ||
2023 | for_each_active_iommu(iommu, drhd) { | 2055 | for_each_active_iommu(iommu, drhd) { |
2024 | ret = iommu_attach_domain(si_domain, iommu); | 2056 | ret = iommu_attach_domain(si_domain, iommu); |
@@ -2035,6 +2067,12 @@ static int si_domain_init(void) | |||
2035 | 2067 | ||
2036 | si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; | 2068 | si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; |
2037 | 2069 | ||
2070 | for_each_online_node(nid) { | ||
2071 | work_with_active_regions(nid, si_domain_work_fn, &ret); | ||
2072 | if (ret) | ||
2073 | return ret; | ||
2074 | } | ||
2075 | |||
2038 | return 0; | 2076 | return 0; |
2039 | } | 2077 | } |
2040 | 2078 | ||
@@ -2081,7 +2119,6 @@ static int domain_add_dev_info(struct dmar_domain *domain, | |||
2081 | 2119 | ||
2082 | static int iommu_prepare_static_identity_mapping(void) | 2120 | static int iommu_prepare_static_identity_mapping(void) |
2083 | { | 2121 | { |
2084 | int i; | ||
2085 | struct pci_dev *pdev = NULL; | 2122 | struct pci_dev *pdev = NULL; |
2086 | int ret; | 2123 | int ret; |
2087 | 2124 | ||
@@ -2089,20 +2126,14 @@ static int iommu_prepare_static_identity_mapping(void) | |||
2089 | if (ret) | 2126 | if (ret) |
2090 | return -EFAULT; | 2127 | return -EFAULT; |
2091 | 2128 | ||
2092 | printk(KERN_INFO "IOMMU: Setting identity map:\n"); | ||
2093 | for_each_pci_dev(pdev) { | 2129 | for_each_pci_dev(pdev) { |
2094 | for (i = 0; i < e820.nr_map; i++) { | 2130 | printk(KERN_INFO "IOMMU: identity mapping for device %s\n", |
2095 | struct e820entry *ei = &e820.map[i]; | 2131 | pci_name(pdev)); |
2096 | 2132 | ||
2097 | if (ei->type == E820_RAM) { | 2133 | ret = domain_context_mapping(si_domain, pdev, |
2098 | ret = iommu_prepare_identity_map(pdev, | 2134 | CONTEXT_TT_MULTI_LEVEL); |
2099 | ei->addr, ei->addr + ei->size); | 2135 | if (ret) |
2100 | if (ret) { | 2136 | return ret; |
2101 | printk(KERN_INFO "1:1 mapping to one domain failed.\n"); | ||
2102 | return -EFAULT; | ||
2103 | } | ||
2104 | } | ||
2105 | } | ||
2106 | ret = domain_add_dev_info(si_domain, pdev); | 2137 | ret = domain_add_dev_info(si_domain, pdev); |
2107 | if (ret) | 2138 | if (ret) |
2108 | return ret; | 2139 | return ret; |
@@ -2293,8 +2324,6 @@ int __init init_dmars(void) | |||
2293 | } | 2324 | } |
2294 | } | 2325 | } |
2295 | 2326 | ||
2296 | iommu_prepare_gfx_mapping(); | ||
2297 | |||
2298 | iommu_prepare_isa(); | 2327 | iommu_prepare_isa(); |
2299 | } | 2328 | } |
2300 | 2329 | ||
@@ -2339,50 +2368,40 @@ error: | |||
2339 | return ret; | 2368 | return ret; |
2340 | } | 2369 | } |
2341 | 2370 | ||
2342 | static inline u64 aligned_size(u64 host_addr, size_t size) | 2371 | static inline unsigned long aligned_nrpages(unsigned long host_addr, |
2343 | { | 2372 | size_t size) |
2344 | u64 addr; | ||
2345 | addr = (host_addr & (~PAGE_MASK)) + size; | ||
2346 | return PAGE_ALIGN(addr); | ||
2347 | } | ||
2348 | |||
2349 | struct iova * | ||
2350 | iommu_alloc_iova(struct dmar_domain *domain, size_t size, u64 end) | ||
2351 | { | 2373 | { |
2352 | struct iova *piova; | 2374 | host_addr &= ~PAGE_MASK; |
2375 | host_addr += size + PAGE_SIZE - 1; | ||
2353 | 2376 | ||
2354 | /* Make sure it's in range */ | 2377 | return host_addr >> VTD_PAGE_SHIFT; |
2355 | end = min_t(u64, DOMAIN_MAX_ADDR(domain->gaw), end); | ||
2356 | if (!size || (IOVA_START_ADDR + size > end)) | ||
2357 | return NULL; | ||
2358 | |||
2359 | piova = alloc_iova(&domain->iovad, | ||
2360 | size >> PAGE_SHIFT, IOVA_PFN(end), 1); | ||
2361 | return piova; | ||
2362 | } | 2378 | } |
2363 | 2379 | ||
2364 | static struct iova * | 2380 | static struct iova *intel_alloc_iova(struct device *dev, |
2365 | __intel_alloc_iova(struct device *dev, struct dmar_domain *domain, | 2381 | struct dmar_domain *domain, |
2366 | size_t size, u64 dma_mask) | 2382 | unsigned long nrpages, uint64_t dma_mask) |
2367 | { | 2383 | { |
2368 | struct pci_dev *pdev = to_pci_dev(dev); | 2384 | struct pci_dev *pdev = to_pci_dev(dev); |
2369 | struct iova *iova = NULL; | 2385 | struct iova *iova = NULL; |
2370 | 2386 | ||
2371 | if (dma_mask <= DMA_BIT_MASK(32) || dmar_forcedac) | 2387 | /* Restrict dma_mask to the width that the iommu can handle */ |
2372 | iova = iommu_alloc_iova(domain, size, dma_mask); | 2388 | dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask); |
2373 | else { | 2389 | |
2390 | if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) { | ||
2374 | /* | 2391 | /* |
2375 | * First try to allocate an io virtual address in | 2392 | * First try to allocate an io virtual address in |
2376 | * DMA_BIT_MASK(32) and if that fails then try allocating | 2393 | * DMA_BIT_MASK(32) and if that fails then try allocating |
2377 | * from higher range | 2394 | * from higher range |
2378 | */ | 2395 | */ |
2379 | iova = iommu_alloc_iova(domain, size, DMA_BIT_MASK(32)); | 2396 | iova = alloc_iova(&domain->iovad, nrpages, |
2380 | if (!iova) | 2397 | IOVA_PFN(DMA_BIT_MASK(32)), 1); |
2381 | iova = iommu_alloc_iova(domain, size, dma_mask); | 2398 | if (iova) |
2382 | } | 2399 | return iova; |
2383 | 2400 | } | |
2384 | if (!iova) { | 2401 | iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1); |
2385 | printk(KERN_ERR"Allocating iova for %s failed", pci_name(pdev)); | 2402 | if (unlikely(!iova)) { |
2403 | printk(KERN_ERR "Allocating %ld-page iova for %s failed", | ||
2404 | nrpages, pci_name(pdev)); | ||
2386 | return NULL; | 2405 | return NULL; |
2387 | } | 2406 | } |
2388 | 2407 | ||
@@ -2485,14 +2504,12 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | |||
2485 | return 0; | 2504 | return 0; |
2486 | 2505 | ||
2487 | iommu = domain_get_iommu(domain); | 2506 | iommu = domain_get_iommu(domain); |
2488 | size = aligned_size((u64)paddr, size); | 2507 | size = aligned_nrpages(paddr, size); |
2489 | 2508 | ||
2490 | iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); | 2509 | iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); |
2491 | if (!iova) | 2510 | if (!iova) |
2492 | goto error; | 2511 | goto error; |
2493 | 2512 | ||
2494 | start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; | ||
2495 | |||
2496 | /* | 2513 | /* |
2497 | * Check if DMAR supports zero-length reads on write only | 2514 | * Check if DMAR supports zero-length reads on write only |
2498 | * mappings.. | 2515 | * mappings.. |
@@ -2508,20 +2525,20 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | |||
2508 | * might have two guest_addr mapping to the same host paddr, but this | 2525 | * might have two guest_addr mapping to the same host paddr, but this |
2509 | * is not a big problem | 2526 | * is not a big problem |
2510 | */ | 2527 | */ |
2511 | ret = domain_page_mapping(domain, start_paddr, | 2528 | ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo), |
2512 | ((u64)paddr) & PHYSICAL_PAGE_MASK, | 2529 | paddr >> VTD_PAGE_SHIFT, size, prot); |
2513 | size, prot); | ||
2514 | if (ret) | 2530 | if (ret) |
2515 | goto error; | 2531 | goto error; |
2516 | 2532 | ||
2517 | /* it's a non-present to present mapping. Only flush if caching mode */ | 2533 | /* it's a non-present to present mapping. Only flush if caching mode */ |
2518 | if (cap_caching_mode(iommu->cap)) | 2534 | if (cap_caching_mode(iommu->cap)) |
2519 | iommu_flush_iotlb_psi(iommu, 0, start_paddr, | 2535 | iommu_flush_iotlb_psi(iommu, 0, mm_to_dma_pfn(iova->pfn_lo), size); |
2520 | size >> VTD_PAGE_SHIFT); | ||
2521 | else | 2536 | else |
2522 | iommu_flush_write_buffer(iommu); | 2537 | iommu_flush_write_buffer(iommu); |
2523 | 2538 | ||
2524 | return start_paddr + ((u64)paddr & (~PAGE_MASK)); | 2539 | start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; |
2540 | start_paddr += paddr & ~PAGE_MASK; | ||
2541 | return start_paddr; | ||
2525 | 2542 | ||
2526 | error: | 2543 | error: |
2527 | if (iova) | 2544 | if (iova) |
@@ -2614,7 +2631,7 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, | |||
2614 | { | 2631 | { |
2615 | struct pci_dev *pdev = to_pci_dev(dev); | 2632 | struct pci_dev *pdev = to_pci_dev(dev); |
2616 | struct dmar_domain *domain; | 2633 | struct dmar_domain *domain; |
2617 | unsigned long start_addr; | 2634 | unsigned long start_pfn, last_pfn; |
2618 | struct iova *iova; | 2635 | struct iova *iova; |
2619 | struct intel_iommu *iommu; | 2636 | struct intel_iommu *iommu; |
2620 | 2637 | ||
@@ -2627,22 +2644,25 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, | |||
2627 | iommu = domain_get_iommu(domain); | 2644 | iommu = domain_get_iommu(domain); |
2628 | 2645 | ||
2629 | iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr)); | 2646 | iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr)); |
2630 | if (!iova) | 2647 | if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n", |
2648 | (unsigned long long)dev_addr)) | ||
2631 | return; | 2649 | return; |
2632 | 2650 | ||
2633 | start_addr = iova->pfn_lo << PAGE_SHIFT; | 2651 | start_pfn = mm_to_dma_pfn(iova->pfn_lo); |
2634 | size = aligned_size((u64)dev_addr, size); | 2652 | last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1; |
2635 | 2653 | ||
2636 | pr_debug("Device %s unmapping: %zx@%llx\n", | 2654 | pr_debug("Device %s unmapping: pfn %lx-%lx\n", |
2637 | pci_name(pdev), size, (unsigned long long)start_addr); | 2655 | pci_name(pdev), start_pfn, last_pfn); |
2638 | 2656 | ||
2639 | /* clear the whole page */ | 2657 | /* clear the whole page */ |
2640 | dma_pte_clear_range(domain, start_addr, start_addr + size); | 2658 | dma_pte_clear_range(domain, start_pfn, last_pfn); |
2659 | |||
2641 | /* free page tables */ | 2660 | /* free page tables */ |
2642 | dma_pte_free_pagetable(domain, start_addr, start_addr + size); | 2661 | dma_pte_free_pagetable(domain, start_pfn, last_pfn); |
2662 | |||
2643 | if (intel_iommu_strict) { | 2663 | if (intel_iommu_strict) { |
2644 | iommu_flush_iotlb_psi(iommu, domain->id, start_addr, | 2664 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, |
2645 | size >> VTD_PAGE_SHIFT); | 2665 | last_pfn - start_pfn + 1); |
2646 | /* free iova */ | 2666 | /* free iova */ |
2647 | __free_iova(&domain->iovad, iova); | 2667 | __free_iova(&domain->iovad, iova); |
2648 | } else { | 2668 | } else { |
@@ -2700,14 +2720,10 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, | |||
2700 | int nelems, enum dma_data_direction dir, | 2720 | int nelems, enum dma_data_direction dir, |
2701 | struct dma_attrs *attrs) | 2721 | struct dma_attrs *attrs) |
2702 | { | 2722 | { |
2703 | int i; | ||
2704 | struct pci_dev *pdev = to_pci_dev(hwdev); | 2723 | struct pci_dev *pdev = to_pci_dev(hwdev); |
2705 | struct dmar_domain *domain; | 2724 | struct dmar_domain *domain; |
2706 | unsigned long start_addr; | 2725 | unsigned long start_pfn, last_pfn; |
2707 | struct iova *iova; | 2726 | struct iova *iova; |
2708 | size_t size = 0; | ||
2709 | phys_addr_t addr; | ||
2710 | struct scatterlist *sg; | ||
2711 | struct intel_iommu *iommu; | 2727 | struct intel_iommu *iommu; |
2712 | 2728 | ||
2713 | if (iommu_no_mapping(pdev)) | 2729 | if (iommu_no_mapping(pdev)) |
@@ -2719,22 +2735,21 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, | |||
2719 | iommu = domain_get_iommu(domain); | 2735 | iommu = domain_get_iommu(domain); |
2720 | 2736 | ||
2721 | iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address)); | 2737 | iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address)); |
2722 | if (!iova) | 2738 | if (WARN_ONCE(!iova, "Driver unmaps unmatched sglist at PFN %llx\n", |
2739 | (unsigned long long)sglist[0].dma_address)) | ||
2723 | return; | 2740 | return; |
2724 | for_each_sg(sglist, sg, nelems, i) { | ||
2725 | addr = page_to_phys(sg_page(sg)) + sg->offset; | ||
2726 | size += aligned_size((u64)addr, sg->length); | ||
2727 | } | ||
2728 | 2741 | ||
2729 | start_addr = iova->pfn_lo << PAGE_SHIFT; | 2742 | start_pfn = mm_to_dma_pfn(iova->pfn_lo); |
2743 | last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1; | ||
2730 | 2744 | ||
2731 | /* clear the whole page */ | 2745 | /* clear the whole page */ |
2732 | dma_pte_clear_range(domain, start_addr, start_addr + size); | 2746 | dma_pte_clear_range(domain, start_pfn, last_pfn); |
2747 | |||
2733 | /* free page tables */ | 2748 | /* free page tables */ |
2734 | dma_pte_free_pagetable(domain, start_addr, start_addr + size); | 2749 | dma_pte_free_pagetable(domain, start_pfn, last_pfn); |
2735 | 2750 | ||
2736 | iommu_flush_iotlb_psi(iommu, domain->id, start_addr, | 2751 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, |
2737 | size >> VTD_PAGE_SHIFT); | 2752 | (last_pfn - start_pfn + 1)); |
2738 | 2753 | ||
2739 | /* free iova */ | 2754 | /* free iova */ |
2740 | __free_iova(&domain->iovad, iova); | 2755 | __free_iova(&domain->iovad, iova); |
@@ -2757,17 +2772,16 @@ static int intel_nontranslate_map_sg(struct device *hddev, | |||
2757 | static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems, | 2772 | static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems, |
2758 | enum dma_data_direction dir, struct dma_attrs *attrs) | 2773 | enum dma_data_direction dir, struct dma_attrs *attrs) |
2759 | { | 2774 | { |
2760 | phys_addr_t addr; | ||
2761 | int i; | 2775 | int i; |
2762 | struct pci_dev *pdev = to_pci_dev(hwdev); | 2776 | struct pci_dev *pdev = to_pci_dev(hwdev); |
2763 | struct dmar_domain *domain; | 2777 | struct dmar_domain *domain; |
2764 | size_t size = 0; | 2778 | size_t size = 0; |
2765 | int prot = 0; | 2779 | int prot = 0; |
2766 | size_t offset = 0; | 2780 | size_t offset_pfn = 0; |
2767 | struct iova *iova = NULL; | 2781 | struct iova *iova = NULL; |
2768 | int ret; | 2782 | int ret; |
2769 | struct scatterlist *sg; | 2783 | struct scatterlist *sg; |
2770 | unsigned long start_addr; | 2784 | unsigned long start_vpfn; |
2771 | struct intel_iommu *iommu; | 2785 | struct intel_iommu *iommu; |
2772 | 2786 | ||
2773 | BUG_ON(dir == DMA_NONE); | 2787 | BUG_ON(dir == DMA_NONE); |
@@ -2780,12 +2794,10 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne | |||
2780 | 2794 | ||
2781 | iommu = domain_get_iommu(domain); | 2795 | iommu = domain_get_iommu(domain); |
2782 | 2796 | ||
2783 | for_each_sg(sglist, sg, nelems, i) { | 2797 | for_each_sg(sglist, sg, nelems, i) |
2784 | addr = page_to_phys(sg_page(sg)) + sg->offset; | 2798 | size += aligned_nrpages(sg->offset, sg->length); |
2785 | size += aligned_size((u64)addr, sg->length); | ||
2786 | } | ||
2787 | 2799 | ||
2788 | iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); | 2800 | iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); |
2789 | if (!iova) { | 2801 | if (!iova) { |
2790 | sglist->dma_length = 0; | 2802 | sglist->dma_length = 0; |
2791 | return 0; | 2803 | return 0; |
@@ -2801,35 +2813,24 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne | |||
2801 | if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) | 2813 | if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) |
2802 | prot |= DMA_PTE_WRITE; | 2814 | prot |= DMA_PTE_WRITE; |
2803 | 2815 | ||
2804 | start_addr = iova->pfn_lo << PAGE_SHIFT; | 2816 | start_vpfn = mm_to_dma_pfn(iova->pfn_lo); |
2805 | offset = 0; | 2817 | |
2806 | for_each_sg(sglist, sg, nelems, i) { | 2818 | ret = domain_sg_mapping(domain, start_vpfn, sglist, mm_to_dma_pfn(size), prot); |
2807 | addr = page_to_phys(sg_page(sg)) + sg->offset; | 2819 | if (unlikely(ret)) { |
2808 | size = aligned_size((u64)addr, sg->length); | 2820 | /* clear the page */ |
2809 | ret = domain_page_mapping(domain, start_addr + offset, | 2821 | dma_pte_clear_range(domain, start_vpfn, |
2810 | ((u64)addr) & PHYSICAL_PAGE_MASK, | 2822 | start_vpfn + size - 1); |
2811 | size, prot); | 2823 | /* free page tables */ |
2812 | if (ret) { | 2824 | dma_pte_free_pagetable(domain, start_vpfn, |
2813 | /* clear the page */ | 2825 | start_vpfn + size - 1); |
2814 | dma_pte_clear_range(domain, start_addr, | 2826 | /* free iova */ |
2815 | start_addr + offset); | 2827 | __free_iova(&domain->iovad, iova); |
2816 | /* free page tables */ | 2828 | return 0; |
2817 | dma_pte_free_pagetable(domain, start_addr, | ||
2818 | start_addr + offset); | ||
2819 | /* free iova */ | ||
2820 | __free_iova(&domain->iovad, iova); | ||
2821 | return 0; | ||
2822 | } | ||
2823 | sg->dma_address = start_addr + offset + | ||
2824 | ((u64)addr & (~PAGE_MASK)); | ||
2825 | sg->dma_length = sg->length; | ||
2826 | offset += size; | ||
2827 | } | 2829 | } |
2828 | 2830 | ||
2829 | /* it's a non-present to present mapping. Only flush if caching mode */ | 2831 | /* it's a non-present to present mapping. Only flush if caching mode */ |
2830 | if (cap_caching_mode(iommu->cap)) | 2832 | if (cap_caching_mode(iommu->cap)) |
2831 | iommu_flush_iotlb_psi(iommu, 0, start_addr, | 2833 | iommu_flush_iotlb_psi(iommu, 0, start_vpfn, offset_pfn); |
2832 | offset >> VTD_PAGE_SHIFT); | ||
2833 | else | 2834 | else |
2834 | iommu_flush_write_buffer(iommu); | 2835 | iommu_flush_write_buffer(iommu); |
2835 | 2836 | ||
@@ -3334,7 +3335,6 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width) | |||
3334 | int adjust_width; | 3335 | int adjust_width; |
3335 | 3336 | ||
3336 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); | 3337 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); |
3337 | spin_lock_init(&domain->mapping_lock); | ||
3338 | spin_lock_init(&domain->iommu_lock); | 3338 | spin_lock_init(&domain->iommu_lock); |
3339 | 3339 | ||
3340 | domain_reserve_special_ranges(domain); | 3340 | domain_reserve_special_ranges(domain); |
@@ -3388,8 +3388,6 @@ static void iommu_free_vm_domain(struct dmar_domain *domain) | |||
3388 | 3388 | ||
3389 | static void vm_domain_exit(struct dmar_domain *domain) | 3389 | static void vm_domain_exit(struct dmar_domain *domain) |
3390 | { | 3390 | { |
3391 | u64 end; | ||
3392 | |||
3393 | /* Domain 0 is reserved, so dont process it */ | 3391 | /* Domain 0 is reserved, so dont process it */ |
3394 | if (!domain) | 3392 | if (!domain) |
3395 | return; | 3393 | return; |
@@ -3397,14 +3395,12 @@ static void vm_domain_exit(struct dmar_domain *domain) | |||
3397 | vm_domain_remove_all_dev_info(domain); | 3395 | vm_domain_remove_all_dev_info(domain); |
3398 | /* destroy iovas */ | 3396 | /* destroy iovas */ |
3399 | put_iova_domain(&domain->iovad); | 3397 | put_iova_domain(&domain->iovad); |
3400 | end = DOMAIN_MAX_ADDR(domain->gaw); | ||
3401 | end = end & (~VTD_PAGE_MASK); | ||
3402 | 3398 | ||
3403 | /* clear ptes */ | 3399 | /* clear ptes */ |
3404 | dma_pte_clear_range(domain, 0, end); | 3400 | dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
3405 | 3401 | ||
3406 | /* free page tables */ | 3402 | /* free page tables */ |
3407 | dma_pte_free_pagetable(domain, 0, end); | 3403 | dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
3408 | 3404 | ||
3409 | iommu_free_vm_domain(domain); | 3405 | iommu_free_vm_domain(domain); |
3410 | free_domain_mem(domain); | 3406 | free_domain_mem(domain); |
@@ -3513,7 +3509,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
3513 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) | 3509 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) |
3514 | prot |= DMA_PTE_SNP; | 3510 | prot |= DMA_PTE_SNP; |
3515 | 3511 | ||
3516 | max_addr = (iova & VTD_PAGE_MASK) + VTD_PAGE_ALIGN(size); | 3512 | max_addr = iova + size; |
3517 | if (dmar_domain->max_addr < max_addr) { | 3513 | if (dmar_domain->max_addr < max_addr) { |
3518 | int min_agaw; | 3514 | int min_agaw; |
3519 | u64 end; | 3515 | u64 end; |
@@ -3531,8 +3527,11 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
3531 | } | 3527 | } |
3532 | dmar_domain->max_addr = max_addr; | 3528 | dmar_domain->max_addr = max_addr; |
3533 | } | 3529 | } |
3534 | 3530 | /* Round up size to next multiple of PAGE_SIZE, if it and | |
3535 | ret = domain_page_mapping(dmar_domain, iova, hpa, size, prot); | 3531 | the low bits of hpa would take us onto the next page */ |
3532 | size = aligned_nrpages(hpa, size); | ||
3533 | ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT, | ||
3534 | hpa >> VTD_PAGE_SHIFT, size, prot); | ||
3536 | return ret; | 3535 | return ret; |
3537 | } | 3536 | } |
3538 | 3537 | ||
@@ -3540,15 +3539,12 @@ static void intel_iommu_unmap_range(struct iommu_domain *domain, | |||
3540 | unsigned long iova, size_t size) | 3539 | unsigned long iova, size_t size) |
3541 | { | 3540 | { |
3542 | struct dmar_domain *dmar_domain = domain->priv; | 3541 | struct dmar_domain *dmar_domain = domain->priv; |
3543 | dma_addr_t base; | ||
3544 | 3542 | ||
3545 | /* The address might not be aligned */ | 3543 | dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, |
3546 | base = iova & VTD_PAGE_MASK; | 3544 | (iova + size - 1) >> VTD_PAGE_SHIFT); |
3547 | size = VTD_PAGE_ALIGN(size); | ||
3548 | dma_pte_clear_range(dmar_domain, base, base + size); | ||
3549 | 3545 | ||
3550 | if (dmar_domain->max_addr == base + size) | 3546 | if (dmar_domain->max_addr == iova + size) |
3551 | dmar_domain->max_addr = base; | 3547 | dmar_domain->max_addr = iova; |
3552 | } | 3548 | } |
3553 | 3549 | ||
3554 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, | 3550 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, |
@@ -3558,7 +3554,7 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, | |||
3558 | struct dma_pte *pte; | 3554 | struct dma_pte *pte; |
3559 | u64 phys = 0; | 3555 | u64 phys = 0; |
3560 | 3556 | ||
3561 | pte = addr_to_dma_pte(dmar_domain, iova); | 3557 | pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT); |
3562 | if (pte) | 3558 | if (pte) |
3563 | phys = dma_pte_addr(pte); | 3559 | phys = dma_pte_addr(pte); |
3564 | 3560 | ||
diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c index 2287116e9822..46dd440e2315 100644 --- a/drivers/pci/iova.c +++ b/drivers/pci/iova.c | |||
@@ -1,9 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006, Intel Corporation. | 2 | * Copyright © 2006-2009, Intel Corporation. |
3 | * | 3 | * |
4 | * This file is released under the GPLv2. | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along with | ||
14 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
15 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
5 | * | 16 | * |
6 | * Copyright (C) 2006-2008 Intel Corporation | ||
7 | * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> | 17 | * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> |
8 | */ | 18 | */ |
9 | 19 | ||
@@ -123,7 +133,15 @@ move_left: | |||
123 | /* Insert the new_iova into domain rbtree by holding writer lock */ | 133 | /* Insert the new_iova into domain rbtree by holding writer lock */ |
124 | /* Add new node and rebalance tree. */ | 134 | /* Add new node and rebalance tree. */ |
125 | { | 135 | { |
126 | struct rb_node **entry = &((prev)), *parent = NULL; | 136 | struct rb_node **entry, *parent = NULL; |
137 | |||
138 | /* If we have 'prev', it's a valid place to start the | ||
139 | insertion. Otherwise, start from the root. */ | ||
140 | if (prev) | ||
141 | entry = &prev; | ||
142 | else | ||
143 | entry = &iovad->rbroot.rb_node; | ||
144 | |||
127 | /* Figure out where to put new node */ | 145 | /* Figure out where to put new node */ |
128 | while (*entry) { | 146 | while (*entry) { |
129 | struct iova *this = container_of(*entry, | 147 | struct iova *this = container_of(*entry, |
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index 659421d0ca46..d4ad50d737b0 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services. | 2 | * vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services. |
3 | * | 3 | * |
4 | * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -32,7 +32,7 @@ | |||
32 | #include "i82365.h" | 32 | #include "i82365.h" |
33 | 33 | ||
34 | MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services"); | 34 | MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services"); |
35 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 35 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
37 | 37 | ||
38 | #define CARD_MAX_SLOTS 2 | 38 | #define CARD_MAX_SLOTS 2 |
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c index 812f038e9bda..9b3c15827e5c 100644 --- a/drivers/pcmcia/vrc4173_cardu.c +++ b/drivers/pcmcia/vrc4173_cardu.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * NEC VRC4173 CARDU driver for Socket Services | 6 | * NEC VRC4173 CARDU driver for Socket Services |
7 | * (This device doesn't support CardBus. it is supporting only 16bit PC Card.) | 7 | * (This device doesn't support CardBus. it is supporting only 16bit PC Card.) |
8 | * | 8 | * |
9 | * Copyright 2002,2003 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 9 | * Copyright 2002,2003 Yoichi Yuasa <yuasa@linux-mips.org> |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify it | 11 | * This program is free software; you can redistribute it and/or modify it |
12 | * under the terms of the GNU General Public License as published by the | 12 | * under the terms of the GNU General Public License as published by the |
@@ -41,7 +41,7 @@ | |||
41 | #include "vrc4173_cardu.h" | 41 | #include "vrc4173_cardu.h" |
42 | 42 | ||
43 | MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services"); | 43 | MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services"); |
44 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 44 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
45 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
46 | 46 | ||
47 | static int vrc4173_cardu_slots; | 47 | static int vrc4173_cardu_slots; |
diff --git a/drivers/pcmcia/vrc4173_cardu.h b/drivers/pcmcia/vrc4173_cardu.h index 7d77c74120c1..a7d96018ed8d 100644 --- a/drivers/pcmcia/vrc4173_cardu.h +++ b/drivers/pcmcia/vrc4173_cardu.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * BRIEF MODULE DESCRIPTION | 5 | * BRIEF MODULE DESCRIPTION |
6 | * Include file for NEC VRC4173 CARDU. | 6 | * Include file for NEC VRC4173 CARDU. |
7 | * | 7 | * |
8 | * Copyright 2002 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 8 | * Copyright 2002 Yoichi Yuasa <yuasa@linux-mips.org> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
11 | * under the terms of the GNU General Public License as published by the | 11 | * under the terms of the GNU General Public License as published by the |
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 7232fe7104aa..46dad12f952f 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -355,6 +355,7 @@ config EEEPC_LAPTOP | |||
355 | depends on INPUT | 355 | depends on INPUT |
356 | depends on EXPERIMENTAL | 356 | depends on EXPERIMENTAL |
357 | depends on RFKILL || RFKILL = n | 357 | depends on RFKILL || RFKILL = n |
358 | depends on HOTPLUG_PCI | ||
358 | select BACKLIGHT_CLASS_DEVICE | 359 | select BACKLIGHT_CLASS_DEVICE |
359 | select HWMON | 360 | select HWMON |
360 | ---help--- | 361 | ---help--- |
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 4207b26ff990..ec560f16d720 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
@@ -16,6 +16,8 @@ | |||
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
20 | |||
19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
20 | #include <linux/module.h> | 22 | #include <linux/module.h> |
21 | #include <linux/init.h> | 23 | #include <linux/init.h> |
@@ -31,6 +33,7 @@ | |||
31 | #include <linux/input.h> | 33 | #include <linux/input.h> |
32 | #include <linux/rfkill.h> | 34 | #include <linux/rfkill.h> |
33 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/pci_hotplug.h> | ||
34 | 37 | ||
35 | #define EEEPC_LAPTOP_VERSION "0.1" | 38 | #define EEEPC_LAPTOP_VERSION "0.1" |
36 | 39 | ||
@@ -40,11 +43,6 @@ | |||
40 | #define EEEPC_HOTK_DEVICE_NAME "Hotkey" | 43 | #define EEEPC_HOTK_DEVICE_NAME "Hotkey" |
41 | #define EEEPC_HOTK_HID "ASUS010" | 44 | #define EEEPC_HOTK_HID "ASUS010" |
42 | 45 | ||
43 | #define EEEPC_LOG EEEPC_HOTK_FILE ": " | ||
44 | #define EEEPC_ERR KERN_ERR EEEPC_LOG | ||
45 | #define EEEPC_WARNING KERN_WARNING EEEPC_LOG | ||
46 | #define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG | ||
47 | #define EEEPC_INFO KERN_INFO EEEPC_LOG | ||
48 | 46 | ||
49 | /* | 47 | /* |
50 | * Definitions for Asus EeePC | 48 | * Definitions for Asus EeePC |
@@ -141,8 +139,10 @@ struct eeepc_hotk { | |||
141 | u16 event_count[128]; /* count for each event */ | 139 | u16 event_count[128]; /* count for each event */ |
142 | struct input_dev *inputdev; | 140 | struct input_dev *inputdev; |
143 | u16 *keycode_map; | 141 | u16 *keycode_map; |
144 | struct rfkill *eeepc_wlan_rfkill; | 142 | struct rfkill *wlan_rfkill; |
145 | struct rfkill *eeepc_bluetooth_rfkill; | 143 | struct rfkill *bluetooth_rfkill; |
144 | struct rfkill *wwan3g_rfkill; | ||
145 | struct hotplug_slot *hotplug_slot; | ||
146 | }; | 146 | }; |
147 | 147 | ||
148 | /* The actual device the driver binds to */ | 148 | /* The actual device the driver binds to */ |
@@ -213,6 +213,15 @@ static struct acpi_driver eeepc_hotk_driver = { | |||
213 | }, | 213 | }, |
214 | }; | 214 | }; |
215 | 215 | ||
216 | /* PCI hotplug ops */ | ||
217 | static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value); | ||
218 | |||
219 | static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { | ||
220 | .owner = THIS_MODULE, | ||
221 | .get_adapter_status = eeepc_get_adapter_status, | ||
222 | .get_power_status = eeepc_get_adapter_status, | ||
223 | }; | ||
224 | |||
216 | /* The backlight device /sys/class/backlight */ | 225 | /* The backlight device /sys/class/backlight */ |
217 | static struct backlight_device *eeepc_backlight_device; | 226 | static struct backlight_device *eeepc_backlight_device; |
218 | 227 | ||
@@ -274,20 +283,20 @@ static int set_acpi(int cm, int value) | |||
274 | if (method == NULL) | 283 | if (method == NULL) |
275 | return -ENODEV; | 284 | return -ENODEV; |
276 | if (write_acpi_int(ehotk->handle, method, value, NULL)) | 285 | if (write_acpi_int(ehotk->handle, method, value, NULL)) |
277 | printk(EEEPC_WARNING "Error writing %s\n", method); | 286 | pr_warning("Error writing %s\n", method); |
278 | } | 287 | } |
279 | return 0; | 288 | return 0; |
280 | } | 289 | } |
281 | 290 | ||
282 | static int get_acpi(int cm) | 291 | static int get_acpi(int cm) |
283 | { | 292 | { |
284 | int value = -1; | 293 | int value = -ENODEV; |
285 | if ((ehotk->cm_supported & (0x1 << cm))) { | 294 | if ((ehotk->cm_supported & (0x1 << cm))) { |
286 | const char *method = cm_getv[cm]; | 295 | const char *method = cm_getv[cm]; |
287 | if (method == NULL) | 296 | if (method == NULL) |
288 | return -ENODEV; | 297 | return -ENODEV; |
289 | if (read_acpi_int(ehotk->handle, method, &value)) | 298 | if (read_acpi_int(ehotk->handle, method, &value)) |
290 | printk(EEEPC_WARNING "Error reading %s\n", method); | 299 | pr_warning("Error reading %s\n", method); |
291 | } | 300 | } |
292 | return value; | 301 | return value; |
293 | } | 302 | } |
@@ -359,13 +368,19 @@ static ssize_t store_sys_acpi(int cm, const char *buf, size_t count) | |||
359 | 368 | ||
360 | rv = parse_arg(buf, count, &value); | 369 | rv = parse_arg(buf, count, &value); |
361 | if (rv > 0) | 370 | if (rv > 0) |
362 | set_acpi(cm, value); | 371 | value = set_acpi(cm, value); |
372 | if (value < 0) | ||
373 | return value; | ||
363 | return rv; | 374 | return rv; |
364 | } | 375 | } |
365 | 376 | ||
366 | static ssize_t show_sys_acpi(int cm, char *buf) | 377 | static ssize_t show_sys_acpi(int cm, char *buf) |
367 | { | 378 | { |
368 | return sprintf(buf, "%d\n", get_acpi(cm)); | 379 | int value = get_acpi(cm); |
380 | |||
381 | if (value < 0) | ||
382 | return value; | ||
383 | return sprintf(buf, "%d\n", value); | ||
369 | } | 384 | } |
370 | 385 | ||
371 | #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ | 386 | #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ |
@@ -539,6 +554,28 @@ static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) | |||
539 | return -EINVAL; | 554 | return -EINVAL; |
540 | } | 555 | } |
541 | 556 | ||
557 | static void cmsg_quirk(int cm, const char *name) | ||
558 | { | ||
559 | int dummy; | ||
560 | |||
561 | /* Some BIOSes do not report cm although it is avaliable. | ||
562 | Check if cm_getv[cm] works and, if yes, assume cm should be set. */ | ||
563 | if (!(ehotk->cm_supported & (1 << cm)) | ||
564 | && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) { | ||
565 | pr_info("%s (%x) not reported by BIOS," | ||
566 | " enabling anyway\n", name, 1 << cm); | ||
567 | ehotk->cm_supported |= 1 << cm; | ||
568 | } | ||
569 | } | ||
570 | |||
571 | static void cmsg_quirks(void) | ||
572 | { | ||
573 | cmsg_quirk(CM_ASL_LID, "LID"); | ||
574 | cmsg_quirk(CM_ASL_TYPE, "TYPE"); | ||
575 | cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER"); | ||
576 | cmsg_quirk(CM_ASL_TPD, "TPD"); | ||
577 | } | ||
578 | |||
542 | static int eeepc_hotk_check(void) | 579 | static int eeepc_hotk_check(void) |
543 | { | 580 | { |
544 | const struct key_entry *key; | 581 | const struct key_entry *key; |
@@ -551,26 +588,24 @@ static int eeepc_hotk_check(void) | |||
551 | if (ehotk->device->status.present) { | 588 | if (ehotk->device->status.present) { |
552 | if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, | 589 | if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, |
553 | &buffer)) { | 590 | &buffer)) { |
554 | printk(EEEPC_ERR "Hotkey initialization failed\n"); | 591 | pr_err("Hotkey initialization failed\n"); |
555 | return -ENODEV; | 592 | return -ENODEV; |
556 | } else { | 593 | } else { |
557 | printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n", | 594 | pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag); |
558 | ehotk->init_flag); | ||
559 | } | 595 | } |
560 | /* get control methods supported */ | 596 | /* get control methods supported */ |
561 | if (read_acpi_int(ehotk->handle, "CMSG" | 597 | if (read_acpi_int(ehotk->handle, "CMSG" |
562 | , &ehotk->cm_supported)) { | 598 | , &ehotk->cm_supported)) { |
563 | printk(EEEPC_ERR | 599 | pr_err("Get control methods supported failed\n"); |
564 | "Get control methods supported failed\n"); | ||
565 | return -ENODEV; | 600 | return -ENODEV; |
566 | } else { | 601 | } else { |
567 | printk(EEEPC_INFO | 602 | cmsg_quirks(); |
568 | "Get control methods supported: 0x%x\n", | 603 | pr_info("Get control methods supported: 0x%x\n", |
569 | ehotk->cm_supported); | 604 | ehotk->cm_supported); |
570 | } | 605 | } |
571 | ehotk->inputdev = input_allocate_device(); | 606 | ehotk->inputdev = input_allocate_device(); |
572 | if (!ehotk->inputdev) { | 607 | if (!ehotk->inputdev) { |
573 | printk(EEEPC_INFO "Unable to allocate input device\n"); | 608 | pr_info("Unable to allocate input device\n"); |
574 | return 0; | 609 | return 0; |
575 | } | 610 | } |
576 | ehotk->inputdev->name = "Asus EeePC extra buttons"; | 611 | ehotk->inputdev->name = "Asus EeePC extra buttons"; |
@@ -589,12 +624,12 @@ static int eeepc_hotk_check(void) | |||
589 | } | 624 | } |
590 | result = input_register_device(ehotk->inputdev); | 625 | result = input_register_device(ehotk->inputdev); |
591 | if (result) { | 626 | if (result) { |
592 | printk(EEEPC_INFO "Unable to register input device\n"); | 627 | pr_info("Unable to register input device\n"); |
593 | input_free_device(ehotk->inputdev); | 628 | input_free_device(ehotk->inputdev); |
594 | return 0; | 629 | return 0; |
595 | } | 630 | } |
596 | } else { | 631 | } else { |
597 | printk(EEEPC_ERR "Hotkey device not present, aborting\n"); | 632 | pr_err("Hotkey device not present, aborting\n"); |
598 | return -EINVAL; | 633 | return -EINVAL; |
599 | } | 634 | } |
600 | return 0; | 635 | return 0; |
@@ -612,6 +647,19 @@ static int notify_brn(void) | |||
612 | return -1; | 647 | return -1; |
613 | } | 648 | } |
614 | 649 | ||
650 | static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot, | ||
651 | u8 *value) | ||
652 | { | ||
653 | int val = get_acpi(CM_ASL_WLAN); | ||
654 | |||
655 | if (val == 1 || val == 0) | ||
656 | *value = val; | ||
657 | else | ||
658 | return -EINVAL; | ||
659 | |||
660 | return 0; | ||
661 | } | ||
662 | |||
615 | static void eeepc_rfkill_hotplug(void) | 663 | static void eeepc_rfkill_hotplug(void) |
616 | { | 664 | { |
617 | struct pci_dev *dev; | 665 | struct pci_dev *dev; |
@@ -619,7 +667,7 @@ static void eeepc_rfkill_hotplug(void) | |||
619 | bool blocked; | 667 | bool blocked; |
620 | 668 | ||
621 | if (!bus) { | 669 | if (!bus) { |
622 | printk(EEEPC_WARNING "Unable to find PCI bus 1?\n"); | 670 | pr_warning("Unable to find PCI bus 1?\n"); |
623 | return; | 671 | return; |
624 | } | 672 | } |
625 | 673 | ||
@@ -635,7 +683,7 @@ static void eeepc_rfkill_hotplug(void) | |||
635 | if (dev) { | 683 | if (dev) { |
636 | pci_bus_assign_resources(bus); | 684 | pci_bus_assign_resources(bus); |
637 | if (pci_bus_add_device(dev)) | 685 | if (pci_bus_add_device(dev)) |
638 | printk(EEEPC_ERR "Unable to hotplug wifi\n"); | 686 | pr_err("Unable to hotplug wifi\n"); |
639 | } | 687 | } |
640 | } else { | 688 | } else { |
641 | dev = pci_get_slot(bus, 0); | 689 | dev = pci_get_slot(bus, 0); |
@@ -645,7 +693,7 @@ static void eeepc_rfkill_hotplug(void) | |||
645 | } | 693 | } |
646 | } | 694 | } |
647 | 695 | ||
648 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked); | 696 | rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); |
649 | } | 697 | } |
650 | 698 | ||
651 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | 699 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) |
@@ -718,8 +766,7 @@ static int eeepc_register_rfkill_notifier(char *node) | |||
718 | eeepc_rfkill_notify, | 766 | eeepc_rfkill_notify, |
719 | NULL); | 767 | NULL); |
720 | if (ACPI_FAILURE(status)) | 768 | if (ACPI_FAILURE(status)) |
721 | printk(EEEPC_WARNING | 769 | pr_warning("Failed to register notify on %s\n", node); |
722 | "Failed to register notify on %s\n", node); | ||
723 | } else | 770 | } else |
724 | return -ENODEV; | 771 | return -ENODEV; |
725 | 772 | ||
@@ -738,19 +785,66 @@ static void eeepc_unregister_rfkill_notifier(char *node) | |||
738 | ACPI_SYSTEM_NOTIFY, | 785 | ACPI_SYSTEM_NOTIFY, |
739 | eeepc_rfkill_notify); | 786 | eeepc_rfkill_notify); |
740 | if (ACPI_FAILURE(status)) | 787 | if (ACPI_FAILURE(status)) |
741 | printk(EEEPC_ERR | 788 | pr_err("Error removing rfkill notify handler %s\n", |
742 | "Error removing rfkill notify handler %s\n", | ||
743 | node); | 789 | node); |
744 | } | 790 | } |
745 | } | 791 | } |
746 | 792 | ||
793 | static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) | ||
794 | { | ||
795 | kfree(hotplug_slot->info); | ||
796 | kfree(hotplug_slot); | ||
797 | } | ||
798 | |||
799 | static int eeepc_setup_pci_hotplug(void) | ||
800 | { | ||
801 | int ret = -ENOMEM; | ||
802 | struct pci_bus *bus = pci_find_bus(0, 1); | ||
803 | |||
804 | if (!bus) { | ||
805 | pr_err("Unable to find wifi PCI bus\n"); | ||
806 | return -ENODEV; | ||
807 | } | ||
808 | |||
809 | ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); | ||
810 | if (!ehotk->hotplug_slot) | ||
811 | goto error_slot; | ||
812 | |||
813 | ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), | ||
814 | GFP_KERNEL); | ||
815 | if (!ehotk->hotplug_slot->info) | ||
816 | goto error_info; | ||
817 | |||
818 | ehotk->hotplug_slot->private = ehotk; | ||
819 | ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug; | ||
820 | ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops; | ||
821 | eeepc_get_adapter_status(ehotk->hotplug_slot, | ||
822 | &ehotk->hotplug_slot->info->adapter_status); | ||
823 | |||
824 | ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi"); | ||
825 | if (ret) { | ||
826 | pr_err("Unable to register hotplug slot - %d\n", ret); | ||
827 | goto error_register; | ||
828 | } | ||
829 | |||
830 | return 0; | ||
831 | |||
832 | error_register: | ||
833 | kfree(ehotk->hotplug_slot->info); | ||
834 | error_info: | ||
835 | kfree(ehotk->hotplug_slot); | ||
836 | ehotk->hotplug_slot = NULL; | ||
837 | error_slot: | ||
838 | return ret; | ||
839 | } | ||
840 | |||
747 | static int eeepc_hotk_add(struct acpi_device *device) | 841 | static int eeepc_hotk_add(struct acpi_device *device) |
748 | { | 842 | { |
749 | int result; | 843 | int result; |
750 | 844 | ||
751 | if (!device) | 845 | if (!device) |
752 | return -EINVAL; | 846 | return -EINVAL; |
753 | printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n"); | 847 | pr_notice(EEEPC_HOTK_NAME "\n"); |
754 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); | 848 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); |
755 | if (!ehotk) | 849 | if (!ehotk) |
756 | return -ENOMEM; | 850 | return -ENOMEM; |
@@ -764,53 +858,8 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
764 | if (result) | 858 | if (result) |
765 | goto ehotk_fail; | 859 | goto ehotk_fail; |
766 | 860 | ||
767 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
768 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
769 | |||
770 | if (get_acpi(CM_ASL_WLAN) != -1) { | ||
771 | ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan", | ||
772 | &device->dev, | ||
773 | RFKILL_TYPE_WLAN, | ||
774 | &eeepc_rfkill_ops, | ||
775 | (void *)CM_ASL_WLAN); | ||
776 | |||
777 | if (!ehotk->eeepc_wlan_rfkill) | ||
778 | goto wlan_fail; | ||
779 | |||
780 | rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill, | ||
781 | get_acpi(CM_ASL_WLAN) != 1); | ||
782 | result = rfkill_register(ehotk->eeepc_wlan_rfkill); | ||
783 | if (result) | ||
784 | goto wlan_fail; | ||
785 | } | ||
786 | |||
787 | if (get_acpi(CM_ASL_BLUETOOTH) != -1) { | ||
788 | ehotk->eeepc_bluetooth_rfkill = | ||
789 | rfkill_alloc("eeepc-bluetooth", | ||
790 | &device->dev, | ||
791 | RFKILL_TYPE_BLUETOOTH, | ||
792 | &eeepc_rfkill_ops, | ||
793 | (void *)CM_ASL_BLUETOOTH); | ||
794 | |||
795 | if (!ehotk->eeepc_bluetooth_rfkill) | ||
796 | goto bluetooth_fail; | ||
797 | |||
798 | rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill, | ||
799 | get_acpi(CM_ASL_BLUETOOTH) != 1); | ||
800 | result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); | ||
801 | if (result) | ||
802 | goto bluetooth_fail; | ||
803 | } | ||
804 | |||
805 | return 0; | 861 | return 0; |
806 | 862 | ||
807 | bluetooth_fail: | ||
808 | rfkill_destroy(ehotk->eeepc_bluetooth_rfkill); | ||
809 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | ||
810 | wlan_fail: | ||
811 | rfkill_destroy(ehotk->eeepc_wlan_rfkill); | ||
812 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
813 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
814 | ehotk_fail: | 863 | ehotk_fail: |
815 | kfree(ehotk); | 864 | kfree(ehotk); |
816 | ehotk = NULL; | 865 | ehotk = NULL; |
@@ -823,16 +872,13 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) | |||
823 | if (!device || !acpi_driver_data(device)) | 872 | if (!device || !acpi_driver_data(device)) |
824 | return -EINVAL; | 873 | return -EINVAL; |
825 | 874 | ||
826 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
827 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
828 | |||
829 | kfree(ehotk); | 875 | kfree(ehotk); |
830 | return 0; | 876 | return 0; |
831 | } | 877 | } |
832 | 878 | ||
833 | static int eeepc_hotk_resume(struct acpi_device *device) | 879 | static int eeepc_hotk_resume(struct acpi_device *device) |
834 | { | 880 | { |
835 | if (ehotk->eeepc_wlan_rfkill) { | 881 | if (ehotk->wlan_rfkill) { |
836 | bool wlan; | 882 | bool wlan; |
837 | 883 | ||
838 | /* Workaround - it seems that _PTS disables the wireless | 884 | /* Workaround - it seems that _PTS disables the wireless |
@@ -844,14 +890,13 @@ static int eeepc_hotk_resume(struct acpi_device *device) | |||
844 | wlan = get_acpi(CM_ASL_WLAN); | 890 | wlan = get_acpi(CM_ASL_WLAN); |
845 | set_acpi(CM_ASL_WLAN, wlan); | 891 | set_acpi(CM_ASL_WLAN, wlan); |
846 | 892 | ||
847 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, | 893 | rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1); |
848 | wlan != 1); | ||
849 | 894 | ||
850 | eeepc_rfkill_hotplug(); | 895 | eeepc_rfkill_hotplug(); |
851 | } | 896 | } |
852 | 897 | ||
853 | if (ehotk->eeepc_bluetooth_rfkill) | 898 | if (ehotk->bluetooth_rfkill) |
854 | rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill, | 899 | rfkill_set_sw_state(ehotk->bluetooth_rfkill, |
855 | get_acpi(CM_ASL_BLUETOOTH) != 1); | 900 | get_acpi(CM_ASL_BLUETOOTH) != 1); |
856 | 901 | ||
857 | return 0; | 902 | return 0; |
@@ -973,10 +1018,16 @@ static void eeepc_backlight_exit(void) | |||
973 | 1018 | ||
974 | static void eeepc_rfkill_exit(void) | 1019 | static void eeepc_rfkill_exit(void) |
975 | { | 1020 | { |
976 | if (ehotk->eeepc_wlan_rfkill) | 1021 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); |
977 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | 1022 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); |
978 | if (ehotk->eeepc_bluetooth_rfkill) | 1023 | if (ehotk->wlan_rfkill) |
979 | rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); | 1024 | rfkill_unregister(ehotk->wlan_rfkill); |
1025 | if (ehotk->bluetooth_rfkill) | ||
1026 | rfkill_unregister(ehotk->bluetooth_rfkill); | ||
1027 | if (ehotk->wwan3g_rfkill) | ||
1028 | rfkill_unregister(ehotk->wwan3g_rfkill); | ||
1029 | if (ehotk->hotplug_slot) | ||
1030 | pci_hp_deregister(ehotk->hotplug_slot); | ||
980 | } | 1031 | } |
981 | 1032 | ||
982 | static void eeepc_input_exit(void) | 1033 | static void eeepc_input_exit(void) |
@@ -1011,6 +1062,75 @@ static void __exit eeepc_laptop_exit(void) | |||
1011 | platform_driver_unregister(&platform_driver); | 1062 | platform_driver_unregister(&platform_driver); |
1012 | } | 1063 | } |
1013 | 1064 | ||
1065 | static int eeepc_new_rfkill(struct rfkill **rfkill, | ||
1066 | const char *name, struct device *dev, | ||
1067 | enum rfkill_type type, int cm) | ||
1068 | { | ||
1069 | int result; | ||
1070 | |||
1071 | result = get_acpi(cm); | ||
1072 | if (result < 0) | ||
1073 | return result; | ||
1074 | |||
1075 | *rfkill = rfkill_alloc(name, dev, type, | ||
1076 | &eeepc_rfkill_ops, (void *)(unsigned long)cm); | ||
1077 | |||
1078 | if (!*rfkill) | ||
1079 | return -EINVAL; | ||
1080 | |||
1081 | rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1); | ||
1082 | result = rfkill_register(*rfkill); | ||
1083 | if (result) { | ||
1084 | rfkill_destroy(*rfkill); | ||
1085 | *rfkill = NULL; | ||
1086 | return result; | ||
1087 | } | ||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | |||
1092 | static int eeepc_rfkill_init(struct device *dev) | ||
1093 | { | ||
1094 | int result = 0; | ||
1095 | |||
1096 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
1097 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
1098 | |||
1099 | result = eeepc_new_rfkill(&ehotk->wlan_rfkill, | ||
1100 | "eeepc-wlan", dev, | ||
1101 | RFKILL_TYPE_WLAN, CM_ASL_WLAN); | ||
1102 | |||
1103 | if (result && result != -ENODEV) | ||
1104 | goto exit; | ||
1105 | |||
1106 | result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill, | ||
1107 | "eeepc-bluetooth", dev, | ||
1108 | RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH); | ||
1109 | |||
1110 | if (result && result != -ENODEV) | ||
1111 | goto exit; | ||
1112 | |||
1113 | result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill, | ||
1114 | "eeepc-wwan3g", dev, | ||
1115 | RFKILL_TYPE_WWAN, CM_ASL_3G); | ||
1116 | |||
1117 | if (result && result != -ENODEV) | ||
1118 | goto exit; | ||
1119 | |||
1120 | result = eeepc_setup_pci_hotplug(); | ||
1121 | /* | ||
1122 | * If we get -EBUSY then something else is handling the PCI hotplug - | ||
1123 | * don't fail in this case | ||
1124 | */ | ||
1125 | if (result == -EBUSY) | ||
1126 | result = 0; | ||
1127 | |||
1128 | exit: | ||
1129 | if (result && result != -ENODEV) | ||
1130 | eeepc_rfkill_exit(); | ||
1131 | return result; | ||
1132 | } | ||
1133 | |||
1014 | static int eeepc_backlight_init(struct device *dev) | 1134 | static int eeepc_backlight_init(struct device *dev) |
1015 | { | 1135 | { |
1016 | struct backlight_device *bd; | 1136 | struct backlight_device *bd; |
@@ -1018,8 +1138,7 @@ static int eeepc_backlight_init(struct device *dev) | |||
1018 | bd = backlight_device_register(EEEPC_HOTK_FILE, dev, | 1138 | bd = backlight_device_register(EEEPC_HOTK_FILE, dev, |
1019 | NULL, &eeepcbl_ops); | 1139 | NULL, &eeepcbl_ops); |
1020 | if (IS_ERR(bd)) { | 1140 | if (IS_ERR(bd)) { |
1021 | printk(EEEPC_ERR | 1141 | pr_err("Could not register eeepc backlight device\n"); |
1022 | "Could not register eeepc backlight device\n"); | ||
1023 | eeepc_backlight_device = NULL; | 1142 | eeepc_backlight_device = NULL; |
1024 | return PTR_ERR(bd); | 1143 | return PTR_ERR(bd); |
1025 | } | 1144 | } |
@@ -1038,8 +1157,7 @@ static int eeepc_hwmon_init(struct device *dev) | |||
1038 | 1157 | ||
1039 | hwmon = hwmon_device_register(dev); | 1158 | hwmon = hwmon_device_register(dev); |
1040 | if (IS_ERR(hwmon)) { | 1159 | if (IS_ERR(hwmon)) { |
1041 | printk(EEEPC_ERR | 1160 | pr_err("Could not register eeepc hwmon device\n"); |
1042 | "Could not register eeepc hwmon device\n"); | ||
1043 | eeepc_hwmon_device = NULL; | 1161 | eeepc_hwmon_device = NULL; |
1044 | return PTR_ERR(hwmon); | 1162 | return PTR_ERR(hwmon); |
1045 | } | 1163 | } |
@@ -1065,19 +1183,6 @@ static int __init eeepc_laptop_init(void) | |||
1065 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | 1183 | acpi_bus_unregister_driver(&eeepc_hotk_driver); |
1066 | return -ENODEV; | 1184 | return -ENODEV; |
1067 | } | 1185 | } |
1068 | dev = acpi_get_physical_device(ehotk->device->handle); | ||
1069 | |||
1070 | if (!acpi_video_backlight_support()) { | ||
1071 | result = eeepc_backlight_init(dev); | ||
1072 | if (result) | ||
1073 | goto fail_backlight; | ||
1074 | } else | ||
1075 | printk(EEEPC_INFO "Backlight controlled by ACPI video " | ||
1076 | "driver\n"); | ||
1077 | |||
1078 | result = eeepc_hwmon_init(dev); | ||
1079 | if (result) | ||
1080 | goto fail_hwmon; | ||
1081 | 1186 | ||
1082 | eeepc_enable_camera(); | 1187 | eeepc_enable_camera(); |
1083 | 1188 | ||
@@ -1097,7 +1202,33 @@ static int __init eeepc_laptop_init(void) | |||
1097 | &platform_attribute_group); | 1202 | &platform_attribute_group); |
1098 | if (result) | 1203 | if (result) |
1099 | goto fail_sysfs; | 1204 | goto fail_sysfs; |
1205 | |||
1206 | dev = &platform_device->dev; | ||
1207 | |||
1208 | if (!acpi_video_backlight_support()) { | ||
1209 | result = eeepc_backlight_init(dev); | ||
1210 | if (result) | ||
1211 | goto fail_backlight; | ||
1212 | } else | ||
1213 | pr_info("Backlight controlled by ACPI video " | ||
1214 | "driver\n"); | ||
1215 | |||
1216 | result = eeepc_hwmon_init(dev); | ||
1217 | if (result) | ||
1218 | goto fail_hwmon; | ||
1219 | |||
1220 | result = eeepc_rfkill_init(dev); | ||
1221 | if (result) | ||
1222 | goto fail_rfkill; | ||
1223 | |||
1100 | return 0; | 1224 | return 0; |
1225 | fail_rfkill: | ||
1226 | eeepc_hwmon_exit(); | ||
1227 | fail_hwmon: | ||
1228 | eeepc_backlight_exit(); | ||
1229 | fail_backlight: | ||
1230 | sysfs_remove_group(&platform_device->dev.kobj, | ||
1231 | &platform_attribute_group); | ||
1101 | fail_sysfs: | 1232 | fail_sysfs: |
1102 | platform_device_del(platform_device); | 1233 | platform_device_del(platform_device); |
1103 | fail_platform_device2: | 1234 | fail_platform_device2: |
@@ -1105,12 +1236,7 @@ fail_platform_device2: | |||
1105 | fail_platform_device1: | 1236 | fail_platform_device1: |
1106 | platform_driver_unregister(&platform_driver); | 1237 | platform_driver_unregister(&platform_driver); |
1107 | fail_platform_driver: | 1238 | fail_platform_driver: |
1108 | eeepc_hwmon_exit(); | ||
1109 | fail_hwmon: | ||
1110 | eeepc_backlight_exit(); | ||
1111 | fail_backlight: | ||
1112 | eeepc_input_exit(); | 1239 | eeepc_input_exit(); |
1113 | eeepc_rfkill_exit(); | ||
1114 | return result; | 1240 | return result; |
1115 | } | 1241 | } |
1116 | 1242 | ||
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index aafd3e6ebb0d..a118eb0f1e67 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Blackfin On-Chip Real Time Clock Driver | 2 | * Blackfin On-Chip Real Time Clock Driver |
3 | * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] | 3 | * Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x |
4 | * | 4 | * |
5 | * Copyright 2004-2008 Analog Devices Inc. | 5 | * Copyright 2004-2009 Analog Devices Inc. |
6 | * | 6 | * |
7 | * Enter bugs at http://blackfin.uclinux.org/ | 7 | * Enter bugs at http://blackfin.uclinux.org/ |
8 | * | 8 | * |
@@ -363,7 +363,7 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
363 | struct bfin_rtc *rtc; | 363 | struct bfin_rtc *rtc; |
364 | struct device *dev = &pdev->dev; | 364 | struct device *dev = &pdev->dev; |
365 | int ret = 0; | 365 | int ret = 0; |
366 | unsigned long timeout; | 366 | unsigned long timeout = jiffies + HZ; |
367 | 367 | ||
368 | dev_dbg_stamp(dev); | 368 | dev_dbg_stamp(dev); |
369 | 369 | ||
@@ -374,32 +374,32 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
374 | platform_set_drvdata(pdev, rtc); | 374 | platform_set_drvdata(pdev, rtc); |
375 | device_init_wakeup(dev, 1); | 375 | device_init_wakeup(dev, 1); |
376 | 376 | ||
377 | /* Register our RTC with the RTC framework */ | ||
378 | rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, | ||
379 | THIS_MODULE); | ||
380 | if (unlikely(IS_ERR(rtc->rtc_dev))) { | ||
381 | ret = PTR_ERR(rtc->rtc_dev); | ||
382 | goto err; | ||
383 | } | ||
384 | |||
377 | /* Grab the IRQ and init the hardware */ | 385 | /* Grab the IRQ and init the hardware */ |
378 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev); | 386 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev); |
379 | if (unlikely(ret)) | 387 | if (unlikely(ret)) |
380 | goto err; | 388 | goto err_reg; |
381 | /* sometimes the bootloader touched things, but the write complete was not | 389 | /* sometimes the bootloader touched things, but the write complete was not |
382 | * enabled, so let's just do a quick timeout here since the IRQ will not fire ... | 390 | * enabled, so let's just do a quick timeout here since the IRQ will not fire ... |
383 | */ | 391 | */ |
384 | timeout = jiffies + HZ; | ||
385 | while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) | 392 | while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) |
386 | if (time_after(jiffies, timeout)) | 393 | if (time_after(jiffies, timeout)) |
387 | break; | 394 | break; |
388 | bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); | 395 | bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); |
389 | bfin_write_RTC_SWCNT(0); | 396 | bfin_write_RTC_SWCNT(0); |
390 | 397 | ||
391 | /* Register our RTC with the RTC framework */ | ||
392 | rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, THIS_MODULE); | ||
393 | if (unlikely(IS_ERR(rtc->rtc_dev))) { | ||
394 | ret = PTR_ERR(rtc->rtc_dev); | ||
395 | goto err_irq; | ||
396 | } | ||
397 | |||
398 | return 0; | 398 | return 0; |
399 | 399 | ||
400 | err_irq: | 400 | err_reg: |
401 | free_irq(IRQ_RTC, dev); | 401 | rtc_device_unregister(rtc->rtc_dev); |
402 | err: | 402 | err: |
403 | kfree(rtc); | 403 | kfree(rtc); |
404 | return ret; | 404 | return ret; |
405 | } | 405 | } |
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index f11297aff854..2c839d0d21bd 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for NEC VR4100 series Real Time Clock unit. | 2 | * Driver for NEC VR4100 series Real Time Clock unit. |
3 | * | 3 | * |
4 | * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2003-2008 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -33,7 +33,7 @@ | |||
33 | #include <asm/io.h> | 33 | #include <asm/io.h> |
34 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
35 | 35 | ||
36 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 36 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
37 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); | 37 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); |
38 | MODULE_LICENSE("GPL v2"); | 38 | MODULE_LICENSE("GPL v2"); |
39 | 39 | ||
diff --git a/drivers/scsi/cxgb3i/Kbuild b/drivers/scsi/cxgb3i/Kbuild index 25a2032bfa26..70d060b7ff4f 100644 --- a/drivers/scsi/cxgb3i/Kbuild +++ b/drivers/scsi/cxgb3i/Kbuild | |||
@@ -1,4 +1,4 @@ | |||
1 | EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/cxgb3 | 1 | EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3 |
2 | 2 | ||
3 | cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o | 3 | cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o |
4 | obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o | 4 | obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index 74369a3f963b..c399f485aa7d 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <linux/inet.h> | 14 | #include <linux/inet.h> |
15 | #include <linux/crypto.h> | 15 | #include <linux/crypto.h> |
16 | #include <linux/if_vlan.h> | ||
16 | #include <net/dst.h> | 17 | #include <net/dst.h> |
17 | #include <net/tcp.h> | 18 | #include <net/tcp.h> |
18 | #include <scsi/scsi_cmnd.h> | 19 | #include <scsi/scsi_cmnd.h> |
@@ -184,6 +185,9 @@ static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev) | |||
184 | struct cxgb3i_adapter *snic; | 185 | struct cxgb3i_adapter *snic; |
185 | int i; | 186 | int i; |
186 | 187 | ||
188 | if (ndev->priv_flags & IFF_802_1Q_VLAN) | ||
189 | ndev = vlan_dev_real_dev(ndev); | ||
190 | |||
187 | read_lock(&cxgb3i_snic_rwlock); | 191 | read_lock(&cxgb3i_snic_rwlock); |
188 | list_for_each_entry(snic, &cxgb3i_snic_list, list_head) { | 192 | list_for_each_entry(snic, &cxgb3i_snic_list, list_head) { |
189 | for (i = 0; i < snic->hba_cnt; i++) { | 193 | for (i = 0; i < snic->hba_cnt; i++) { |
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index a84072865fc2..2c266c01dc5a 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c | |||
@@ -473,16 +473,16 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
473 | * limitation for the device. Try 40-bit first, and | 473 | * limitation for the device. Try 40-bit first, and |
474 | * fail to 32-bit. | 474 | * fail to 32-bit. |
475 | */ | 475 | */ |
476 | err = pci_set_dma_mask(pdev, DMA_40BIT_MASK); | 476 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(40)); |
477 | if (err) { | 477 | if (err) { |
478 | err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | 478 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
479 | if (err) { | 479 | if (err) { |
480 | shost_printk(KERN_ERR, fnic->lport->host, | 480 | shost_printk(KERN_ERR, fnic->lport->host, |
481 | "No usable DMA configuration " | 481 | "No usable DMA configuration " |
482 | "aborting\n"); | 482 | "aborting\n"); |
483 | goto err_out_release_regions; | 483 | goto err_out_release_regions; |
484 | } | 484 | } |
485 | err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); | 485 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); |
486 | if (err) { | 486 | if (err) { |
487 | shost_printk(KERN_ERR, fnic->lport->host, | 487 | shost_printk(KERN_ERR, fnic->lport->host, |
488 | "Unable to obtain 32-bit DMA " | 488 | "Unable to obtain 32-bit DMA " |
@@ -490,7 +490,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
490 | goto err_out_release_regions; | 490 | goto err_out_release_regions; |
491 | } | 491 | } |
492 | } else { | 492 | } else { |
493 | err = pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK); | 493 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40)); |
494 | if (err) { | 494 | if (err) { |
495 | shost_printk(KERN_ERR, fnic->lport->host, | 495 | shost_printk(KERN_ERR, fnic->lport->host, |
496 | "Unable to obtain 40-bit DMA " | 496 | "Unable to obtain 40-bit DMA " |
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index eabf36502856..bfc996971b81 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c | |||
@@ -245,7 +245,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic, | |||
245 | struct vnic_wq_copy *wq, | 245 | struct vnic_wq_copy *wq, |
246 | struct fnic_io_req *io_req, | 246 | struct fnic_io_req *io_req, |
247 | struct scsi_cmnd *sc, | 247 | struct scsi_cmnd *sc, |
248 | u32 sg_count) | 248 | int sg_count) |
249 | { | 249 | { |
250 | struct scatterlist *sg; | 250 | struct scatterlist *sg; |
251 | struct fc_rport *rport = starget_to_rport(scsi_target(sc->device)); | 251 | struct fc_rport *rport = starget_to_rport(scsi_target(sc->device)); |
@@ -260,9 +260,6 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic, | |||
260 | char msg[2]; | 260 | char msg[2]; |
261 | 261 | ||
262 | if (sg_count) { | 262 | if (sg_count) { |
263 | BUG_ON(sg_count < 0); | ||
264 | BUG_ON(sg_count > FNIC_MAX_SG_DESC_CNT); | ||
265 | |||
266 | /* For each SGE, create a device desc entry */ | 263 | /* For each SGE, create a device desc entry */ |
267 | desc = io_req->sgl_list; | 264 | desc = io_req->sgl_list; |
268 | for_each_sg(scsi_sglist(sc), sg, sg_count, i) { | 265 | for_each_sg(scsi_sglist(sc), sg, sg_count, i) { |
@@ -344,7 +341,7 @@ int fnic_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
344 | struct fnic *fnic; | 341 | struct fnic *fnic; |
345 | struct vnic_wq_copy *wq; | 342 | struct vnic_wq_copy *wq; |
346 | int ret; | 343 | int ret; |
347 | u32 sg_count; | 344 | int sg_count; |
348 | unsigned long flags; | 345 | unsigned long flags; |
349 | unsigned long ptr; | 346 | unsigned long ptr; |
350 | 347 | ||
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 869a11bdccbd..9928704e235f 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -1095,9 +1095,14 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct) | |||
1095 | MAX_INDIRECT_BUFS); | 1095 | MAX_INDIRECT_BUFS); |
1096 | hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; | 1096 | hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; |
1097 | } | 1097 | } |
1098 | |||
1099 | if (hostdata->madapter_info.os_type == 3) { | ||
1100 | enable_fast_fail(hostdata); | ||
1101 | return; | ||
1102 | } | ||
1098 | } | 1103 | } |
1099 | 1104 | ||
1100 | enable_fast_fail(hostdata); | 1105 | send_srp_login(hostdata); |
1101 | } | 1106 | } |
1102 | 1107 | ||
1103 | /** | 1108 | /** |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 2eee9e6e4fe8..292c02f810d0 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -3670,13 +3670,14 @@ static void | |||
3670 | fc_bsg_goose_queue(struct fc_rport *rport) | 3670 | fc_bsg_goose_queue(struct fc_rport *rport) |
3671 | { | 3671 | { |
3672 | int flagset; | 3672 | int flagset; |
3673 | unsigned long flags; | ||
3673 | 3674 | ||
3674 | if (!rport->rqst_q) | 3675 | if (!rport->rqst_q) |
3675 | return; | 3676 | return; |
3676 | 3677 | ||
3677 | get_device(&rport->dev); | 3678 | get_device(&rport->dev); |
3678 | 3679 | ||
3679 | spin_lock(rport->rqst_q->queue_lock); | 3680 | spin_lock_irqsave(rport->rqst_q->queue_lock, flags); |
3680 | flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) && | 3681 | flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) && |
3681 | !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags); | 3682 | !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags); |
3682 | if (flagset) | 3683 | if (flagset) |
@@ -3684,7 +3685,7 @@ fc_bsg_goose_queue(struct fc_rport *rport) | |||
3684 | __blk_run_queue(rport->rqst_q); | 3685 | __blk_run_queue(rport->rqst_q); |
3685 | if (flagset) | 3686 | if (flagset) |
3686 | queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q); | 3687 | queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q); |
3687 | spin_unlock(rport->rqst_q->queue_lock); | 3688 | spin_unlock_irqrestore(rport->rqst_q->queue_lock, flags); |
3688 | 3689 | ||
3689 | put_device(&rport->dev); | 3690 | put_device(&rport->dev); |
3690 | } | 3691 | } |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 8201387b4daa..ef142fd47a83 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -210,13 +210,11 @@ static void sg_put_dev(Sg_device *sdp); | |||
210 | static int sg_allow_access(struct file *filp, unsigned char *cmd) | 210 | static int sg_allow_access(struct file *filp, unsigned char *cmd) |
211 | { | 211 | { |
212 | struct sg_fd *sfp = (struct sg_fd *)filp->private_data; | 212 | struct sg_fd *sfp = (struct sg_fd *)filp->private_data; |
213 | struct request_queue *q = sfp->parentdp->device->request_queue; | ||
214 | 213 | ||
215 | if (sfp->parentdp->device->type == TYPE_SCANNER) | 214 | if (sfp->parentdp->device->type == TYPE_SCANNER) |
216 | return 0; | 215 | return 0; |
217 | 216 | ||
218 | return blk_verify_command(&q->cmd_filter, | 217 | return blk_verify_command(cmd, filp->f_mode & FMODE_WRITE); |
219 | cmd, filp->f_mode & FMODE_WRITE); | ||
220 | } | 218 | } |
221 | 219 | ||
222 | static int | 220 | static int |
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index 97f3158fa7b5..27e84e4b1fa9 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c | |||
@@ -134,7 +134,7 @@ zalon_probe(struct parisc_device *dev) | |||
134 | 134 | ||
135 | host = ncr_attach(&zalon7xx_template, unit, &device); | 135 | host = ncr_attach(&zalon7xx_template, unit, &device); |
136 | if (!host) | 136 | if (!host) |
137 | goto fail; | 137 | return -ENODEV; |
138 | 138 | ||
139 | if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) { | 139 | if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) { |
140 | dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ", | 140 | dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ", |
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index a07015d646dd..6160e03f410c 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c | |||
@@ -759,6 +759,8 @@ static int pci_netmos_init(struct pci_dev *dev) | |||
759 | /* subdevice 0x00PS means <P> parallel, <S> serial */ | 759 | /* subdevice 0x00PS means <P> parallel, <S> serial */ |
760 | unsigned int num_serial = dev->subsystem_device & 0xf; | 760 | unsigned int num_serial = dev->subsystem_device & 0xf; |
761 | 761 | ||
762 | if (dev->device == PCI_DEVICE_ID_NETMOS_9901) | ||
763 | return 0; | ||
762 | if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && | 764 | if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && |
763 | dev->subsystem_device == 0x0299) | 765 | dev->subsystem_device == 0x0299) |
764 | return 0; | 766 | return 0; |
@@ -3557,6 +3559,10 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
3557 | PCI_VENDOR_ID_IBM, 0x0299, | 3559 | PCI_VENDOR_ID_IBM, 0x0299, |
3558 | 0, 0, pbn_b0_bt_2_115200 }, | 3560 | 0, 0, pbn_b0_bt_2_115200 }, |
3559 | 3561 | ||
3562 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, | ||
3563 | 0xA000, 0x1000, | ||
3564 | 0, 0, pbn_b0_1_115200 }, | ||
3565 | |||
3560 | /* | 3566 | /* |
3561 | * These entries match devices with class COMMUNICATION_SERIAL, | 3567 | * These entries match devices with class COMMUNICATION_SERIAL, |
3562 | * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL | 3568 | * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL |
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index 0573f3b5175e..dac550e57c29 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for NEC VR4100 series Serial Interface Unit. | 2 | * Driver for NEC VR4100 series Serial Interface Unit. |
3 | * | 3 | * |
4 | * Copyright (C) 2004-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2004-2008 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * Based on drivers/serial/8250.c, by Russell King. | 6 | * Based on drivers/serial/8250.c, by Russell King. |
7 | * | 7 | * |
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c index aa90ddb37066..8980a5640bd9 100644 --- a/drivers/spi/omap_uwire.c +++ b/drivers/spi/omap_uwire.c | |||
@@ -514,6 +514,8 @@ static int __init uwire_probe(struct platform_device *pdev) | |||
514 | /* the spi->mode bits understood by this driver: */ | 514 | /* the spi->mode bits understood by this driver: */ |
515 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | 515 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; |
516 | 516 | ||
517 | master->flags = SPI_MASTER_HALF_DUPLEX; | ||
518 | |||
517 | master->bus_num = 2; /* "official" */ | 519 | master->bus_num = 2; /* "official" */ |
518 | master->num_chipselect = 4; | 520 | master->num_chipselect = 4; |
519 | master->setup = uwire_setup; | 521 | master->setup = uwire_setup; |
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 2a5abc08e857..f1db395dd889 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c | |||
@@ -258,6 +258,11 @@ static void bitbang_work(struct work_struct *work) | |||
258 | struct spi_bitbang *bitbang = | 258 | struct spi_bitbang *bitbang = |
259 | container_of(work, struct spi_bitbang, work); | 259 | container_of(work, struct spi_bitbang, work); |
260 | unsigned long flags; | 260 | unsigned long flags; |
261 | int do_setup = -1; | ||
262 | int (*setup_transfer)(struct spi_device *, | ||
263 | struct spi_transfer *); | ||
264 | |||
265 | setup_transfer = bitbang->setup_transfer; | ||
261 | 266 | ||
262 | spin_lock_irqsave(&bitbang->lock, flags); | 267 | spin_lock_irqsave(&bitbang->lock, flags); |
263 | bitbang->busy = 1; | 268 | bitbang->busy = 1; |
@@ -269,8 +274,6 @@ static void bitbang_work(struct work_struct *work) | |||
269 | unsigned tmp; | 274 | unsigned tmp; |
270 | unsigned cs_change; | 275 | unsigned cs_change; |
271 | int status; | 276 | int status; |
272 | int (*setup_transfer)(struct spi_device *, | ||
273 | struct spi_transfer *); | ||
274 | 277 | ||
275 | m = container_of(bitbang->queue.next, struct spi_message, | 278 | m = container_of(bitbang->queue.next, struct spi_message, |
276 | queue); | 279 | queue); |
@@ -287,19 +290,19 @@ static void bitbang_work(struct work_struct *work) | |||
287 | tmp = 0; | 290 | tmp = 0; |
288 | cs_change = 1; | 291 | cs_change = 1; |
289 | status = 0; | 292 | status = 0; |
290 | setup_transfer = NULL; | ||
291 | 293 | ||
292 | list_for_each_entry (t, &m->transfers, transfer_list) { | 294 | list_for_each_entry (t, &m->transfers, transfer_list) { |
293 | 295 | ||
294 | /* override or restore speed and wordsize */ | 296 | /* override speed or wordsize? */ |
295 | if (t->speed_hz || t->bits_per_word) { | 297 | if (t->speed_hz || t->bits_per_word) |
296 | setup_transfer = bitbang->setup_transfer; | 298 | do_setup = 1; |
299 | |||
300 | /* init (-1) or override (1) transfer params */ | ||
301 | if (do_setup != 0) { | ||
297 | if (!setup_transfer) { | 302 | if (!setup_transfer) { |
298 | status = -ENOPROTOOPT; | 303 | status = -ENOPROTOOPT; |
299 | break; | 304 | break; |
300 | } | 305 | } |
301 | } | ||
302 | if (setup_transfer) { | ||
303 | status = setup_transfer(spi, t); | 306 | status = setup_transfer(spi, t); |
304 | if (status < 0) | 307 | if (status < 0) |
305 | break; | 308 | break; |
@@ -363,9 +366,10 @@ static void bitbang_work(struct work_struct *work) | |||
363 | m->status = status; | 366 | m->status = status; |
364 | m->complete(m->context); | 367 | m->complete(m->context); |
365 | 368 | ||
366 | /* restore speed and wordsize */ | 369 | /* restore speed and wordsize if it was overridden */ |
367 | if (setup_transfer) | 370 | if (do_setup == 1) |
368 | setup_transfer(spi, NULL); | 371 | setup_transfer(spi, NULL); |
372 | do_setup = 0; | ||
369 | 373 | ||
370 | /* normally deactivate chipselect ... unless no error and | 374 | /* normally deactivate chipselect ... unless no error and |
371 | * cs_change has hinted that the next message will probably | 375 | * cs_change has hinted that the next message will probably |
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 5d869c4d3eb2..606e7a40a8da 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c | |||
@@ -58,15 +58,20 @@ static unsigned long minors[N_SPI_MINORS / BITS_PER_LONG]; | |||
58 | 58 | ||
59 | 59 | ||
60 | /* Bit masks for spi_device.mode management. Note that incorrect | 60 | /* Bit masks for spi_device.mode management. Note that incorrect |
61 | * settings for CS_HIGH and 3WIRE can cause *lots* of trouble for other | 61 | * settings for some settings can cause *lots* of trouble for other |
62 | * devices on a shared bus: CS_HIGH, because this device will be | 62 | * devices on a shared bus: |
63 | * active when it shouldn't be; 3WIRE, because when active it won't | ||
64 | * behave as it should. | ||
65 | * | 63 | * |
66 | * REVISIT should changing those two modes be privileged? | 64 | * - CS_HIGH ... this device will be active when it shouldn't be |
65 | * - 3WIRE ... when active, it won't behave as it should | ||
66 | * - NO_CS ... there will be no explicit message boundaries; this | ||
67 | * is completely incompatible with the shared bus model | ||
68 | * - READY ... transfers may proceed when they shouldn't. | ||
69 | * | ||
70 | * REVISIT should changing those flags be privileged? | ||
67 | */ | 71 | */ |
68 | #define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ | 72 | #define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ |
69 | | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP) | 73 | | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ |
74 | | SPI_NO_CS | SPI_READY) | ||
70 | 75 | ||
71 | struct spidev_data { | 76 | struct spidev_data { |
72 | dev_t devt; | 77 | dev_t devt; |
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 3fd3e3b412b6..3c6feed46f6e 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c | |||
@@ -49,29 +49,54 @@ static const u32 ipsflag_irq_shift[] = { | |||
49 | 49 | ||
50 | static inline u32 ssb_irqflag(struct ssb_device *dev) | 50 | static inline u32 ssb_irqflag(struct ssb_device *dev) |
51 | { | 51 | { |
52 | return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; | 52 | u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG); |
53 | if (tpsflag) | ||
54 | return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; | ||
55 | else | ||
56 | /* not irq supported */ | ||
57 | return 0x3f; | ||
58 | } | ||
59 | |||
60 | static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag) | ||
61 | { | ||
62 | struct ssb_bus *bus = rdev->bus; | ||
63 | int i; | ||
64 | for (i = 0; i < bus->nr_devices; i++) { | ||
65 | struct ssb_device *dev; | ||
66 | dev = &(bus->devices[i]); | ||
67 | if (ssb_irqflag(dev) == irqflag) | ||
68 | return dev; | ||
69 | } | ||
70 | return NULL; | ||
53 | } | 71 | } |
54 | 72 | ||
55 | /* Get the MIPS IRQ assignment for a specified device. | 73 | /* Get the MIPS IRQ assignment for a specified device. |
56 | * If unassigned, 0 is returned. | 74 | * If unassigned, 0 is returned. |
75 | * If disabled, 5 is returned. | ||
76 | * If not supported, 6 is returned. | ||
57 | */ | 77 | */ |
58 | unsigned int ssb_mips_irq(struct ssb_device *dev) | 78 | unsigned int ssb_mips_irq(struct ssb_device *dev) |
59 | { | 79 | { |
60 | struct ssb_bus *bus = dev->bus; | 80 | struct ssb_bus *bus = dev->bus; |
81 | struct ssb_device *mdev = bus->mipscore.dev; | ||
61 | u32 irqflag; | 82 | u32 irqflag; |
62 | u32 ipsflag; | 83 | u32 ipsflag; |
63 | u32 tmp; | 84 | u32 tmp; |
64 | unsigned int irq; | 85 | unsigned int irq; |
65 | 86 | ||
66 | irqflag = ssb_irqflag(dev); | 87 | irqflag = ssb_irqflag(dev); |
88 | if (irqflag == 0x3f) | ||
89 | return 6; | ||
67 | ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG); | 90 | ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG); |
68 | for (irq = 1; irq <= 4; irq++) { | 91 | for (irq = 1; irq <= 4; irq++) { |
69 | tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]); | 92 | tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]); |
70 | if (tmp == irqflag) | 93 | if (tmp == irqflag) |
71 | break; | 94 | break; |
72 | } | 95 | } |
73 | if (irq == 5) | 96 | if (irq == 5) { |
74 | irq = 0; | 97 | if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)) |
98 | irq = 0; | ||
99 | } | ||
75 | 100 | ||
76 | return irq; | 101 | return irq; |
77 | } | 102 | } |
@@ -97,25 +122,56 @@ static void set_irq(struct ssb_device *dev, unsigned int irq) | |||
97 | struct ssb_device *mdev = bus->mipscore.dev; | 122 | struct ssb_device *mdev = bus->mipscore.dev; |
98 | u32 irqflag = ssb_irqflag(dev); | 123 | u32 irqflag = ssb_irqflag(dev); |
99 | 124 | ||
125 | BUG_ON(oldirq == 6); | ||
126 | |||
100 | dev->irq = irq + 2; | 127 | dev->irq = irq + 2; |
101 | 128 | ||
102 | ssb_dprintk(KERN_INFO PFX | ||
103 | "set_irq: core 0x%04x, irq %d => %d\n", | ||
104 | dev->id.coreid, oldirq, irq); | ||
105 | /* clear the old irq */ | 129 | /* clear the old irq */ |
106 | if (oldirq == 0) | 130 | if (oldirq == 0) |
107 | ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); | 131 | ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); |
108 | else | 132 | else if (oldirq != 5) |
109 | clear_irq(bus, oldirq); | 133 | clear_irq(bus, oldirq); |
110 | 134 | ||
111 | /* assign the new one */ | 135 | /* assign the new one */ |
112 | if (irq == 0) { | 136 | if (irq == 0) { |
113 | ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC))); | 137 | ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC))); |
114 | } else { | 138 | } else { |
139 | u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG); | ||
140 | if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) { | ||
141 | u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]; | ||
142 | struct ssb_device *olddev = find_device(dev, oldipsflag); | ||
143 | if (olddev) | ||
144 | set_irq(olddev, 0); | ||
145 | } | ||
115 | irqflag <<= ipsflag_irq_shift[irq]; | 146 | irqflag <<= ipsflag_irq_shift[irq]; |
116 | irqflag |= (ssb_read32(mdev, SSB_IPSFLAG) & ~ipsflag_irq_mask[irq]); | 147 | irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); |
117 | ssb_write32(mdev, SSB_IPSFLAG, irqflag); | 148 | ssb_write32(mdev, SSB_IPSFLAG, irqflag); |
118 | } | 149 | } |
150 | ssb_dprintk(KERN_INFO PFX | ||
151 | "set_irq: core 0x%04x, irq %d => %d\n", | ||
152 | dev->id.coreid, oldirq+2, irq+2); | ||
153 | } | ||
154 | |||
155 | static void print_irq(struct ssb_device *dev, unsigned int irq) | ||
156 | { | ||
157 | int i; | ||
158 | static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; | ||
159 | ssb_dprintk(KERN_INFO PFX | ||
160 | "core 0x%04x, irq :", dev->id.coreid); | ||
161 | for (i = 0; i <= 6; i++) { | ||
162 | ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" "); | ||
163 | } | ||
164 | ssb_dprintk("\n"); | ||
165 | } | ||
166 | |||
167 | static void dump_irq(struct ssb_bus *bus) | ||
168 | { | ||
169 | int i; | ||
170 | for (i = 0; i < bus->nr_devices; i++) { | ||
171 | struct ssb_device *dev; | ||
172 | dev = &(bus->devices[i]); | ||
173 | print_irq(dev, ssb_mips_irq(dev)); | ||
174 | } | ||
119 | } | 175 | } |
120 | 176 | ||
121 | static void ssb_mips_serial_init(struct ssb_mipscore *mcore) | 177 | static void ssb_mips_serial_init(struct ssb_mipscore *mcore) |
@@ -197,16 +253,23 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
197 | 253 | ||
198 | /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ | 254 | /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ |
199 | for (irq = 2, i = 0; i < bus->nr_devices; i++) { | 255 | for (irq = 2, i = 0; i < bus->nr_devices; i++) { |
256 | int mips_irq; | ||
200 | dev = &(bus->devices[i]); | 257 | dev = &(bus->devices[i]); |
201 | dev->irq = ssb_mips_irq(dev) + 2; | 258 | mips_irq = ssb_mips_irq(dev); |
259 | if (mips_irq > 4) | ||
260 | dev->irq = 0; | ||
261 | else | ||
262 | dev->irq = mips_irq + 2; | ||
263 | if (dev->irq > 5) | ||
264 | continue; | ||
202 | switch (dev->id.coreid) { | 265 | switch (dev->id.coreid) { |
203 | case SSB_DEV_USB11_HOST: | 266 | case SSB_DEV_USB11_HOST: |
204 | /* shouldn't need a separate irq line for non-4710, most of them have a proper | 267 | /* shouldn't need a separate irq line for non-4710, most of them have a proper |
205 | * external usb controller on the pci */ | 268 | * external usb controller on the pci */ |
206 | if ((bus->chip_id == 0x4710) && (irq <= 4)) { | 269 | if ((bus->chip_id == 0x4710) && (irq <= 4)) { |
207 | set_irq(dev, irq++); | 270 | set_irq(dev, irq++); |
208 | break; | ||
209 | } | 271 | } |
272 | break; | ||
210 | /* fallthrough */ | 273 | /* fallthrough */ |
211 | case SSB_DEV_PCI: | 274 | case SSB_DEV_PCI: |
212 | case SSB_DEV_ETHERNET: | 275 | case SSB_DEV_ETHERNET: |
@@ -220,6 +283,8 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
220 | } | 283 | } |
221 | } | 284 | } |
222 | } | 285 | } |
286 | ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); | ||
287 | dump_irq(bus); | ||
223 | 288 | ||
224 | ssb_mips_serial_init(mcore); | 289 | ssb_mips_serial_init(mcore); |
225 | ssb_mips_flash_detect(mcore); | 290 | ssb_mips_flash_detect(mcore); |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 38bfdb0f6660..3f1045993474 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -550,7 +550,7 @@ static void acm_waker(struct work_struct *waker) | |||
550 | static int acm_tty_open(struct tty_struct *tty, struct file *filp) | 550 | static int acm_tty_open(struct tty_struct *tty, struct file *filp) |
551 | { | 551 | { |
552 | struct acm *acm; | 552 | struct acm *acm; |
553 | int rv = -EINVAL; | 553 | int rv = -ENODEV; |
554 | int i; | 554 | int i; |
555 | dbg("Entering acm_tty_open."); | 555 | dbg("Entering acm_tty_open."); |
556 | 556 | ||
@@ -677,7 +677,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) | |||
677 | 677 | ||
678 | /* Perform the closing process and see if we need to do the hardware | 678 | /* Perform the closing process and see if we need to do the hardware |
679 | shutdown */ | 679 | shutdown */ |
680 | if (tty_port_close_start(&acm->port, tty, filp) == 0) | 680 | if (!acm || tty_port_close_start(&acm->port, tty, filp) == 0) |
681 | return; | 681 | return; |
682 | acm_port_down(acm, 0); | 682 | acm_port_down(acm, 0); |
683 | tty_port_close_end(&acm->port, tty); | 683 | tty_port_close_end(&acm->port, tty); |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index d595aa5586a7..a84216464ca0 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -333,6 +333,9 @@ static void serial_close(struct tty_struct *tty, struct file *filp) | |||
333 | { | 333 | { |
334 | struct usb_serial_port *port = tty->driver_data; | 334 | struct usb_serial_port *port = tty->driver_data; |
335 | 335 | ||
336 | if (!port) | ||
337 | return; | ||
338 | |||
336 | dbg("%s - port %d", __func__, port->number); | 339 | dbg("%s - port %d", __func__, port->number); |
337 | 340 | ||
338 | 341 | ||
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index d6d65ef85f54..8afcf08eba98 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -616,6 +616,8 @@ config FB_STI | |||
616 | select FB_CFB_FILLRECT | 616 | select FB_CFB_FILLRECT |
617 | select FB_CFB_COPYAREA | 617 | select FB_CFB_COPYAREA |
618 | select FB_CFB_IMAGEBLIT | 618 | select FB_CFB_IMAGEBLIT |
619 | select STI_CONSOLE | ||
620 | select VT | ||
619 | default y | 621 | default y |
620 | ---help--- | 622 | ---help--- |
621 | STI refers to the HP "Standard Text Interface" which is a set of | 623 | STI refers to the HP "Standard Text Interface" which is a set of |
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 018850c116c6..497ff8af03ed 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c | |||
@@ -2414,7 +2414,10 @@ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) | |||
2414 | if (err) | 2414 | if (err) |
2415 | return err; | 2415 | return err; |
2416 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | 2416 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); |
2417 | return fbhw->encode_fix(fix, &par); | 2417 | mutex_lock(&info->mm_lock); |
2418 | err = fbhw->encode_fix(fix, &par); | ||
2419 | mutex_unlock(&info->mm_lock); | ||
2420 | return err; | ||
2418 | } | 2421 | } |
2419 | 2422 | ||
2420 | static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info) | 2423 | static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info) |
@@ -2743,7 +2746,9 @@ static int atafb_set_par(struct fb_info *info) | |||
2743 | 2746 | ||
2744 | /* Decode wanted screen parameters */ | 2747 | /* Decode wanted screen parameters */ |
2745 | fbhw->decode_var(&info->var, par); | 2748 | fbhw->decode_var(&info->var, par); |
2749 | mutex_lock(&info->mm_lock); | ||
2746 | fbhw->encode_fix(&info->fix, par); | 2750 | fbhw->encode_fix(&info->fix, par); |
2751 | mutex_unlock(&info->mm_lock); | ||
2747 | 2752 | ||
2748 | /* Set new videomode */ | 2753 | /* Set new videomode */ |
2749 | ata_set_par(par); | 2754 | ata_set_par(par); |
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 5afd64482f55..cb88394ba995 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
@@ -270,7 +270,9 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) | |||
270 | 270 | ||
271 | smem_len = (var->xres_virtual * var->yres_virtual | 271 | smem_len = (var->xres_virtual * var->yres_virtual |
272 | * ((var->bits_per_pixel + 7) / 8)); | 272 | * ((var->bits_per_pixel + 7) / 8)); |
273 | mutex_lock(&info->mm_lock); | ||
273 | info->fix.smem_len = max(smem_len, sinfo->smem_len); | 274 | info->fix.smem_len = max(smem_len, sinfo->smem_len); |
275 | mutex_unlock(&info->mm_lock); | ||
274 | 276 | ||
275 | info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, | 277 | info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, |
276 | (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); | 278 | (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); |
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h index 7691e73823d3..1f39a62f899b 100644 --- a/drivers/video/aty/atyfb.h +++ b/drivers/video/aty/atyfb.h | |||
@@ -187,6 +187,8 @@ struct atyfb_par { | |||
187 | int mtrr_reg; | 187 | int mtrr_reg; |
188 | #endif | 188 | #endif |
189 | u32 mem_cntl; | 189 | u32 mem_cntl; |
190 | struct crtc saved_crtc; | ||
191 | union aty_pll saved_pll; | ||
190 | }; | 192 | }; |
191 | 193 | ||
192 | /* | 194 | /* |
@@ -217,6 +219,7 @@ struct atyfb_par { | |||
217 | #define M64F_XL_DLL 0x00080000 | 219 | #define M64F_XL_DLL 0x00080000 |
218 | #define M64F_MFB_FORCE_4 0x00100000 | 220 | #define M64F_MFB_FORCE_4 0x00100000 |
219 | #define M64F_HW_TRIPLE 0x00200000 | 221 | #define M64F_HW_TRIPLE 0x00200000 |
222 | #define M64F_XL_MEM 0x00400000 | ||
220 | /* | 223 | /* |
221 | * Register access | 224 | * Register access |
222 | */ | 225 | */ |
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 1207c208a30b..63d3739d43a8 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c | |||
@@ -66,6 +66,8 @@ | |||
66 | #include <linux/spinlock.h> | 66 | #include <linux/spinlock.h> |
67 | #include <linux/wait.h> | 67 | #include <linux/wait.h> |
68 | #include <linux/backlight.h> | 68 | #include <linux/backlight.h> |
69 | #include <linux/reboot.h> | ||
70 | #include <linux/dmi.h> | ||
69 | 71 | ||
70 | #include <asm/io.h> | 72 | #include <asm/io.h> |
71 | #include <linux/uaccess.h> | 73 | #include <linux/uaccess.h> |
@@ -249,8 +251,6 @@ static int aty_init(struct fb_info *info); | |||
249 | static int store_video_par(char *videopar, unsigned char m64_num); | 251 | static int store_video_par(char *videopar, unsigned char m64_num); |
250 | #endif | 252 | #endif |
251 | 253 | ||
252 | static struct crtc saved_crtc; | ||
253 | static union aty_pll saved_pll; | ||
254 | static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc); | 254 | static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc); |
255 | 255 | ||
256 | static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc); | 256 | static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc); |
@@ -261,6 +261,8 @@ static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info); | |||
261 | static int read_aty_sense(const struct atyfb_par *par); | 261 | static int read_aty_sense(const struct atyfb_par *par); |
262 | #endif | 262 | #endif |
263 | 263 | ||
264 | static DEFINE_MUTEX(reboot_lock); | ||
265 | static struct fb_info *reboot_info; | ||
264 | 266 | ||
265 | /* | 267 | /* |
266 | * Interface used by the world | 268 | * Interface used by the world |
@@ -361,8 +363,8 @@ static unsigned long phys_guiregbase[FB_MAX] __devinitdata = { 0, }; | |||
361 | #define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D) | 363 | #define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D) |
362 | #define ATI_CHIP_264LTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D) | 364 | #define ATI_CHIP_264LTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D) |
363 | 365 | ||
364 | #define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4) | 366 | #define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM) |
365 | #define ATI_CHIP_MOBILITY (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_MOBIL_BUS) | 367 | #define ATI_CHIP_MOBILITY (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM | M64F_MOBIL_BUS) |
366 | 368 | ||
367 | static struct { | 369 | static struct { |
368 | u16 pci_id; | 370 | u16 pci_id; |
@@ -539,6 +541,7 @@ static char ram_edo[] __devinitdata = "EDO"; | |||
539 | static char ram_sdram[] __devinitdata = "SDRAM (1:1)"; | 541 | static char ram_sdram[] __devinitdata = "SDRAM (1:1)"; |
540 | static char ram_sgram[] __devinitdata = "SGRAM (1:1)"; | 542 | static char ram_sgram[] __devinitdata = "SGRAM (1:1)"; |
541 | static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)"; | 543 | static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)"; |
544 | static char ram_wram[] __devinitdata = "WRAM"; | ||
542 | static char ram_off[] __devinitdata = "OFF"; | 545 | static char ram_off[] __devinitdata = "OFF"; |
543 | #endif /* CONFIG_FB_ATY_CT */ | 546 | #endif /* CONFIG_FB_ATY_CT */ |
544 | 547 | ||
@@ -553,6 +556,10 @@ static char *aty_gx_ram[8] __devinitdata = { | |||
553 | #ifdef CONFIG_FB_ATY_CT | 556 | #ifdef CONFIG_FB_ATY_CT |
554 | static char *aty_ct_ram[8] __devinitdata = { | 557 | static char *aty_ct_ram[8] __devinitdata = { |
555 | ram_off, ram_dram, ram_edo, ram_edo, | 558 | ram_off, ram_dram, ram_edo, ram_edo, |
559 | ram_sdram, ram_sgram, ram_wram, ram_resv | ||
560 | }; | ||
561 | static char *aty_xl_ram[8] __devinitdata = { | ||
562 | ram_off, ram_dram, ram_edo, ram_edo, | ||
556 | ram_sdram, ram_sgram, ram_sdram32, ram_resv | 563 | ram_sdram, ram_sgram, ram_sdram32, ram_resv |
557 | }; | 564 | }; |
558 | #endif /* CONFIG_FB_ATY_CT */ | 565 | #endif /* CONFIG_FB_ATY_CT */ |
@@ -760,6 +767,17 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) | |||
760 | #endif /* CONFIG_FB_ATY_GENERIC_LCD */ | 767 | #endif /* CONFIG_FB_ATY_GENERIC_LCD */ |
761 | } | 768 | } |
762 | 769 | ||
770 | static u32 calc_line_length(struct atyfb_par *par, u32 vxres, u32 bpp) | ||
771 | { | ||
772 | u32 line_length = vxres * bpp / 8; | ||
773 | |||
774 | if (par->ram_type == SGRAM || | ||
775 | (!M64_HAS(XL_MEM) && par->ram_type == WRAM)) | ||
776 | line_length = (line_length + 63) & ~63; | ||
777 | |||
778 | return line_length; | ||
779 | } | ||
780 | |||
763 | static int aty_var_to_crtc(const struct fb_info *info, | 781 | static int aty_var_to_crtc(const struct fb_info *info, |
764 | const struct fb_var_screeninfo *var, struct crtc *crtc) | 782 | const struct fb_var_screeninfo *var, struct crtc *crtc) |
765 | { | 783 | { |
@@ -769,13 +787,14 @@ static int aty_var_to_crtc(const struct fb_info *info, | |||
769 | u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol; | 787 | u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol; |
770 | u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync; | 788 | u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync; |
771 | u32 pix_width, dp_pix_width, dp_chain_mask; | 789 | u32 pix_width, dp_pix_width, dp_chain_mask; |
790 | u32 line_length; | ||
772 | 791 | ||
773 | /* input */ | 792 | /* input */ |
774 | xres = var->xres; | 793 | xres = (var->xres + 7) & ~7; |
775 | yres = var->yres; | 794 | yres = var->yres; |
776 | vxres = var->xres_virtual; | 795 | vxres = (var->xres_virtual + 7) & ~7; |
777 | vyres = var->yres_virtual; | 796 | vyres = var->yres_virtual; |
778 | xoffset = var->xoffset; | 797 | xoffset = (var->xoffset + 7) & ~7; |
779 | yoffset = var->yoffset; | 798 | yoffset = var->yoffset; |
780 | bpp = var->bits_per_pixel; | 799 | bpp = var->bits_per_pixel; |
781 | if (bpp == 16) | 800 | if (bpp == 16) |
@@ -827,7 +846,9 @@ static int aty_var_to_crtc(const struct fb_info *info, | |||
827 | } else | 846 | } else |
828 | FAIL("invalid bpp"); | 847 | FAIL("invalid bpp"); |
829 | 848 | ||
830 | if (vxres * vyres * bpp / 8 > info->fix.smem_len) | 849 | line_length = calc_line_length(par, vxres, bpp); |
850 | |||
851 | if (vyres * line_length > info->fix.smem_len) | ||
831 | FAIL("not enough video RAM"); | 852 | FAIL("not enough video RAM"); |
832 | 853 | ||
833 | h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; | 854 | h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; |
@@ -969,7 +990,9 @@ static int aty_var_to_crtc(const struct fb_info *info, | |||
969 | crtc->xoffset = xoffset; | 990 | crtc->xoffset = xoffset; |
970 | crtc->yoffset = yoffset; | 991 | crtc->yoffset = yoffset; |
971 | crtc->bpp = bpp; | 992 | crtc->bpp = bpp; |
972 | crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19); | 993 | crtc->off_pitch = |
994 | ((yoffset * line_length + xoffset * bpp / 8) / 8) | | ||
995 | ((line_length / bpp) << 22); | ||
973 | crtc->vline_crnt_vline = 0; | 996 | crtc->vline_crnt_vline = 0; |
974 | 997 | ||
975 | crtc->h_tot_disp = h_total | (h_disp<<16); | 998 | crtc->h_tot_disp = h_total | (h_disp<<16); |
@@ -1394,7 +1417,9 @@ static int atyfb_set_par(struct fb_info *info) | |||
1394 | } | 1417 | } |
1395 | aty_st_8(DAC_MASK, 0xff, par); | 1418 | aty_st_8(DAC_MASK, 0xff, par); |
1396 | 1419 | ||
1397 | info->fix.line_length = var->xres_virtual * var->bits_per_pixel/8; | 1420 | info->fix.line_length = calc_line_length(par, var->xres_virtual, |
1421 | var->bits_per_pixel); | ||
1422 | |||
1398 | info->fix.visual = var->bits_per_pixel <= 8 ? | 1423 | info->fix.visual = var->bits_per_pixel <= 8 ? |
1399 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; | 1424 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; |
1400 | 1425 | ||
@@ -1505,10 +1530,12 @@ static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info) | |||
1505 | { | 1530 | { |
1506 | u32 xoffset = info->var.xoffset; | 1531 | u32 xoffset = info->var.xoffset; |
1507 | u32 yoffset = info->var.yoffset; | 1532 | u32 yoffset = info->var.yoffset; |
1508 | u32 vxres = par->crtc.vxres; | 1533 | u32 line_length = info->fix.line_length; |
1509 | u32 bpp = info->var.bits_per_pixel; | 1534 | u32 bpp = info->var.bits_per_pixel; |
1510 | 1535 | ||
1511 | par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19); | 1536 | par->crtc.off_pitch = |
1537 | ((yoffset * line_length + xoffset * bpp / 8) / 8) | | ||
1538 | ((line_length / bpp) << 22); | ||
1512 | } | 1539 | } |
1513 | 1540 | ||
1514 | 1541 | ||
@@ -2201,7 +2228,7 @@ static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk) | |||
2201 | const int *refresh_tbl; | 2228 | const int *refresh_tbl; |
2202 | int i, size; | 2229 | int i, size; |
2203 | 2230 | ||
2204 | if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) { | 2231 | if (M64_HAS(XL_MEM)) { |
2205 | refresh_tbl = ragexl_tbl; | 2232 | refresh_tbl = ragexl_tbl; |
2206 | size = ARRAY_SIZE(ragexl_tbl); | 2233 | size = ARRAY_SIZE(ragexl_tbl); |
2207 | } else { | 2234 | } else { |
@@ -2335,7 +2362,10 @@ static int __devinit aty_init(struct fb_info *info) | |||
2335 | par->pll_ops = &aty_pll_ct; | 2362 | par->pll_ops = &aty_pll_ct; |
2336 | par->bus_type = PCI; | 2363 | par->bus_type = PCI; |
2337 | par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07); | 2364 | par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07); |
2338 | ramname = aty_ct_ram[par->ram_type]; | 2365 | if (M64_HAS(XL_MEM)) |
2366 | ramname = aty_xl_ram[par->ram_type]; | ||
2367 | else | ||
2368 | ramname = aty_ct_ram[par->ram_type]; | ||
2339 | /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ | 2369 | /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ |
2340 | if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM) | 2370 | if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM) |
2341 | par->pll_limits.mclk = 63; | 2371 | par->pll_limits.mclk = 63; |
@@ -2390,9 +2420,9 @@ static int __devinit aty_init(struct fb_info *info) | |||
2390 | #endif /* CONFIG_FB_ATY_CT */ | 2420 | #endif /* CONFIG_FB_ATY_CT */ |
2391 | 2421 | ||
2392 | /* save previous video mode */ | 2422 | /* save previous video mode */ |
2393 | aty_get_crtc(par, &saved_crtc); | 2423 | aty_get_crtc(par, &par->saved_crtc); |
2394 | if(par->pll_ops->get_pll) | 2424 | if(par->pll_ops->get_pll) |
2395 | par->pll_ops->get_pll(info, &saved_pll); | 2425 | par->pll_ops->get_pll(info, &par->saved_pll); |
2396 | 2426 | ||
2397 | par->mem_cntl = aty_ld_le32(MEM_CNTL, par); | 2427 | par->mem_cntl = aty_ld_le32(MEM_CNTL, par); |
2398 | gtb_memsize = M64_HAS(GTB_DSP); | 2428 | gtb_memsize = M64_HAS(GTB_DSP); |
@@ -2667,8 +2697,8 @@ static int __devinit aty_init(struct fb_info *info) | |||
2667 | 2697 | ||
2668 | aty_init_exit: | 2698 | aty_init_exit: |
2669 | /* restore video mode */ | 2699 | /* restore video mode */ |
2670 | aty_set_crtc(par, &saved_crtc); | 2700 | aty_set_crtc(par, &par->saved_crtc); |
2671 | par->pll_ops->set_pll(info, &saved_pll); | 2701 | par->pll_ops->set_pll(info, &par->saved_pll); |
2672 | 2702 | ||
2673 | #ifdef CONFIG_MTRR | 2703 | #ifdef CONFIG_MTRR |
2674 | if (par->mtrr_reg >= 0) { | 2704 | if (par->mtrr_reg >= 0) { |
@@ -3502,6 +3532,11 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi | |||
3502 | par->mmap_map[1].prot_flag = _PAGE_E; | 3532 | par->mmap_map[1].prot_flag = _PAGE_E; |
3503 | #endif /* __sparc__ */ | 3533 | #endif /* __sparc__ */ |
3504 | 3534 | ||
3535 | mutex_lock(&reboot_lock); | ||
3536 | if (!reboot_info) | ||
3537 | reboot_info = info; | ||
3538 | mutex_unlock(&reboot_lock); | ||
3539 | |||
3505 | return 0; | 3540 | return 0; |
3506 | 3541 | ||
3507 | err_release_io: | 3542 | err_release_io: |
@@ -3614,8 +3649,8 @@ static void __devexit atyfb_remove(struct fb_info *info) | |||
3614 | struct atyfb_par *par = (struct atyfb_par *) info->par; | 3649 | struct atyfb_par *par = (struct atyfb_par *) info->par; |
3615 | 3650 | ||
3616 | /* restore video mode */ | 3651 | /* restore video mode */ |
3617 | aty_set_crtc(par, &saved_crtc); | 3652 | aty_set_crtc(par, &par->saved_crtc); |
3618 | par->pll_ops->set_pll(info, &saved_pll); | 3653 | par->pll_ops->set_pll(info, &par->saved_pll); |
3619 | 3654 | ||
3620 | unregister_framebuffer(info); | 3655 | unregister_framebuffer(info); |
3621 | 3656 | ||
@@ -3661,6 +3696,11 @@ static void __devexit atyfb_pci_remove(struct pci_dev *pdev) | |||
3661 | { | 3696 | { |
3662 | struct fb_info *info = pci_get_drvdata(pdev); | 3697 | struct fb_info *info = pci_get_drvdata(pdev); |
3663 | 3698 | ||
3699 | mutex_lock(&reboot_lock); | ||
3700 | if (reboot_info == info) | ||
3701 | reboot_info = NULL; | ||
3702 | mutex_unlock(&reboot_lock); | ||
3703 | |||
3664 | atyfb_remove(info); | 3704 | atyfb_remove(info); |
3665 | } | 3705 | } |
3666 | 3706 | ||
@@ -3808,6 +3848,56 @@ static int __init atyfb_setup(char *options) | |||
3808 | } | 3848 | } |
3809 | #endif /* MODULE */ | 3849 | #endif /* MODULE */ |
3810 | 3850 | ||
3851 | static int atyfb_reboot_notify(struct notifier_block *nb, | ||
3852 | unsigned long code, void *unused) | ||
3853 | { | ||
3854 | struct atyfb_par *par; | ||
3855 | |||
3856 | if (code != SYS_RESTART) | ||
3857 | return NOTIFY_DONE; | ||
3858 | |||
3859 | mutex_lock(&reboot_lock); | ||
3860 | |||
3861 | if (!reboot_info) | ||
3862 | goto out; | ||
3863 | |||
3864 | if (!lock_fb_info(reboot_info)) | ||
3865 | goto out; | ||
3866 | |||
3867 | par = reboot_info->par; | ||
3868 | |||
3869 | /* | ||
3870 | * HP OmniBook 500's BIOS doesn't like the state of the | ||
3871 | * hardware after atyfb has been used. Restore the hardware | ||
3872 | * to the original state to allow successful reboots. | ||
3873 | */ | ||
3874 | aty_set_crtc(par, &par->saved_crtc); | ||
3875 | par->pll_ops->set_pll(reboot_info, &par->saved_pll); | ||
3876 | |||
3877 | unlock_fb_info(reboot_info); | ||
3878 | out: | ||
3879 | mutex_unlock(&reboot_lock); | ||
3880 | |||
3881 | return NOTIFY_DONE; | ||
3882 | } | ||
3883 | |||
3884 | static struct notifier_block atyfb_reboot_notifier = { | ||
3885 | .notifier_call = atyfb_reboot_notify, | ||
3886 | }; | ||
3887 | |||
3888 | static const struct dmi_system_id atyfb_reboot_ids[] = { | ||
3889 | { | ||
3890 | .ident = "HP OmniBook 500", | ||
3891 | .matches = { | ||
3892 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
3893 | DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), | ||
3894 | DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 500 FA"), | ||
3895 | }, | ||
3896 | }, | ||
3897 | |||
3898 | { } | ||
3899 | }; | ||
3900 | |||
3811 | static int __init atyfb_init(void) | 3901 | static int __init atyfb_init(void) |
3812 | { | 3902 | { |
3813 | int err1 = 1, err2 = 1; | 3903 | int err1 = 1, err2 = 1; |
@@ -3826,11 +3916,20 @@ static int __init atyfb_init(void) | |||
3826 | err2 = atyfb_atari_probe(); | 3916 | err2 = atyfb_atari_probe(); |
3827 | #endif | 3917 | #endif |
3828 | 3918 | ||
3829 | return (err1 && err2) ? -ENODEV : 0; | 3919 | if (err1 && err2) |
3920 | return -ENODEV; | ||
3921 | |||
3922 | if (dmi_check_system(atyfb_reboot_ids)) | ||
3923 | register_reboot_notifier(&atyfb_reboot_notifier); | ||
3924 | |||
3925 | return 0; | ||
3830 | } | 3926 | } |
3831 | 3927 | ||
3832 | static void __exit atyfb_exit(void) | 3928 | static void __exit atyfb_exit(void) |
3833 | { | 3929 | { |
3930 | if (dmi_check_system(atyfb_reboot_ids)) | ||
3931 | unregister_reboot_notifier(&atyfb_reboot_notifier); | ||
3932 | |||
3834 | #ifdef CONFIG_PCI | 3933 | #ifdef CONFIG_PCI |
3835 | pci_unregister_driver(&atyfb_driver); | 3934 | pci_unregister_driver(&atyfb_driver); |
3836 | #endif | 3935 | #endif |
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c index 0cc9724e61a2..51fcc0a2c94a 100644 --- a/drivers/video/aty/mach64_accel.c +++ b/drivers/video/aty/mach64_accel.c | |||
@@ -63,14 +63,17 @@ static void reset_GTC_3D_engine(const struct atyfb_par *par) | |||
63 | void aty_init_engine(struct atyfb_par *par, struct fb_info *info) | 63 | void aty_init_engine(struct atyfb_par *par, struct fb_info *info) |
64 | { | 64 | { |
65 | u32 pitch_value; | 65 | u32 pitch_value; |
66 | u32 vxres; | ||
66 | 67 | ||
67 | /* determine modal information from global mode structure */ | 68 | /* determine modal information from global mode structure */ |
68 | pitch_value = info->var.xres_virtual; | 69 | pitch_value = info->fix.line_length / (info->var.bits_per_pixel / 8); |
70 | vxres = info->var.xres_virtual; | ||
69 | 71 | ||
70 | if (info->var.bits_per_pixel == 24) { | 72 | if (info->var.bits_per_pixel == 24) { |
71 | /* In 24 bpp, the engine is in 8 bpp - this requires that all */ | 73 | /* In 24 bpp, the engine is in 8 bpp - this requires that all */ |
72 | /* horizontal coordinates and widths must be adjusted */ | 74 | /* horizontal coordinates and widths must be adjusted */ |
73 | pitch_value *= 3; | 75 | pitch_value *= 3; |
76 | vxres *= 3; | ||
74 | } | 77 | } |
75 | 78 | ||
76 | /* On GTC (RagePro), we need to reset the 3D engine before */ | 79 | /* On GTC (RagePro), we need to reset the 3D engine before */ |
@@ -133,7 +136,7 @@ void aty_init_engine(struct atyfb_par *par, struct fb_info *info) | |||
133 | aty_st_le32(SC_LEFT, 0, par); | 136 | aty_st_le32(SC_LEFT, 0, par); |
134 | aty_st_le32(SC_TOP, 0, par); | 137 | aty_st_le32(SC_TOP, 0, par); |
135 | aty_st_le32(SC_BOTTOM, par->crtc.vyres - 1, par); | 138 | aty_st_le32(SC_BOTTOM, par->crtc.vyres - 1, par); |
136 | aty_st_le32(SC_RIGHT, pitch_value - 1, par); | 139 | aty_st_le32(SC_RIGHT, vxres - 1, par); |
137 | 140 | ||
138 | /* set background color to minimum value (usually BLACK) */ | 141 | /* set background color to minimum value (usually BLACK) */ |
139 | aty_st_le32(DP_BKGD_CLR, 0, par); | 142 | aty_st_le32(DP_BKGD_CLR, 0, par); |
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index 1dae7f8f3c6b..51422fc4f606 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c | |||
@@ -356,7 +356,7 @@ static int __devinit tdo24m_probe(struct spi_device *spi) | |||
356 | lcd->power = FB_BLANK_POWERDOWN; | 356 | lcd->power = FB_BLANK_POWERDOWN; |
357 | lcd->mode = MODE_VGA; /* default to VGA */ | 357 | lcd->mode = MODE_VGA; /* default to VGA */ |
358 | 358 | ||
359 | lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, sizeof(GFP_KERNEL)); | 359 | lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, GFP_KERNEL); |
360 | if (lcd->buf == NULL) { | 360 | if (lcd->buf == NULL) { |
361 | kfree(lcd); | 361 | kfree(lcd); |
362 | return -ENOMEM; | 362 | return -ENOMEM; |
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index 7bad24ed04ef..108b89e09a80 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Cobalt server LCD frame buffer driver. | 2 | * Cobalt server LCD frame buffer driver. |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index f8a09bf8d0cd..53ea05645ff8 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1310,8 +1310,6 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, | |||
1310 | 1310 | ||
1311 | static int | 1311 | static int |
1312 | fb_mmap(struct file *file, struct vm_area_struct * vma) | 1312 | fb_mmap(struct file *file, struct vm_area_struct * vma) |
1313 | __acquires(&info->lock) | ||
1314 | __releases(&info->lock) | ||
1315 | { | 1313 | { |
1316 | int fbidx = iminor(file->f_path.dentry->d_inode); | 1314 | int fbidx = iminor(file->f_path.dentry->d_inode); |
1317 | struct fb_info *info = registered_fb[fbidx]; | 1315 | struct fb_info *info = registered_fb[fbidx]; |
@@ -1325,16 +1323,14 @@ __releases(&info->lock) | |||
1325 | off = vma->vm_pgoff << PAGE_SHIFT; | 1323 | off = vma->vm_pgoff << PAGE_SHIFT; |
1326 | if (!fb) | 1324 | if (!fb) |
1327 | return -ENODEV; | 1325 | return -ENODEV; |
1326 | mutex_lock(&info->mm_lock); | ||
1328 | if (fb->fb_mmap) { | 1327 | if (fb->fb_mmap) { |
1329 | int res; | 1328 | int res; |
1330 | mutex_lock(&info->lock); | ||
1331 | res = fb->fb_mmap(info, vma); | 1329 | res = fb->fb_mmap(info, vma); |
1332 | mutex_unlock(&info->lock); | 1330 | mutex_unlock(&info->mm_lock); |
1333 | return res; | 1331 | return res; |
1334 | } | 1332 | } |
1335 | 1333 | ||
1336 | mutex_lock(&info->lock); | ||
1337 | |||
1338 | /* frame buffer memory */ | 1334 | /* frame buffer memory */ |
1339 | start = info->fix.smem_start; | 1335 | start = info->fix.smem_start; |
1340 | len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); | 1336 | len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); |
@@ -1342,13 +1338,13 @@ __releases(&info->lock) | |||
1342 | /* memory mapped io */ | 1338 | /* memory mapped io */ |
1343 | off -= len; | 1339 | off -= len; |
1344 | if (info->var.accel_flags) { | 1340 | if (info->var.accel_flags) { |
1345 | mutex_unlock(&info->lock); | 1341 | mutex_unlock(&info->mm_lock); |
1346 | return -EINVAL; | 1342 | return -EINVAL; |
1347 | } | 1343 | } |
1348 | start = info->fix.mmio_start; | 1344 | start = info->fix.mmio_start; |
1349 | len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); | 1345 | len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); |
1350 | } | 1346 | } |
1351 | mutex_unlock(&info->lock); | 1347 | mutex_unlock(&info->mm_lock); |
1352 | start &= PAGE_MASK; | 1348 | start &= PAGE_MASK; |
1353 | if ((vma->vm_end - vma->vm_start + off) > len) | 1349 | if ((vma->vm_end - vma->vm_start + off) > len) |
1354 | return -EINVAL; | 1350 | return -EINVAL; |
@@ -1518,6 +1514,7 @@ register_framebuffer(struct fb_info *fb_info) | |||
1518 | break; | 1514 | break; |
1519 | fb_info->node = i; | 1515 | fb_info->node = i; |
1520 | mutex_init(&fb_info->lock); | 1516 | mutex_init(&fb_info->lock); |
1517 | mutex_init(&fb_info->mm_lock); | ||
1521 | 1518 | ||
1522 | fb_info->dev = device_create(fb_class, fb_info->device, | 1519 | fb_info->dev = device_create(fb_class, fb_info->device, |
1523 | MKDEV(FB_MAJOR, i), NULL, "fb%d", i); | 1520 | MKDEV(FB_MAJOR, i), NULL, "fb%d", i); |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index f153c581cbd7..0bf2190928d0 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
@@ -750,24 +750,26 @@ static void update_lcdc(struct fb_info *info) | |||
750 | static int map_video_memory(struct fb_info *info) | 750 | static int map_video_memory(struct fb_info *info) |
751 | { | 751 | { |
752 | phys_addr_t phys; | 752 | phys_addr_t phys; |
753 | u32 smem_len = info->fix.line_length * info->var.yres_virtual; | ||
753 | 754 | ||
754 | pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual); | 755 | pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual); |
755 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); | 756 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); |
756 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); | 757 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); |
758 | pr_debug("MAP_VIDEO_MEMORY: smem_len = %u\n", smem_len); | ||
757 | 759 | ||
758 | info->fix.smem_len = info->fix.line_length * info->var.yres_virtual; | 760 | info->screen_base = fsl_diu_alloc(smem_len, &phys); |
759 | pr_debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->fix.smem_len); | ||
760 | info->screen_base = fsl_diu_alloc(info->fix.smem_len, &phys); | ||
761 | if (info->screen_base == NULL) { | 761 | if (info->screen_base == NULL) { |
762 | printk(KERN_ERR "Unable to allocate fb memory\n"); | 762 | printk(KERN_ERR "Unable to allocate fb memory\n"); |
763 | return -ENOMEM; | 763 | return -ENOMEM; |
764 | } | 764 | } |
765 | mutex_lock(&info->mm_lock); | ||
765 | info->fix.smem_start = (unsigned long) phys; | 766 | info->fix.smem_start = (unsigned long) phys; |
767 | info->fix.smem_len = smem_len; | ||
768 | mutex_unlock(&info->mm_lock); | ||
766 | info->screen_size = info->fix.smem_len; | 769 | info->screen_size = info->fix.smem_len; |
767 | 770 | ||
768 | pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n", | 771 | pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n", |
769 | info->fix.smem_start, | 772 | info->fix.smem_start, info->fix.smem_len); |
770 | info->fix.smem_len); | ||
771 | pr_debug("screen base %p\n", info->screen_base); | 773 | pr_debug("screen base %p\n", info->screen_base); |
772 | 774 | ||
773 | return 0; | 775 | return 0; |
@@ -776,9 +778,11 @@ static int map_video_memory(struct fb_info *info) | |||
776 | static void unmap_video_memory(struct fb_info *info) | 778 | static void unmap_video_memory(struct fb_info *info) |
777 | { | 779 | { |
778 | fsl_diu_free(info->screen_base, info->fix.smem_len); | 780 | fsl_diu_free(info->screen_base, info->fix.smem_len); |
781 | mutex_lock(&info->mm_lock); | ||
779 | info->screen_base = NULL; | 782 | info->screen_base = NULL; |
780 | info->fix.smem_start = 0; | 783 | info->fix.smem_start = 0; |
781 | info->fix.smem_len = 0; | 784 | info->fix.smem_len = 0; |
785 | mutex_unlock(&info->mm_lock); | ||
782 | } | 786 | } |
783 | 787 | ||
784 | /* | 788 | /* |
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 2e940199fc89..71960672d721 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c | |||
@@ -1090,8 +1090,10 @@ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) | |||
1090 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | 1090 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); |
1091 | 1091 | ||
1092 | strcpy(fix->id, "I810"); | 1092 | strcpy(fix->id, "I810"); |
1093 | mutex_lock(&info->mm_lock); | ||
1093 | fix->smem_start = par->fb.physical; | 1094 | fix->smem_start = par->fb.physical; |
1094 | fix->smem_len = par->fb.size; | 1095 | fix->smem_len = par->fb.size; |
1096 | mutex_unlock(&info->mm_lock); | ||
1095 | fix->type = FB_TYPE_PACKED_PIXELS; | 1097 | fix->type = FB_TYPE_PACKED_PIXELS; |
1096 | fix->type_aux = 0; | 1098 | fix->type_aux = 0; |
1097 | fix->xpanstep = 8; | 1099 | fix->xpanstep = 8; |
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 8e7a275df50c..59c3a2e14913 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c | |||
@@ -724,8 +724,10 @@ static void matroxfb_update_fix(WPMINFO2) | |||
724 | struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix; | 724 | struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix; |
725 | DBG(__func__) | 725 | DBG(__func__) |
726 | 726 | ||
727 | mutex_lock(&ACCESS_FBINFO(fbcon).mm_lock); | ||
727 | fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); | 728 | fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); |
728 | fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes); | 729 | fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes); |
730 | mutex_unlock(&ACCESS_FBINFO(fbcon).mm_lock); | ||
729 | } | 731 | } |
730 | 732 | ||
731 | static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | 733 | static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) |
@@ -2081,6 +2083,7 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm | |||
2081 | spin_lock_init(&ACCESS_FBINFO(lock.accel)); | 2083 | spin_lock_init(&ACCESS_FBINFO(lock.accel)); |
2082 | init_rwsem(&ACCESS_FBINFO(crtc2.lock)); | 2084 | init_rwsem(&ACCESS_FBINFO(crtc2.lock)); |
2083 | init_rwsem(&ACCESS_FBINFO(altout.lock)); | 2085 | init_rwsem(&ACCESS_FBINFO(altout.lock)); |
2086 | mutex_init(&ACCESS_FBINFO(fbcon).mm_lock); | ||
2084 | ACCESS_FBINFO(irq_flags) = 0; | 2087 | ACCESS_FBINFO(irq_flags) = 0; |
2085 | init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); | 2088 | init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); |
2086 | init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait)); | 2089 | init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait)); |
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 7ac4c5f6145d..909e10a11898 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c | |||
@@ -289,13 +289,16 @@ static int matroxfb_dh_release(struct fb_info* info, int user) { | |||
289 | #undef m2info | 289 | #undef m2info |
290 | } | 290 | } |
291 | 291 | ||
292 | static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) { | 292 | static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) |
293 | { | ||
293 | struct fb_fix_screeninfo *fix = &m2info->fbcon.fix; | 294 | struct fb_fix_screeninfo *fix = &m2info->fbcon.fix; |
294 | 295 | ||
295 | strcpy(fix->id, "MATROX DH"); | 296 | strcpy(fix->id, "MATROX DH"); |
296 | 297 | ||
298 | mutex_lock(&m2info->fbcon.mm_lock); | ||
297 | fix->smem_start = m2info->video.base; | 299 | fix->smem_start = m2info->video.base; |
298 | fix->smem_len = m2info->video.len_usable; | 300 | fix->smem_len = m2info->video.len_usable; |
301 | mutex_unlock(&m2info->fbcon.mm_lock); | ||
299 | fix->ypanstep = 1; | 302 | fix->ypanstep = 1; |
300 | fix->ywrapstep = 0; | 303 | fix->ywrapstep = 0; |
301 | fix->xpanstep = 8; /* TBD */ | 304 | fix->xpanstep = 8; /* TBD */ |
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index b7af5256e887..567fb944bd2a 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c | |||
@@ -669,7 +669,7 @@ static uint32_t bpp_to_pixfmt(int bpp) | |||
669 | } | 669 | } |
670 | 670 | ||
671 | static int mx3fb_blank(int blank, struct fb_info *fbi); | 671 | static int mx3fb_blank(int blank, struct fb_info *fbi); |
672 | static int mx3fb_map_video_memory(struct fb_info *fbi); | 672 | static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len); |
673 | static int mx3fb_unmap_video_memory(struct fb_info *fbi); | 673 | static int mx3fb_unmap_video_memory(struct fb_info *fbi); |
674 | 674 | ||
675 | /** | 675 | /** |
@@ -742,8 +742,7 @@ static int mx3fb_set_par(struct fb_info *fbi) | |||
742 | if (fbi->fix.smem_start) | 742 | if (fbi->fix.smem_start) |
743 | mx3fb_unmap_video_memory(fbi); | 743 | mx3fb_unmap_video_memory(fbi); |
744 | 744 | ||
745 | fbi->fix.smem_len = mem_len; | 745 | if (mx3fb_map_video_memory(fbi, mem_len) < 0) { |
746 | if (mx3fb_map_video_memory(fbi) < 0) { | ||
747 | mutex_unlock(&mx3_fbi->mutex); | 746 | mutex_unlock(&mx3_fbi->mutex); |
748 | return -ENOMEM; | 747 | return -ENOMEM; |
749 | } | 748 | } |
@@ -1198,6 +1197,7 @@ static int mx3fb_resume(struct platform_device *pdev) | |||
1198 | /** | 1197 | /** |
1199 | * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer. | 1198 | * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer. |
1200 | * @fbi: framebuffer information pointer | 1199 | * @fbi: framebuffer information pointer |
1200 | * @mem_len: length of mapped memory | ||
1201 | * @return: Error code indicating success or failure | 1201 | * @return: Error code indicating success or failure |
1202 | * | 1202 | * |
1203 | * This buffer is remapped into a non-cached, non-buffered, memory region to | 1203 | * This buffer is remapped into a non-cached, non-buffered, memory region to |
@@ -1205,23 +1205,26 @@ static int mx3fb_resume(struct platform_device *pdev) | |||
1205 | * area is remapped, all virtual memory access to the video memory should occur | 1205 | * area is remapped, all virtual memory access to the video memory should occur |
1206 | * at the new region. | 1206 | * at the new region. |
1207 | */ | 1207 | */ |
1208 | static int mx3fb_map_video_memory(struct fb_info *fbi) | 1208 | static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len) |
1209 | { | 1209 | { |
1210 | int retval = 0; | 1210 | int retval = 0; |
1211 | dma_addr_t addr; | 1211 | dma_addr_t addr; |
1212 | 1212 | ||
1213 | fbi->screen_base = dma_alloc_writecombine(fbi->device, | 1213 | fbi->screen_base = dma_alloc_writecombine(fbi->device, |
1214 | fbi->fix.smem_len, | 1214 | mem_len, |
1215 | &addr, GFP_DMA); | 1215 | &addr, GFP_DMA); |
1216 | 1216 | ||
1217 | if (!fbi->screen_base) { | 1217 | if (!fbi->screen_base) { |
1218 | dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n", | 1218 | dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n", |
1219 | fbi->fix.smem_len); | 1219 | mem_len); |
1220 | retval = -EBUSY; | 1220 | retval = -EBUSY; |
1221 | goto err0; | 1221 | goto err0; |
1222 | } | 1222 | } |
1223 | 1223 | ||
1224 | mutex_lock(&fbi->mm_lock); | ||
1224 | fbi->fix.smem_start = addr; | 1225 | fbi->fix.smem_start = addr; |
1226 | fbi->fix.smem_len = mem_len; | ||
1227 | mutex_unlock(&fbi->mm_lock); | ||
1225 | 1228 | ||
1226 | dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n", | 1229 | dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n", |
1227 | (uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len); | 1230 | (uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len); |
@@ -1251,8 +1254,10 @@ static int mx3fb_unmap_video_memory(struct fb_info *fbi) | |||
1251 | fbi->screen_base, fbi->fix.smem_start); | 1254 | fbi->screen_base, fbi->fix.smem_start); |
1252 | 1255 | ||
1253 | fbi->screen_base = 0; | 1256 | fbi->screen_base = 0; |
1257 | mutex_lock(&fbi->mm_lock); | ||
1254 | fbi->fix.smem_start = 0; | 1258 | fbi->fix.smem_start = 0; |
1255 | fbi->fix.smem_len = 0; | 1259 | fbi->fix.smem_len = 0; |
1260 | mutex_unlock(&fbi->mm_lock); | ||
1256 | return 0; | 1261 | return 0; |
1257 | } | 1262 | } |
1258 | 1263 | ||
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 060d72fe57cb..4ea99bfc37b4 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c | |||
@@ -393,8 +393,10 @@ static void set_fb_fix(struct fb_info *fbi) | |||
393 | 393 | ||
394 | rg = &plane->fbdev->mem_desc.region[plane->idx]; | 394 | rg = &plane->fbdev->mem_desc.region[plane->idx]; |
395 | fbi->screen_base = rg->vaddr; | 395 | fbi->screen_base = rg->vaddr; |
396 | mutex_lock(&fbi->mm_lock); | ||
396 | fix->smem_start = rg->paddr; | 397 | fix->smem_start = rg->paddr; |
397 | fix->smem_len = rg->size; | 398 | fix->smem_len = rg->size; |
399 | mutex_unlock(&fbi->mm_lock); | ||
398 | 400 | ||
399 | fix->type = FB_TYPE_PACKED_PIXELS; | 401 | fix->type = FB_TYPE_PACKED_PIXELS; |
400 | bpp = var->bits_per_pixel; | 402 | bpp = var->bits_per_pixel; |
@@ -886,8 +888,10 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
886 | * plane memory is dealloce'd, the other | 888 | * plane memory is dealloce'd, the other |
887 | * screen parameters in var / fix are invalid. | 889 | * screen parameters in var / fix are invalid. |
888 | */ | 890 | */ |
891 | mutex_lock(&fbi->mm_lock); | ||
889 | fbi->fix.smem_start = 0; | 892 | fbi->fix.smem_start = 0; |
890 | fbi->fix.smem_len = 0; | 893 | fbi->fix.smem_len = 0; |
894 | mutex_unlock(&fbi->mm_lock); | ||
891 | } | 895 | } |
892 | } | 896 | } |
893 | } | 897 | } |
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 03b3670130a0..bacfabd9ce16 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c | |||
@@ -141,7 +141,9 @@ static int platinumfb_set_par (struct fb_info *info) | |||
141 | offset = 0x10; | 141 | offset = 0x10; |
142 | 142 | ||
143 | info->screen_base = pinfo->frame_buffer + init->fb_offset + offset; | 143 | info->screen_base = pinfo->frame_buffer + init->fb_offset + offset; |
144 | mutex_lock(&info->mm_lock); | ||
144 | info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset; | 145 | info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset; |
146 | mutex_unlock(&info->mm_lock); | ||
145 | info->fix.visual = (pinfo->cmode == CMODE_8) ? | 147 | info->fix.visual = (pinfo->cmode == CMODE_8) ? |
146 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; | 148 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; |
147 | info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) | 149 | info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) |
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 0889d50c3288..6506117c134b 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
@@ -815,8 +815,10 @@ static int overlayfb_map_video_memory(struct pxafb_layer *ofb) | |||
815 | ofb->video_mem_phys = virt_to_phys(ofb->video_mem); | 815 | ofb->video_mem_phys = virt_to_phys(ofb->video_mem); |
816 | ofb->video_mem_size = size; | 816 | ofb->video_mem_size = size; |
817 | 817 | ||
818 | mutex_lock(&ofb->fb.mm_lock); | ||
818 | ofb->fb.fix.smem_start = ofb->video_mem_phys; | 819 | ofb->fb.fix.smem_start = ofb->video_mem_phys; |
819 | ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual; | 820 | ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual; |
821 | mutex_unlock(&ofb->fb.mm_lock); | ||
820 | ofb->fb.screen_base = ofb->video_mem; | 822 | ofb->fb.screen_base = ofb->video_mem; |
821 | return 0; | 823 | return 0; |
822 | } | 824 | } |
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c index 653bdfee3057..9f6d6e61f0cc 100644 --- a/drivers/video/sh7760fb.c +++ b/drivers/video/sh7760fb.c | |||
@@ -120,18 +120,6 @@ static int sh7760_setcolreg (u_int regno, | |||
120 | return 0; | 120 | return 0; |
121 | } | 121 | } |
122 | 122 | ||
123 | static void encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info, | ||
124 | unsigned long stride) | ||
125 | { | ||
126 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | ||
127 | strcpy(fix->id, "sh7760-lcdc"); | ||
128 | |||
129 | fix->smem_start = (unsigned long)info->screen_base; | ||
130 | fix->smem_len = info->screen_size; | ||
131 | |||
132 | fix->line_length = stride; | ||
133 | } | ||
134 | |||
135 | static int sh7760fb_get_color_info(struct device *dev, | 123 | static int sh7760fb_get_color_info(struct device *dev, |
136 | u16 lddfr, int *bpp, int *gray) | 124 | u16 lddfr, int *bpp, int *gray) |
137 | { | 125 | { |
@@ -334,7 +322,8 @@ static int sh7760fb_set_par(struct fb_info *info) | |||
334 | 322 | ||
335 | iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */ | 323 | iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */ |
336 | 324 | ||
337 | encode_fix(&info->fix, info, stride); | 325 | info->fix.line_length = stride; |
326 | |||
338 | sh7760fb_check_var(&info->var, info); | 327 | sh7760fb_check_var(&info->var, info); |
339 | 328 | ||
340 | sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */ | 329 | sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */ |
@@ -435,6 +424,8 @@ static int sh7760fb_alloc_mem(struct fb_info *info) | |||
435 | 424 | ||
436 | info->screen_base = fbmem; | 425 | info->screen_base = fbmem; |
437 | info->screen_size = vram; | 426 | info->screen_size = vram; |
427 | info->fix.smem_start = (unsigned long)info->screen_base; | ||
428 | info->fix.smem_len = info->screen_size; | ||
438 | 429 | ||
439 | return 0; | 430 | return 0; |
440 | } | 431 | } |
@@ -520,6 +511,8 @@ static int __devinit sh7760fb_probe(struct platform_device *pdev) | |||
520 | info->var.transp.length = 0; | 511 | info->var.transp.length = 0; |
521 | info->var.transp.msb_right = 0; | 512 | info->var.transp.msb_right = 0; |
522 | 513 | ||
514 | strcpy(info->fix.id, "sh7760-lcdc"); | ||
515 | |||
523 | /* set the DON2 bit now, before cmap allocation, as it will randomize | 516 | /* set the DON2 bit now, before cmap allocation, as it will randomize |
524 | * palette memory. | 517 | * palette memory. |
525 | */ | 518 | */ |
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index f10d2fbeda06..da983b720f08 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/vmalloc.h> | ||
20 | #include <video/sh_mobile_lcdc.h> | 21 | #include <video/sh_mobile_lcdc.h> |
21 | #include <asm/atomic.h> | 22 | #include <asm/atomic.h> |
22 | 23 | ||
@@ -33,6 +34,7 @@ struct sh_mobile_lcdc_chan { | |||
33 | struct fb_info info; | 34 | struct fb_info info; |
34 | dma_addr_t dma_handle; | 35 | dma_addr_t dma_handle; |
35 | struct fb_deferred_io defio; | 36 | struct fb_deferred_io defio; |
37 | struct scatterlist *sglist; | ||
36 | unsigned long frame_end; | 38 | unsigned long frame_end; |
37 | wait_queue_head_t frame_end_wait; | 39 | wait_queue_head_t frame_end_wait; |
38 | }; | 40 | }; |
@@ -206,16 +208,38 @@ static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) {} | |||
206 | static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {} | 208 | static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {} |
207 | #endif | 209 | #endif |
208 | 210 | ||
211 | static int sh_mobile_lcdc_sginit(struct fb_info *info, | ||
212 | struct list_head *pagelist) | ||
213 | { | ||
214 | struct sh_mobile_lcdc_chan *ch = info->par; | ||
215 | unsigned int nr_pages_max = info->fix.smem_len >> PAGE_SHIFT; | ||
216 | struct page *page; | ||
217 | int nr_pages = 0; | ||
218 | |||
219 | sg_init_table(ch->sglist, nr_pages_max); | ||
220 | |||
221 | list_for_each_entry(page, pagelist, lru) | ||
222 | sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0); | ||
223 | |||
224 | return nr_pages; | ||
225 | } | ||
226 | |||
209 | static void sh_mobile_lcdc_deferred_io(struct fb_info *info, | 227 | static void sh_mobile_lcdc_deferred_io(struct fb_info *info, |
210 | struct list_head *pagelist) | 228 | struct list_head *pagelist) |
211 | { | 229 | { |
212 | struct sh_mobile_lcdc_chan *ch = info->par; | 230 | struct sh_mobile_lcdc_chan *ch = info->par; |
231 | unsigned int nr_pages; | ||
213 | 232 | ||
214 | /* enable clocks before accessing hardware */ | 233 | /* enable clocks before accessing hardware */ |
215 | sh_mobile_lcdc_clk_on(ch->lcdc); | 234 | sh_mobile_lcdc_clk_on(ch->lcdc); |
216 | 235 | ||
236 | nr_pages = sh_mobile_lcdc_sginit(info, pagelist); | ||
237 | dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); | ||
238 | |||
217 | /* trigger panel update */ | 239 | /* trigger panel update */ |
218 | lcdc_write_chan(ch, LDSM2R, 1); | 240 | lcdc_write_chan(ch, LDSM2R, 1); |
241 | |||
242 | dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); | ||
219 | } | 243 | } |
220 | 244 | ||
221 | static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) | 245 | static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) |
@@ -846,21 +870,31 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
846 | } | 870 | } |
847 | 871 | ||
848 | for (i = 0; i < j; i++) { | 872 | for (i = 0; i < j; i++) { |
849 | error = register_framebuffer(&priv->ch[i].info); | 873 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; |
874 | |||
875 | info = &ch->info; | ||
876 | |||
877 | if (info->fbdefio) { | ||
878 | priv->ch->sglist = vmalloc(sizeof(struct scatterlist) * | ||
879 | info->fix.smem_len >> PAGE_SHIFT); | ||
880 | if (!priv->ch->sglist) { | ||
881 | dev_err(&pdev->dev, "cannot allocate sglist\n"); | ||
882 | goto err1; | ||
883 | } | ||
884 | } | ||
885 | |||
886 | error = register_framebuffer(info); | ||
850 | if (error < 0) | 887 | if (error < 0) |
851 | goto err1; | 888 | goto err1; |
852 | } | ||
853 | 889 | ||
854 | for (i = 0; i < j; i++) { | ||
855 | info = &priv->ch[i].info; | ||
856 | dev_info(info->dev, | 890 | dev_info(info->dev, |
857 | "registered %s/%s as %dx%d %dbpp.\n", | 891 | "registered %s/%s as %dx%d %dbpp.\n", |
858 | pdev->name, | 892 | pdev->name, |
859 | (priv->ch[i].cfg.chan == LCDC_CHAN_MAINLCD) ? | 893 | (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? |
860 | "mainlcd" : "sublcd", | 894 | "mainlcd" : "sublcd", |
861 | (int) priv->ch[i].cfg.lcd_cfg.xres, | 895 | (int) ch->cfg.lcd_cfg.xres, |
862 | (int) priv->ch[i].cfg.lcd_cfg.yres, | 896 | (int) ch->cfg.lcd_cfg.yres, |
863 | priv->ch[i].cfg.bpp); | 897 | ch->cfg.bpp); |
864 | 898 | ||
865 | /* deferred io mode: disable clock to save power */ | 899 | /* deferred io mode: disable clock to save power */ |
866 | if (info->fbdefio) | 900 | if (info->fbdefio) |
@@ -892,6 +926,9 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) | |||
892 | if (!info->device) | 926 | if (!info->device) |
893 | continue; | 927 | continue; |
894 | 928 | ||
929 | if (priv->ch[i].sglist) | ||
930 | vfree(priv->ch[i].sglist); | ||
931 | |||
895 | dma_free_coherent(&pdev->dev, info->fix.smem_len, | 932 | dma_free_coherent(&pdev->dev, info->fix.smem_len, |
896 | info->screen_base, priv->ch[i].dma_handle); | 933 | info->screen_base, priv->ch[i].dma_handle); |
897 | fb_dealloc_cmap(&info->cmap); | 934 | fb_dealloc_cmap(&info->cmap); |
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 7072d19080d5..fd33455389b8 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
@@ -1847,8 +1847,10 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) | |||
1847 | 1847 | ||
1848 | strcpy(fix->id, ivideo->myid); | 1848 | strcpy(fix->id, ivideo->myid); |
1849 | 1849 | ||
1850 | mutex_lock(&info->mm_lock); | ||
1850 | fix->smem_start = ivideo->video_base + ivideo->video_offset; | 1851 | fix->smem_start = ivideo->video_base + ivideo->video_offset; |
1851 | fix->smem_len = ivideo->sisfb_mem; | 1852 | fix->smem_len = ivideo->sisfb_mem; |
1853 | mutex_unlock(&info->mm_lock); | ||
1852 | fix->type = FB_TYPE_PACKED_PIXELS; | 1854 | fix->type = FB_TYPE_PACKED_PIXELS; |
1853 | fix->type_aux = 0; | 1855 | fix->type_aux = 0; |
1854 | fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | 1856 | fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; |
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index eb5d73a06702..16d4f4c7d52b 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
@@ -145,7 +145,7 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info) | |||
145 | #define SM501_MEMF_ACCEL (8) | 145 | #define SM501_MEMF_ACCEL (8) |
146 | 146 | ||
147 | static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, | 147 | static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, |
148 | unsigned int why, size_t size) | 148 | unsigned int why, size_t size, u32 smem_len) |
149 | { | 149 | { |
150 | struct sm501fb_par *par; | 150 | struct sm501fb_par *par; |
151 | struct fb_info *fbi; | 151 | struct fb_info *fbi; |
@@ -172,7 +172,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, | |||
172 | if (ptr > 0) | 172 | if (ptr > 0) |
173 | ptr &= ~(PAGE_SIZE - 1); | 173 | ptr &= ~(PAGE_SIZE - 1); |
174 | 174 | ||
175 | if (fbi && ptr < fbi->fix.smem_len) | 175 | if (fbi && ptr < smem_len) |
176 | return -ENOMEM; | 176 | return -ENOMEM; |
177 | 177 | ||
178 | break; | 178 | break; |
@@ -197,7 +197,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, | |||
197 | 197 | ||
198 | case SM501_MEMF_ACCEL: | 198 | case SM501_MEMF_ACCEL: |
199 | fbi = inf->fb[HEAD_CRT]; | 199 | fbi = inf->fb[HEAD_CRT]; |
200 | ptr = fbi ? fbi->fix.smem_len : 0; | 200 | ptr = fbi ? smem_len : 0; |
201 | 201 | ||
202 | fbi = inf->fb[HEAD_PANEL]; | 202 | fbi = inf->fb[HEAD_PANEL]; |
203 | if (fbi) { | 203 | if (fbi) { |
@@ -413,6 +413,7 @@ static int sm501fb_set_par_common(struct fb_info *info, | |||
413 | unsigned int mem_type; | 413 | unsigned int mem_type; |
414 | unsigned int clock_type; | 414 | unsigned int clock_type; |
415 | unsigned int head_addr; | 415 | unsigned int head_addr; |
416 | unsigned int smem_len; | ||
416 | 417 | ||
417 | dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n", | 418 | dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n", |
418 | __func__, var->xres, var->yres, var->bits_per_pixel, | 419 | __func__, var->xres, var->yres, var->bits_per_pixel, |
@@ -453,18 +454,20 @@ static int sm501fb_set_par_common(struct fb_info *info, | |||
453 | 454 | ||
454 | /* allocate fb memory within 501 */ | 455 | /* allocate fb memory within 501 */ |
455 | info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8; | 456 | info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8; |
456 | info->fix.smem_len = info->fix.line_length * var->yres_virtual; | 457 | smem_len = info->fix.line_length * var->yres_virtual; |
457 | 458 | ||
458 | dev_dbg(fbi->dev, "%s: line length = %u\n", __func__, | 459 | dev_dbg(fbi->dev, "%s: line length = %u\n", __func__, |
459 | info->fix.line_length); | 460 | info->fix.line_length); |
460 | 461 | ||
461 | if (sm501_alloc_mem(fbi, &par->screen, mem_type, | 462 | if (sm501_alloc_mem(fbi, &par->screen, mem_type, smem_len, smem_len)) { |
462 | info->fix.smem_len)) { | ||
463 | dev_err(fbi->dev, "no memory available\n"); | 463 | dev_err(fbi->dev, "no memory available\n"); |
464 | return -ENOMEM; | 464 | return -ENOMEM; |
465 | } | 465 | } |
466 | 466 | ||
467 | mutex_lock(&info->mm_lock); | ||
467 | info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr; | 468 | info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr; |
469 | info->fix.smem_len = smem_len; | ||
470 | mutex_unlock(&info->mm_lock); | ||
468 | 471 | ||
469 | info->screen_base = fbi->fbmem + par->screen.sm_addr; | 472 | info->screen_base = fbi->fbmem + par->screen.sm_addr; |
470 | info->screen_size = info->fix.smem_len; | 473 | info->screen_size = info->fix.smem_len; |
@@ -637,7 +640,8 @@ static int sm501fb_set_par_crt(struct fb_info *info) | |||
637 | if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) { | 640 | if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) { |
638 | /* the head is displaying panel data... */ | 641 | /* the head is displaying panel data... */ |
639 | 642 | ||
640 | sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0); | 643 | sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0, |
644 | info->fix.smem_len); | ||
641 | goto out_update; | 645 | goto out_update; |
642 | } | 646 | } |
643 | 647 | ||
@@ -1289,7 +1293,8 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) | |||
1289 | 1293 | ||
1290 | par->cursor_regs = info->regs + reg_base; | 1294 | par->cursor_regs = info->regs + reg_base; |
1291 | 1295 | ||
1292 | ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024); | 1296 | ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024, |
1297 | fbi->fix.smem_len); | ||
1293 | if (ret < 0) | 1298 | if (ret < 0) |
1294 | return ret; | 1299 | return ret; |
1295 | 1300 | ||
@@ -1619,6 +1624,8 @@ static int __devinit sm501fb_start_one(struct sm501fb_info *info, | |||
1619 | if (!fbi) | 1624 | if (!fbi) |
1620 | return 0; | 1625 | return 0; |
1621 | 1626 | ||
1627 | mutex_init(&info->fb[head]->mm_lock); | ||
1628 | |||
1622 | ret = sm501fb_init_fb(info->fb[head], head, drvname); | 1629 | ret = sm501fb_init_fb(info->fb[head], head, drvname); |
1623 | if (ret) { | 1630 | if (ret) { |
1624 | dev_err(info->dev, "cannot initialise fb %s\n", drvname); | 1631 | dev_err(info->dev, "cannot initialise fb %s\n", drvname); |
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index d0674f1e3f10..8a141c2c637b 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c | |||
@@ -523,6 +523,7 @@ static int w100fb_set_par(struct fb_info *info) | |||
523 | info->fix.ywrapstep = 0; | 523 | info->fix.ywrapstep = 0; |
524 | info->fix.line_length = par->xres * BITS_PER_PIXEL / 8; | 524 | info->fix.line_length = par->xres * BITS_PER_PIXEL / 8; |
525 | 525 | ||
526 | mutex_lock(&info->mm_lock); | ||
526 | if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) { | 527 | if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) { |
527 | par->extmem_active = 1; | 528 | par->extmem_active = 1; |
528 | info->fix.smem_len = par->mach->mem->size+1; | 529 | info->fix.smem_len = par->mach->mem->size+1; |
@@ -530,6 +531,7 @@ static int w100fb_set_par(struct fb_info *info) | |||
530 | par->extmem_active = 0; | 531 | par->extmem_active = 0; |
531 | info->fix.smem_len = MEM_INT_SIZE+1; | 532 | info->fix.smem_len = MEM_INT_SIZE+1; |
532 | } | 533 | } |
534 | mutex_unlock(&info->mm_lock); | ||
533 | 535 | ||
534 | w100fb_activate_var(par); | 536 | w100fb_activate_var(par); |
535 | } | 537 | } |
diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c index a4fe7a38d9b0..3bde56bce63a 100644 --- a/drivers/watchdog/wdrtas.c +++ b/drivers/watchdog/wdrtas.c | |||
@@ -218,16 +218,14 @@ static void wdrtas_timer_keepalive(void) | |||
218 | */ | 218 | */ |
219 | static int wdrtas_get_temperature(void) | 219 | static int wdrtas_get_temperature(void) |
220 | { | 220 | { |
221 | long result; | 221 | int result; |
222 | int temperature = 0; | 222 | int temperature = 0; |
223 | 223 | ||
224 | result = rtas_call(wdrtas_token_get_sensor_state, 2, 2, | 224 | result = rtas_get_sensor(WDRTAS_THERMAL_SENSOR, 0, &temperature); |
225 | (void *)__pa(&temperature), | ||
226 | WDRTAS_THERMAL_SENSOR, 0); | ||
227 | 225 | ||
228 | if (result < 0) | 226 | if (result < 0) |
229 | printk(KERN_WARNING "wdrtas: reading the thermal sensor " | 227 | printk(KERN_WARNING "wdrtas: reading the thermal sensor " |
230 | "faild: %li\n", result); | 228 | "failed: %i\n", result); |
231 | else | 229 | else |
232 | temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */ | 230 | temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */ |
233 | 231 | ||