diff options
277 files changed, 10850 insertions, 1545 deletions
@@ -1097,7 +1097,7 @@ S: 80050-430 - Curitiba - Paraná | |||
1097 | S: Brazil | 1097 | S: Brazil |
1098 | 1098 | ||
1099 | N: Kumar Gala | 1099 | N: Kumar Gala |
1100 | E: kumar.gala@freescale.com | 1100 | E: galak@kernel.crashing.org |
1101 | D: Embedded PowerPC 6xx/7xx/74xx/82xx/83xx/85xx support | 1101 | D: Embedded PowerPC 6xx/7xx/74xx/82xx/83xx/85xx support |
1102 | S: Austin, Texas 78729 | 1102 | S: Austin, Texas 78729 |
1103 | S: USA | 1103 | S: USA |
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 7018f5c6a447..1c955883cf58 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile | |||
@@ -20,6 +20,12 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ | |||
20 | # +--> DIR=file (htmldocs) | 20 | # +--> DIR=file (htmldocs) |
21 | # +--> man/ (mandocs) | 21 | # +--> man/ (mandocs) |
22 | 22 | ||
23 | |||
24 | # for PDF and PS output you can choose between xmlto and docbook-utils tools | ||
25 | PDF_METHOD = $(prefer-db2x) | ||
26 | PS_METHOD = $(prefer-db2x) | ||
27 | |||
28 | |||
23 | ### | 29 | ### |
24 | # The targets that may be used. | 30 | # The targets that may be used. |
25 | .PHONY: xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs | 31 | .PHONY: xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs |
@@ -93,27 +99,39 @@ C-procfs-example = procfs_example.xml | |||
93 | C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example)) | 99 | C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example)) |
94 | $(obj)/procfs-guide.xml: $(C-procfs-example2) | 100 | $(obj)/procfs-guide.xml: $(C-procfs-example2) |
95 | 101 | ||
96 | ### | 102 | notfoundtemplate = echo "*** You have to install docbook-utils or xmlto ***"; \ |
97 | # Rules to generate postscript, PDF and HTML | 103 | exit 1 |
98 | # db2html creates a directory. Generate a html file used for timestamp | 104 | db2xtemplate = db2TYPE -o $(dir $@) $< |
105 | xmltotemplate = xmlto TYPE $(XMLTOFLAGS) -o $(dir $@) $< | ||
106 | |||
107 | # determine which methods are available | ||
108 | ifeq ($(shell which db2ps >/dev/null 2>&1 && echo found),found) | ||
109 | use-db2x = db2x | ||
110 | prefer-db2x = db2x | ||
111 | else | ||
112 | use-db2x = notfound | ||
113 | prefer-db2x = $(use-xmlto) | ||
114 | endif | ||
115 | ifeq ($(shell which xmlto >/dev/null 2>&1 && echo found),found) | ||
116 | use-xmlto = xmlto | ||
117 | prefer-xmlto = xmlto | ||
118 | else | ||
119 | use-xmlto = notfound | ||
120 | prefer-xmlto = $(use-db2x) | ||
121 | endif | ||
99 | 122 | ||
100 | quiet_cmd_db2ps = XMLTO $@ | 123 | # the commands, generated from the chosen template |
101 | cmd_db2ps = xmlto ps $(XMLTOFLAGS) -o $(dir $@) $< | 124 | quiet_cmd_db2ps = PS $@ |
125 | cmd_db2ps = $(subst TYPE,ps, $($(PS_METHOD)template)) | ||
102 | %.ps : %.xml | 126 | %.ps : %.xml |
103 | @(which xmlto > /dev/null 2>&1) || \ | ||
104 | (echo "*** You need to install xmlto ***"; \ | ||
105 | exit 1) | ||
106 | $(call cmd,db2ps) | 127 | $(call cmd,db2ps) |
107 | 128 | ||
108 | quiet_cmd_db2pdf = XMLTO $@ | 129 | quiet_cmd_db2pdf = PDF $@ |
109 | cmd_db2pdf = xmlto pdf $(XMLTOFLAGS) -o $(dir $@) $< | 130 | cmd_db2pdf = $(subst TYPE,pdf, $($(PDF_METHOD)template)) |
110 | %.pdf : %.xml | 131 | %.pdf : %.xml |
111 | @(which xmlto > /dev/null 2>&1) || \ | ||
112 | (echo "*** You need to install xmlto ***"; \ | ||
113 | exit 1) | ||
114 | $(call cmd,db2pdf) | 132 | $(call cmd,db2pdf) |
115 | 133 | ||
116 | quiet_cmd_db2html = XMLTO $@ | 134 | quiet_cmd_db2html = HTML $@ |
117 | cmd_db2html = xmlto xhtml $(XMLTOFLAGS) -o $(patsubst %.html,%,$@) $< && \ | 135 | cmd_db2html = xmlto xhtml $(XMLTOFLAGS) -o $(patsubst %.html,%,$@) $< && \ |
118 | echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/index.html"> \ | 136 | echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/index.html"> \ |
119 | Goto $(patsubst %.html,%,$(notdir $@))</a><p>' > $@ | 137 | Goto $(patsubst %.html,%,$(notdir $@))</a><p>' > $@ |
@@ -127,7 +145,7 @@ quiet_cmd_db2html = XMLTO $@ | |||
127 | @if [ ! -z "$(PNG-$(basename $(notdir $@)))" ]; then \ | 145 | @if [ ! -z "$(PNG-$(basename $(notdir $@)))" ]; then \ |
128 | cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi | 146 | cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi |
129 | 147 | ||
130 | quiet_cmd_db2man = XMLTO $@ | 148 | quiet_cmd_db2man = MAN $@ |
131 | cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man $< ; gzip -f $(obj)/man/*.9; fi | 149 | cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man $< ; gzip -f $(obj)/man/*.9; fi |
132 | %.9 : %.xml | 150 | %.9 : %.xml |
133 | @(which xmlto > /dev/null 2>&1) || \ | 151 | @(which xmlto > /dev/null 2>&1) || \ |
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index a8316b1a3e3d..0519c9dc0065 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl | |||
@@ -68,9 +68,7 @@ X!Iinclude/linux/kobject.h | |||
68 | 68 | ||
69 | <sect1><title>Kernel utility functions</title> | 69 | <sect1><title>Kernel utility functions</title> |
70 | !Iinclude/linux/kernel.h | 70 | !Iinclude/linux/kernel.h |
71 | <!-- This needs to clean up to make kernel-doc happy | 71 | !Ekernel/printk.c |
72 | X!Ekernel/printk.c | ||
73 | --> | ||
74 | !Ekernel/panic.c | 72 | !Ekernel/panic.c |
75 | !Ekernel/sys.c | 73 | !Ekernel/sys.c |
76 | !Ekernel/rcupdate.c | 74 | !Ekernel/rcupdate.c |
diff --git a/Documentation/DocBook/stylesheet.xsl b/Documentation/DocBook/stylesheet.xsl index 64be9f7ee3bb..3ccce886c349 100644 --- a/Documentation/DocBook/stylesheet.xsl +++ b/Documentation/DocBook/stylesheet.xsl | |||
@@ -3,4 +3,5 @@ | |||
3 | <param name="chunk.quietly">1</param> | 3 | <param name="chunk.quietly">1</param> |
4 | <param name="funcsynopsis.style">ansi</param> | 4 | <param name="funcsynopsis.style">ansi</param> |
5 | <param name="funcsynopsis.tabular.threshold">80</param> | 5 | <param name="funcsynopsis.tabular.threshold">80</param> |
6 | <!-- <param name="paper.type">A4</param> --> | ||
6 | </stylesheet> | 7 | </stylesheet> |
diff --git a/Documentation/atomic_ops.txt b/Documentation/atomic_ops.txt index 8eedaa24f5e2..23a1c2402bcc 100644 --- a/Documentation/atomic_ops.txt +++ b/Documentation/atomic_ops.txt | |||
@@ -115,6 +115,33 @@ boolean is return which indicates whether the resulting counter value | |||
115 | is negative. It requires explicit memory barrier semantics around the | 115 | is negative. It requires explicit memory barrier semantics around the |
116 | operation. | 116 | operation. |
117 | 117 | ||
118 | Then: | ||
119 | |||
120 | int atomic_cmpxchg(atomic_t *v, int old, int new); | ||
121 | |||
122 | This performs an atomic compare exchange operation on the atomic value v, | ||
123 | with the given old and new values. Like all atomic_xxx operations, | ||
124 | atomic_cmpxchg will only satisfy its atomicity semantics as long as all | ||
125 | other accesses of *v are performed through atomic_xxx operations. | ||
126 | |||
127 | atomic_cmpxchg requires explicit memory barriers around the operation. | ||
128 | |||
129 | The semantics for atomic_cmpxchg are the same as those defined for 'cas' | ||
130 | below. | ||
131 | |||
132 | Finally: | ||
133 | |||
134 | int atomic_add_unless(atomic_t *v, int a, int u); | ||
135 | |||
136 | If the atomic value v is not equal to u, this function adds a to v, and | ||
137 | returns non zero. If v is equal to u then it returns zero. This is done as | ||
138 | an atomic operation. | ||
139 | |||
140 | atomic_add_unless requires explicit memory barriers around the operation. | ||
141 | |||
142 | atomic_inc_not_zero, equivalent to atomic_add_unless(v, 1, 0) | ||
143 | |||
144 | |||
118 | If a caller requires memory barrier semantics around an atomic_t | 145 | If a caller requires memory barrier semantics around an atomic_t |
119 | operation which does not return a value, a set of interfaces are | 146 | operation which does not return a value, a set of interfaces are |
120 | defined which accomplish this: | 147 | defined which accomplish this: |
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt index c563842ed805..9f30ac6ca47b 100644 --- a/Documentation/oops-tracing.txt +++ b/Documentation/oops-tracing.txt | |||
@@ -30,7 +30,9 @@ the disk is not available then you have three options :- | |||
30 | 30 | ||
31 | (1) Hand copy the text from the screen and type it in after the machine | 31 | (1) Hand copy the text from the screen and type it in after the machine |
32 | has restarted. Messy but it is the only option if you have not | 32 | has restarted. Messy but it is the only option if you have not |
33 | planned for a crash. | 33 | planned for a crash. Alternatively, you can take a picture of |
34 | the screen with a digital camera - not nice, but better than | ||
35 | nothing. | ||
34 | 36 | ||
35 | (2) Boot with a serial console (see Documentation/serial-console.txt), | 37 | (2) Boot with a serial console (see Documentation/serial-console.txt), |
36 | run a null modem to a second machine and capture the output there | 38 | run a null modem to a second machine and capture the output there |
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 2404099996ac..330246ac80f8 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv | |||
@@ -140,3 +140,4 @@ | |||
140 | 139 -> Prolink PixelView PlayTV MPEG2 PV-M4900 | 140 | 139 -> Prolink PixelView PlayTV MPEG2 PV-M4900 |
141 | 140 -> Osprey 440 [0070:ff07] | 141 | 140 -> Osprey 440 [0070:ff07] |
142 | 141 -> Asound Skyeye PCTV | 142 | 141 -> Asound Skyeye PCTV |
143 | 142 -> Sabrent TV-FM (bttv version) | ||
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 57c9d631db56..efb708ec116a 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 | |||
@@ -80,3 +80,5 @@ | |||
80 | 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) | 80 | 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) |
81 | 80 -> ASUS Digimatrix TV [1043:0210] | 81 | 80 -> ASUS Digimatrix TV [1043:0210] |
82 | 81 -> Philips Tiger reference design [1131:2018] | 82 | 81 -> Philips Tiger reference design [1131:2018] |
83 | 82 -> MSI TV@Anywhere plus [1462:6231] | ||
84 | |||
diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index ec840ca6f455..9d6544ea9f41 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner | |||
@@ -67,3 +67,4 @@ tuner=65 - Ymec TVF66T5-B/DFF | |||
67 | tuner=66 - LG NTSC (TALN mini series) | 67 | tuner=66 - LG NTSC (TALN mini series) |
68 | tuner=67 - Philips TD1316 Hybrid Tuner | 68 | tuner=67 - Philips TD1316 Hybrid Tuner |
69 | tuner=68 - Philips TUV1236D ATSC/NTSC dual in | 69 | tuner=68 - Philips TUV1236D ATSC/NTSC dual in |
70 | tuner=69 - Tena TNF 5335 MF | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 2313de23b0da..509927e40bbb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1565,7 +1565,7 @@ S: Maintained | |||
1565 | 1565 | ||
1566 | LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX | 1566 | LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX |
1567 | P: Kumar Gala | 1567 | P: Kumar Gala |
1568 | M: kumar.gala@freescale.com | 1568 | M: galak@kernel.crashing.org |
1569 | W: http://www.penguinppc.org/ | 1569 | W: http://www.penguinppc.org/ |
1570 | L: linuxppc-embedded@ozlabs.org | 1570 | L: linuxppc-embedded@ozlabs.org |
1571 | S: Maintained | 1571 | S: Maintained |
@@ -1873,6 +1873,16 @@ L: linux-tr@linuxtr.net | |||
1873 | W: http://www.linuxtr.net | 1873 | W: http://www.linuxtr.net |
1874 | S: Maintained | 1874 | S: Maintained |
1875 | 1875 | ||
1876 | OMNIKEY CARDMAN 4000 DRIVER | ||
1877 | P: Harald Welte | ||
1878 | M: laforge@gnumonks.org | ||
1879 | S: Maintained | ||
1880 | |||
1881 | OMNIKEY CARDMAN 4040 DRIVER | ||
1882 | P: Harald Welte | ||
1883 | M: laforge@gnumonks.org | ||
1884 | S: Maintained | ||
1885 | |||
1876 | ONSTREAM SCSI TAPE DRIVER | 1886 | ONSTREAM SCSI TAPE DRIVER |
1877 | P: Willem Riede | 1887 | P: Willem Riede |
1878 | M: osst@riede.org | 1888 | M: osst@riede.org |
@@ -1193,6 +1193,17 @@ else | |||
1193 | __srctree = $(srctree)/ | 1193 | __srctree = $(srctree)/ |
1194 | endif | 1194 | endif |
1195 | 1195 | ||
1196 | ifeq ($(ALLSOURCE_ARCHS),) | ||
1197 | ifeq ($(ARCH),um) | ||
1198 | ALLINCLUDE_ARCHS := $(ARCH) $(SUBARCH) | ||
1199 | else | ||
1200 | ALLINCLUDE_ARCHS := $(ARCH) | ||
1201 | endif | ||
1202 | else | ||
1203 | #Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behaviour. | ||
1204 | ALLINCLUDE_ARCHS := $(ALLSOURCE_ARCHS) | ||
1205 | endif | ||
1206 | |||
1196 | ALLSOURCE_ARCHS := $(ARCH) | 1207 | ALLSOURCE_ARCHS := $(ARCH) |
1197 | 1208 | ||
1198 | define all-sources | 1209 | define all-sources |
@@ -1208,7 +1219,7 @@ define all-sources | |||
1208 | find $(__srctree)include $(RCS_FIND_IGNORE) \ | 1219 | find $(__srctree)include $(RCS_FIND_IGNORE) \ |
1209 | \( -name config -o -name 'asm-*' \) -prune \ | 1220 | \( -name config -o -name 'asm-*' \) -prune \ |
1210 | -o -name '*.[chS]' -print; \ | 1221 | -o -name '*.[chS]' -print; \ |
1211 | for ARCH in $(ALLSOURCE_ARCHS) ; do \ | 1222 | for ARCH in $(ALLINCLUDE_ARCHS) ; do \ |
1212 | find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \ | 1223 | find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \ |
1213 | -name '*.[chS]' -print; \ | 1224 | -name '*.[chS]' -print; \ |
1214 | done ; \ | 1225 | done ; \ |
@@ -81,6 +81,11 @@ INSTALLING the kernel: | |||
81 | failed patches (xxx# or xxx.rej). If there are, either you or me has | 81 | failed patches (xxx# or xxx.rej). If there are, either you or me has |
82 | made a mistake. | 82 | made a mistake. |
83 | 83 | ||
84 | Unlike patches for the 2.6.x kernels, patches for the 2.6.x.y kernels | ||
85 | (also known as the -stable kernels) are not incremental but instead apply | ||
86 | directly to the base 2.6.x kernel. Please read | ||
87 | Documentation/applying-patches.txt for more information. | ||
88 | |||
84 | Alternatively, the script patch-kernel can be used to automate this | 89 | Alternatively, the script patch-kernel can be used to automate this |
85 | process. It determines the current kernel version and applies any | 90 | process. It determines the current kernel version and applies any |
86 | patches found. | 91 | patches found. |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3df7cbd924a1..70b007e66926 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -702,6 +702,8 @@ menu "Device Drivers" | |||
702 | 702 | ||
703 | source "drivers/base/Kconfig" | 703 | source "drivers/base/Kconfig" |
704 | 704 | ||
705 | source "drivers/connector/Kconfig" | ||
706 | |||
705 | if ALIGNMENT_TRAP | 707 | if ALIGNMENT_TRAP |
706 | source "drivers/mtd/Kconfig" | 708 | source "drivers/mtd/Kconfig" |
707 | endif | 709 | endif |
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 557e52c1c869..1b7eaab02b9e 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c | |||
@@ -623,8 +623,6 @@ static int locomo_resume(struct platform_device *dev) | |||
623 | locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD); | 623 | locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD); |
624 | 624 | ||
625 | spin_unlock_irqrestore(&lchip->lock, flags); | 625 | spin_unlock_irqrestore(&lchip->lock, flags); |
626 | |||
627 | dev->power.saved_state = NULL; | ||
628 | kfree(save); | 626 | kfree(save); |
629 | 627 | ||
630 | return 0; | 628 | return 0; |
@@ -775,7 +773,7 @@ static int locomo_probe(struct platform_device *dev) | |||
775 | 773 | ||
776 | static int locomo_remove(struct platform_device *dev) | 774 | static int locomo_remove(struct platform_device *dev) |
777 | { | 775 | { |
778 | struct locomo *lchip = platform__get_drvdata(dev); | 776 | struct locomo *lchip = platform_get_drvdata(dev); |
779 | 777 | ||
780 | if (lchip) { | 778 | if (lchip) { |
781 | __locomo_remove(lchip); | 779 | __locomo_remove(lchip); |
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index 32924c6714fe..0c3cbd9a388b 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c | |||
@@ -153,7 +153,7 @@ int __init scoop_probe(struct platform_device *pdev) | |||
153 | printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem->start,(unsigned int)devptr->base); | 153 | printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem->start,(unsigned int)devptr->base); |
154 | 154 | ||
155 | SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140; | 155 | SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140; |
156 | reset_scoop(dev); | 156 | reset_scoop(&pdev->dev); |
157 | SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff; | 157 | SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff; |
158 | SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff; | 158 | SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff; |
159 | 159 | ||
diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c index b0bbd1e62ebb..a2843be05557 100644 --- a/arch/arm/kernel/apm.c +++ b/arch/arm/kernel/apm.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/apm_bios.h> | 20 | #include <linux/apm_bios.h> |
21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
22 | #include <linux/pm.h> | 22 | #include <linux/pm.h> |
23 | #include <linux/pm_legacy.h> | ||
23 | #include <linux/device.h> | 24 | #include <linux/device.h> |
24 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
25 | #include <linux/list.h> | 26 | #include <linux/list.h> |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index e55ea952f7aa..373c0959bc2f 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -256,9 +256,7 @@ void __cpuexit cpu_die(void) | |||
256 | asmlinkage void __cpuinit secondary_start_kernel(void) | 256 | asmlinkage void __cpuinit secondary_start_kernel(void) |
257 | { | 257 | { |
258 | struct mm_struct *mm = &init_mm; | 258 | struct mm_struct *mm = &init_mm; |
259 | unsigned int cpu; | 259 | unsigned int cpu = smp_processor_id(); |
260 | |||
261 | cpu = smp_processor_id(); | ||
262 | 260 | ||
263 | printk("CPU%u: Booted secondary processor\n", cpu); | 261 | printk("CPU%u: Booted secondary processor\n", cpu); |
264 | 262 | ||
diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c index dc09fd200c16..bbe6e4a0bf6a 100644 --- a/arch/arm/mach-footbridge/common.c +++ b/arch/arm/mach-footbridge/common.c | |||
@@ -132,14 +132,14 @@ void __init footbridge_init_irq(void) | |||
132 | static struct map_desc fb_common_io_desc[] __initdata = { | 132 | static struct map_desc fb_common_io_desc[] __initdata = { |
133 | { | 133 | { |
134 | .virtual = ARMCSR_BASE, | 134 | .virtual = ARMCSR_BASE, |
135 | .pfn = DC21285_ARMCSR_BASE, | 135 | .pfn = __phys_to_pfn(DC21285_ARMCSR_BASE), |
136 | .length = ARMCSR_SIZE, | 136 | .length = ARMCSR_SIZE, |
137 | .type = MT_DEVICE | 137 | .type = MT_DEVICE, |
138 | }, { | 138 | }, { |
139 | .virtual = XBUS_BASE, | 139 | .virtual = XBUS_BASE, |
140 | .pfn = __phys_to_pfn(0x40000000), | 140 | .pfn = __phys_to_pfn(0x40000000), |
141 | .length = XBUS_SIZE, | 141 | .length = XBUS_SIZE, |
142 | .type = MT_DEVICE | 142 | .type = MT_DEVICE, |
143 | } | 143 | } |
144 | }; | 144 | }; |
145 | 145 | ||
@@ -153,28 +153,28 @@ static struct map_desc ebsa285_host_io_desc[] __initdata = { | |||
153 | .virtual = PCIMEM_BASE, | 153 | .virtual = PCIMEM_BASE, |
154 | .pfn = __phys_to_pfn(DC21285_PCI_MEM), | 154 | .pfn = __phys_to_pfn(DC21285_PCI_MEM), |
155 | .length = PCIMEM_SIZE, | 155 | .length = PCIMEM_SIZE, |
156 | .type = MT_DEVICE | 156 | .type = MT_DEVICE, |
157 | }, { | 157 | }, { |
158 | .virtual = PCICFG0_BASE, | 158 | .virtual = PCICFG0_BASE, |
159 | .pfn = __phys_to_pfn(DC21285_PCI_TYPE_0_CONFIG), | 159 | .pfn = __phys_to_pfn(DC21285_PCI_TYPE_0_CONFIG), |
160 | .length = PCICFG0_SIZE, | 160 | .length = PCICFG0_SIZE, |
161 | .type = MT_DEVICE | 161 | .type = MT_DEVICE, |
162 | }, { | 162 | }, { |
163 | .virtual = PCICFG1_BASE, | 163 | .virtual = PCICFG1_BASE, |
164 | .pfn = __phys_to_pfn(DC21285_PCI_TYPE_1_CONFIG), | 164 | .pfn = __phys_to_pfn(DC21285_PCI_TYPE_1_CONFIG), |
165 | .length = PCICFG1_SIZE, | 165 | .length = PCICFG1_SIZE, |
166 | .type = MT_DEVICE | 166 | .type = MT_DEVICE, |
167 | }, { | 167 | }, { |
168 | .virtual = PCIIACK_BASE, | 168 | .virtual = PCIIACK_BASE, |
169 | .pfn = __phys_to_pfn(DC21285_PCI_IACK), | 169 | .pfn = __phys_to_pfn(DC21285_PCI_IACK), |
170 | .length = PCIIACK_SIZE, | 170 | .length = PCIIACK_SIZE, |
171 | .type = MT_DEVICE | 171 | .type = MT_DEVICE, |
172 | }, { | 172 | }, { |
173 | .virtual = PCIO_BASE, | 173 | .virtual = PCIO_BASE, |
174 | .pfn = __phys_to_pfn(DC21285_PCI_IO), | 174 | .pfn = __phys_to_pfn(DC21285_PCI_IO), |
175 | .length = PCIO_SIZE, | 175 | .length = PCIO_SIZE, |
176 | .type = MT_DEVICE | 176 | .type = MT_DEVICE, |
177 | } | 177 | }, |
178 | #endif | 178 | #endif |
179 | }; | 179 | }; |
180 | 180 | ||
@@ -187,13 +187,13 @@ static struct map_desc co285_io_desc[] __initdata = { | |||
187 | .virtual = PCIO_BASE, | 187 | .virtual = PCIO_BASE, |
188 | .pfn = __phys_to_pfn(DC21285_PCI_IO), | 188 | .pfn = __phys_to_pfn(DC21285_PCI_IO), |
189 | .length = PCIO_SIZE, | 189 | .length = PCIO_SIZE, |
190 | .type = MT_DEVICE | 190 | .type = MT_DEVICE, |
191 | }, { | 191 | }, { |
192 | .virtual = PCIMEM_BASE, | 192 | .virtual = PCIMEM_BASE, |
193 | .pfn = __phys_to_pfn(DC21285_PCI_MEM), | 193 | .pfn = __phys_to_pfn(DC21285_PCI_MEM), |
194 | .length = PCIMEM_SIZE, | 194 | .length = PCIMEM_SIZE, |
195 | .type = MT_DEVICE | 195 | .type = MT_DEVICE, |
196 | } | 196 | }, |
197 | #endif | 197 | #endif |
198 | }; | 198 | }; |
199 | 199 | ||
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index e201aa9765b9..cd506646801a 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig | |||
@@ -72,6 +72,12 @@ config MACH_HUSKY | |||
72 | depends PXA_SHARPSL_25x | 72 | depends PXA_SHARPSL_25x |
73 | select PXA_SHARP_C7xx | 73 | select PXA_SHARP_C7xx |
74 | 74 | ||
75 | config MACH_AKITA | ||
76 | bool "Enable Sharp SL-1000 (Akita) Support" | ||
77 | depends PXA_SHARPSL_27x | ||
78 | select PXA_SHARP_Cxx00 | ||
79 | select MACH_SPITZ | ||
80 | |||
75 | config MACH_SPITZ | 81 | config MACH_SPITZ |
76 | bool "Enable Sharp Zaurus SL-3000 (Spitz) Support" | 82 | bool "Enable Sharp Zaurus SL-3000 (Spitz) Support" |
77 | depends PXA_SHARPSL_27x | 83 | depends PXA_SHARPSL_27x |
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index d210bd5032ce..32526a0a6f86 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile | |||
@@ -11,8 +11,9 @@ obj-$(CONFIG_PXA27x) += pxa27x.o | |||
11 | obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o | 11 | obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o |
12 | obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o | 12 | obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o |
13 | obj-$(CONFIG_ARCH_PXA_IDP) += idp.o | 13 | obj-$(CONFIG_ARCH_PXA_IDP) += idp.o |
14 | obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o | 14 | obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o |
15 | obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o | 15 | obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o |
16 | obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o | ||
16 | obj-$(CONFIG_MACH_POODLE) += poodle.o | 17 | obj-$(CONFIG_MACH_POODLE) += poodle.o |
17 | obj-$(CONFIG_MACH_TOSA) += tosa.o | 18 | obj-$(CONFIG_MACH_TOSA) += tosa.o |
18 | 19 | ||
diff --git a/arch/arm/mach-pxa/akita-ioexp.c b/arch/arm/mach-pxa/akita-ioexp.c new file mode 100644 index 000000000000..f6d73cc01f78 --- /dev/null +++ b/arch/arm/mach-pxa/akita-ioexp.c | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * Support for the Extra GPIOs on the Sharp SL-C1000 (Akita) | ||
3 | * (uses a Maxim MAX7310 8 Port IO Expander) | ||
4 | * | ||
5 | * Copyright 2005 Openedhand Ltd. | ||
6 | * | ||
7 | * Author: Richard Purdie <richard@openedhand.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | #include <asm/arch/akita.h> | ||
23 | |||
24 | /* MAX7310 Regiser Map */ | ||
25 | #define MAX7310_INPUT 0x00 | ||
26 | #define MAX7310_OUTPUT 0x01 | ||
27 | #define MAX7310_POLINV 0x02 | ||
28 | #define MAX7310_IODIR 0x03 /* 1 = Input, 0 = Output */ | ||
29 | #define MAX7310_TIMEOUT 0x04 | ||
30 | |||
31 | /* Addresses to scan */ | ||
32 | static unsigned short normal_i2c[] = { 0x18, I2C_CLIENT_END }; | ||
33 | |||
34 | /* I2C Magic */ | ||
35 | I2C_CLIENT_INSMOD; | ||
36 | |||
37 | static int max7310_write(struct i2c_client *client, int address, int data); | ||
38 | static struct i2c_client max7310_template; | ||
39 | static void akita_ioexp_work(void *private_); | ||
40 | |||
41 | static struct device *akita_ioexp_device; | ||
42 | static unsigned char ioexp_output_value = AKITA_IOEXP_IO_OUT; | ||
43 | DECLARE_WORK(akita_ioexp, akita_ioexp_work, NULL); | ||
44 | |||
45 | |||
46 | /* | ||
47 | * MAX7310 Access | ||
48 | */ | ||
49 | static int max7310_config(struct device *dev, int iomode, int polarity) | ||
50 | { | ||
51 | int ret; | ||
52 | struct i2c_client *client = to_i2c_client(dev); | ||
53 | |||
54 | ret = max7310_write(client, MAX7310_POLINV, polarity); | ||
55 | if (ret < 0) | ||
56 | return ret; | ||
57 | ret = max7310_write(client, MAX7310_IODIR, iomode); | ||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | static int max7310_set_ouputs(struct device *dev, int outputs) | ||
62 | { | ||
63 | struct i2c_client *client = to_i2c_client(dev); | ||
64 | |||
65 | return max7310_write(client, MAX7310_OUTPUT, outputs); | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * I2C Functions | ||
70 | */ | ||
71 | static int max7310_write(struct i2c_client *client, int address, int value) | ||
72 | { | ||
73 | u8 data[2]; | ||
74 | |||
75 | data[0] = address & 0xff; | ||
76 | data[1] = value & 0xff; | ||
77 | |||
78 | if (i2c_master_send(client, data, 2) == 2) | ||
79 | return 0; | ||
80 | return -1; | ||
81 | } | ||
82 | |||
83 | static int max7310_detect(struct i2c_adapter *adapter, int address, int kind) | ||
84 | { | ||
85 | struct i2c_client *new_client; | ||
86 | int err; | ||
87 | |||
88 | if (!(new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) | ||
89 | return -ENOMEM; | ||
90 | |||
91 | max7310_template.adapter = adapter; | ||
92 | max7310_template.addr = address; | ||
93 | |||
94 | memcpy(new_client, &max7310_template, sizeof(struct i2c_client)); | ||
95 | |||
96 | if ((err = i2c_attach_client(new_client))) { | ||
97 | kfree(new_client); | ||
98 | return err; | ||
99 | } | ||
100 | |||
101 | max7310_config(&new_client->dev, AKITA_IOEXP_IO_DIR, 0); | ||
102 | akita_ioexp_device = &new_client->dev; | ||
103 | schedule_work(&akita_ioexp); | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int max7310_attach_adapter(struct i2c_adapter *adapter) | ||
109 | { | ||
110 | return i2c_probe(adapter, &addr_data, max7310_detect); | ||
111 | } | ||
112 | |||
113 | static int max7310_detach_client(struct i2c_client *client) | ||
114 | { | ||
115 | int err; | ||
116 | |||
117 | akita_ioexp_device = NULL; | ||
118 | |||
119 | if ((err = i2c_detach_client(client))) | ||
120 | return err; | ||
121 | |||
122 | kfree(client); | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static struct i2c_driver max7310_i2c_driver = { | ||
127 | .owner = THIS_MODULE, | ||
128 | .name = "akita-max7310", | ||
129 | .id = I2C_DRIVERID_AKITAIOEXP, | ||
130 | .flags = I2C_DF_NOTIFY, | ||
131 | .attach_adapter = max7310_attach_adapter, | ||
132 | .detach_client = max7310_detach_client, | ||
133 | }; | ||
134 | |||
135 | static struct i2c_client max7310_template = { | ||
136 | name: "akita-max7310", | ||
137 | flags: I2C_CLIENT_ALLOW_USE, | ||
138 | driver: &max7310_i2c_driver, | ||
139 | }; | ||
140 | |||
141 | void akita_set_ioexp(struct device *dev, unsigned char bit) | ||
142 | { | ||
143 | ioexp_output_value |= bit; | ||
144 | |||
145 | if (akita_ioexp_device) | ||
146 | schedule_work(&akita_ioexp); | ||
147 | return; | ||
148 | } | ||
149 | |||
150 | void akita_reset_ioexp(struct device *dev, unsigned char bit) | ||
151 | { | ||
152 | ioexp_output_value &= ~bit; | ||
153 | |||
154 | if (akita_ioexp_device) | ||
155 | schedule_work(&akita_ioexp); | ||
156 | return; | ||
157 | } | ||
158 | |||
159 | EXPORT_SYMBOL(akita_set_ioexp); | ||
160 | EXPORT_SYMBOL(akita_reset_ioexp); | ||
161 | |||
162 | static void akita_ioexp_work(void *private_) | ||
163 | { | ||
164 | if (akita_ioexp_device) | ||
165 | max7310_set_ouputs(akita_ioexp_device, ioexp_output_value); | ||
166 | } | ||
167 | |||
168 | |||
169 | #ifdef CONFIG_PM | ||
170 | static int akita_ioexp_suspend(struct platform_device *pdev, pm_message_t state) | ||
171 | { | ||
172 | flush_scheduled_work(); | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int akita_ioexp_resume(struct platform_device *pdev) | ||
177 | { | ||
178 | schedule_work(&akita_ioexp); | ||
179 | return 0; | ||
180 | } | ||
181 | #else | ||
182 | #define akita_ioexp_suspend NULL | ||
183 | #define akita_ioexp_resume NULL | ||
184 | #endif | ||
185 | |||
186 | static int __init akita_ioexp_probe(struct platform_device *pdev) | ||
187 | { | ||
188 | return i2c_add_driver(&max7310_i2c_driver); | ||
189 | } | ||
190 | |||
191 | static int akita_ioexp_remove(struct platform_device *pdev) | ||
192 | { | ||
193 | i2c_del_driver(&max7310_i2c_driver); | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static struct platform_driver akita_ioexp_driver = { | ||
198 | .probe = akita_ioexp_probe, | ||
199 | .remove = akita_ioexp_remove, | ||
200 | .suspend = akita_ioexp_suspend, | ||
201 | .resume = akita_ioexp_resume, | ||
202 | .driver = { | ||
203 | .name = "akita-ioexp", | ||
204 | }, | ||
205 | }; | ||
206 | |||
207 | static int __init akita_ioexp_init(void) | ||
208 | { | ||
209 | return platform_driver_register(&akita_ioexp_driver); | ||
210 | } | ||
211 | |||
212 | static void __exit akita_ioexp_exit(void) | ||
213 | { | ||
214 | platform_driver_unregister(&akita_ioexp_driver); | ||
215 | } | ||
216 | |||
217 | MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>"); | ||
218 | MODULE_DESCRIPTION("Akita IO-Expander driver"); | ||
219 | MODULE_LICENSE("GPL"); | ||
220 | |||
221 | fs_initcall(akita_ioexp_init); | ||
222 | module_exit(akita_ioexp_exit); | ||
223 | |||
diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c new file mode 100644 index 000000000000..599be14754f9 --- /dev/null +++ b/arch/arm/mach-pxa/corgi_pm.c | |||
@@ -0,0 +1,228 @@ | |||
1 | /* | ||
2 | * Battery and Power Management code for the Sharp SL-C7xx | ||
3 | * | ||
4 | * Copyright (c) 2005 Richard Purdie | ||
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 | #include <linux/module.h> | ||
13 | #include <linux/stat.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <asm/apm.h> | ||
20 | #include <asm/irq.h> | ||
21 | #include <asm/mach-types.h> | ||
22 | #include <asm/hardware.h> | ||
23 | #include <asm/hardware/scoop.h> | ||
24 | |||
25 | #include <asm/arch/sharpsl.h> | ||
26 | #include <asm/arch/corgi.h> | ||
27 | #include <asm/arch/pxa-regs.h> | ||
28 | #include "sharpsl.h" | ||
29 | |||
30 | static void corgi_charger_init(void) | ||
31 | { | ||
32 | pxa_gpio_mode(CORGI_GPIO_ADC_TEMP_ON | GPIO_OUT); | ||
33 | pxa_gpio_mode(CORGI_GPIO_CHRG_ON | GPIO_OUT); | ||
34 | pxa_gpio_mode(CORGI_GPIO_CHRG_UKN | GPIO_OUT); | ||
35 | pxa_gpio_mode(CORGI_GPIO_KEY_INT | GPIO_IN); | ||
36 | } | ||
37 | |||
38 | static void corgi_charge_led(int val) | ||
39 | { | ||
40 | if (val == SHARPSL_LED_ERROR) { | ||
41 | dev_dbg(sharpsl_pm.dev, "Charge LED Error\n"); | ||
42 | } else if (val == SHARPSL_LED_ON) { | ||
43 | dev_dbg(sharpsl_pm.dev, "Charge LED On\n"); | ||
44 | GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); | ||
45 | } else { | ||
46 | dev_dbg(sharpsl_pm.dev, "Charge LED Off\n"); | ||
47 | GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | static void corgi_measure_temp(int on) | ||
52 | { | ||
53 | if (on) | ||
54 | GPSR(CORGI_GPIO_ADC_TEMP_ON) = GPIO_bit(CORGI_GPIO_ADC_TEMP_ON); | ||
55 | else | ||
56 | GPCR(CORGI_GPIO_ADC_TEMP_ON) = GPIO_bit(CORGI_GPIO_ADC_TEMP_ON); | ||
57 | } | ||
58 | |||
59 | static void corgi_charge(int on) | ||
60 | { | ||
61 | if (on) { | ||
62 | if (machine_is_corgi() && (sharpsl_pm.flags & SHARPSL_SUSPENDED)) { | ||
63 | GPCR(CORGI_GPIO_CHRG_ON) = GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
64 | GPSR(CORGI_GPIO_CHRG_UKN) = GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
65 | } else { | ||
66 | GPSR(CORGI_GPIO_CHRG_ON) = GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
67 | GPCR(CORGI_GPIO_CHRG_UKN) = GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
68 | } | ||
69 | } else { | ||
70 | GPCR(CORGI_GPIO_CHRG_ON) = GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
71 | GPCR(CORGI_GPIO_CHRG_UKN) = GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | static void corgi_discharge(int on) | ||
76 | { | ||
77 | if (on) | ||
78 | GPSR(CORGI_GPIO_DISCHARGE_ON) = GPIO_bit(CORGI_GPIO_DISCHARGE_ON); | ||
79 | else | ||
80 | GPCR(CORGI_GPIO_DISCHARGE_ON) = GPIO_bit(CORGI_GPIO_DISCHARGE_ON); | ||
81 | } | ||
82 | |||
83 | static void corgi_presuspend(void) | ||
84 | { | ||
85 | int i; | ||
86 | unsigned long wakeup_mask; | ||
87 | |||
88 | /* charging , so CHARGE_ON bit is HIGH during OFF. */ | ||
89 | if (READ_GPIO_BIT(CORGI_GPIO_CHRG_ON)) | ||
90 | PGSR1 |= GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
91 | else | ||
92 | PGSR1 &= ~GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
93 | |||
94 | if (READ_GPIO_BIT(CORGI_GPIO_LED_ORANGE)) | ||
95 | PGSR0 |= GPIO_bit(CORGI_GPIO_LED_ORANGE); | ||
96 | else | ||
97 | PGSR0 &= ~GPIO_bit(CORGI_GPIO_LED_ORANGE); | ||
98 | |||
99 | if (READ_GPIO_BIT(CORGI_GPIO_CHRG_UKN)) | ||
100 | PGSR1 |= GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
101 | else | ||
102 | PGSR1 &= ~GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
103 | |||
104 | /* Resume on keyboard power key */ | ||
105 | PGSR2 = (PGSR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(0); | ||
106 | |||
107 | wakeup_mask = GPIO_bit(CORGI_GPIO_KEY_INT) | GPIO_bit(CORGI_GPIO_WAKEUP) | GPIO_bit(CORGI_GPIO_AC_IN) | GPIO_bit(CORGI_GPIO_CHRG_FULL); | ||
108 | |||
109 | if (!machine_is_corgi()) | ||
110 | wakeup_mask |= GPIO_bit(CORGI_GPIO_MAIN_BAT_LOW); | ||
111 | |||
112 | PWER = wakeup_mask | PWER_RTC; | ||
113 | PRER = wakeup_mask; | ||
114 | PFER = wakeup_mask; | ||
115 | |||
116 | for (i = 0; i <=15; i++) { | ||
117 | if (PRER & PFER & GPIO_bit(i)) { | ||
118 | if (GPLR0 & GPIO_bit(i) ) | ||
119 | PRER &= ~GPIO_bit(i); | ||
120 | else | ||
121 | PFER &= ~GPIO_bit(i); | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | |||
126 | static void corgi_postsuspend(void) | ||
127 | { | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * Check what brought us out of the suspend. | ||
132 | * Return: 0 to sleep, otherwise wake | ||
133 | */ | ||
134 | static int corgi_should_wakeup(unsigned int resume_on_alarm) | ||
135 | { | ||
136 | int is_resume = 0; | ||
137 | |||
138 | dev_dbg(sharpsl_pm.dev, "GPLR0 = %x,%x\n", GPLR0, PEDR); | ||
139 | |||
140 | if ((PEDR & GPIO_bit(CORGI_GPIO_AC_IN))) { | ||
141 | if (STATUS_AC_IN()) { | ||
142 | /* charge on */ | ||
143 | dev_dbg(sharpsl_pm.dev, "ac insert\n"); | ||
144 | sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG; | ||
145 | } else { | ||
146 | /* charge off */ | ||
147 | dev_dbg(sharpsl_pm.dev, "ac remove\n"); | ||
148 | CHARGE_LED_OFF(); | ||
149 | CHARGE_OFF(); | ||
150 | sharpsl_pm.charge_mode = CHRG_OFF; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | if ((PEDR & GPIO_bit(CORGI_GPIO_CHRG_FULL))) | ||
155 | dev_dbg(sharpsl_pm.dev, "Charge full interrupt\n"); | ||
156 | |||
157 | if (PEDR & GPIO_bit(CORGI_GPIO_KEY_INT)) | ||
158 | is_resume |= GPIO_bit(CORGI_GPIO_KEY_INT); | ||
159 | |||
160 | if (PEDR & GPIO_bit(CORGI_GPIO_WAKEUP)) | ||
161 | is_resume |= GPIO_bit(CORGI_GPIO_WAKEUP); | ||
162 | |||
163 | if (resume_on_alarm && (PEDR & PWER_RTC)) | ||
164 | is_resume |= PWER_RTC; | ||
165 | |||
166 | dev_dbg(sharpsl_pm.dev, "is_resume: %x\n",is_resume); | ||
167 | return is_resume; | ||
168 | } | ||
169 | |||
170 | static unsigned long corgi_charger_wakeup(void) | ||
171 | { | ||
172 | return ~GPLR0 & ( GPIO_bit(CORGI_GPIO_AC_IN) | GPIO_bit(CORGI_GPIO_KEY_INT) | GPIO_bit(CORGI_GPIO_WAKEUP) ); | ||
173 | } | ||
174 | |||
175 | static int corgi_acin_status(void) | ||
176 | { | ||
177 | return ((GPLR(CORGI_GPIO_AC_IN) & GPIO_bit(CORGI_GPIO_AC_IN)) != 0); | ||
178 | } | ||
179 | |||
180 | static struct sharpsl_charger_machinfo corgi_pm_machinfo = { | ||
181 | .init = corgi_charger_init, | ||
182 | .gpio_batlock = CORGI_GPIO_BAT_COVER, | ||
183 | .gpio_acin = CORGI_GPIO_AC_IN, | ||
184 | .gpio_batfull = CORGI_GPIO_CHRG_FULL, | ||
185 | .status_acin = corgi_acin_status, | ||
186 | .discharge = corgi_discharge, | ||
187 | .charge = corgi_charge, | ||
188 | .chargeled = corgi_charge_led, | ||
189 | .measure_temp = corgi_measure_temp, | ||
190 | .presuspend = corgi_presuspend, | ||
191 | .postsuspend = corgi_postsuspend, | ||
192 | .charger_wakeup = corgi_charger_wakeup, | ||
193 | .should_wakeup = corgi_should_wakeup, | ||
194 | .bat_levels = 40, | ||
195 | .bat_levels_noac = spitz_battery_levels_noac, | ||
196 | .bat_levels_acin = spitz_battery_levels_acin, | ||
197 | .status_high_acin = 188, | ||
198 | .status_low_acin = 178, | ||
199 | .status_high_noac = 185, | ||
200 | .status_low_noac = 175, | ||
201 | }; | ||
202 | |||
203 | static struct platform_device *corgipm_device; | ||
204 | |||
205 | static int __devinit corgipm_init(void) | ||
206 | { | ||
207 | int ret; | ||
208 | |||
209 | corgipm_device = platform_device_alloc("sharpsl-pm", -1); | ||
210 | if (!corgipm_device) | ||
211 | return -ENOMEM; | ||
212 | |||
213 | corgipm_device->dev.platform_data = &corgi_pm_machinfo; | ||
214 | ret = platform_device_add(corgipm_device); | ||
215 | |||
216 | if (ret) | ||
217 | platform_device_put(corgipm_device); | ||
218 | |||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | static void corgipm_exit(void) | ||
223 | { | ||
224 | platform_device_unregister(corgipm_device); | ||
225 | } | ||
226 | |||
227 | module_init(corgipm_init); | ||
228 | module_exit(corgipm_exit); | ||
diff --git a/arch/arm/mach-pxa/sharpsl.h b/arch/arm/mach-pxa/sharpsl.h index 4879c0f7da72..b0c40a1d6671 100644 --- a/arch/arm/mach-pxa/sharpsl.h +++ b/arch/arm/mach-pxa/sharpsl.h | |||
@@ -115,7 +115,7 @@ extern struct battery_thresh spitz_battery_levels_noac[]; | |||
115 | #define CHARGE_LED_ERR() sharpsl_pm.machinfo->chargeled(SHARPSL_LED_ERROR) | 115 | #define CHARGE_LED_ERR() sharpsl_pm.machinfo->chargeled(SHARPSL_LED_ERROR) |
116 | #define DISCHARGE_ON() sharpsl_pm.machinfo->discharge(1) | 116 | #define DISCHARGE_ON() sharpsl_pm.machinfo->discharge(1) |
117 | #define DISCHARGE_OFF() sharpsl_pm.machinfo->discharge(0) | 117 | #define DISCHARGE_OFF() sharpsl_pm.machinfo->discharge(0) |
118 | #define STATUS_AC_IN sharpsl_pm.machinfo->status_acin() | 118 | #define STATUS_AC_IN() sharpsl_pm.machinfo->status_acin() |
119 | #define STATUS_BATT_LOCKED READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batlock) | 119 | #define STATUS_BATT_LOCKED() READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batlock) |
120 | #define STATUS_CHRG_FULL READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batfull) | 120 | #define STATUS_CHRG_FULL() READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batfull) |
121 | #define STATUS_FATAL READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_fatal) | 121 | #define STATUS_FATAL() READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_fatal) |
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 6c9e871c53d8..c10be00fb526 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/apm_bios.h> | 21 | #include <linux/apm_bios.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/device.h> | 24 | #include <linux/platform_device.h> |
25 | 25 | ||
26 | #include <asm/hardware.h> | 26 | #include <asm/hardware.h> |
27 | #include <asm/hardware/scoop.h> | 27 | #include <asm/hardware/scoop.h> |
@@ -45,15 +45,15 @@ | |||
45 | #define SHARPSL_WAIT_DISCHARGE_ON 100 /* 100 msec */ | 45 | #define SHARPSL_WAIT_DISCHARGE_ON 100 /* 100 msec */ |
46 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP 10 /* 10 msec */ | 46 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP 10 /* 10 msec */ |
47 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT 10 /* 10 msec */ | 47 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT 10 /* 10 msec */ |
48 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_JKVAD 10 /* 10 msec */ | 48 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN 10 /* 10 msec */ |
49 | #define SHARPSL_CHARGE_WAIT_TIME 15 /* 15 msec */ | 49 | #define SHARPSL_CHARGE_WAIT_TIME 15 /* 15 msec */ |
50 | #define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */ | 50 | #define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */ |
51 | #define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */ | 51 | #define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */ |
52 | 52 | ||
53 | #define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ | 53 | #define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ |
54 | #define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ | 54 | #define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ |
55 | #define SHARPSL_CHARGE_ON_JKVAD_HIGH 0x9b /* 6V */ | 55 | #define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */ |
56 | #define SHARPSL_CHARGE_ON_JKVAD_LOW 0x34 /* 2V */ | 56 | #define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */ |
57 | #define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ | 57 | #define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ |
58 | #define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ | 58 | #define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ |
59 | 59 | ||
@@ -160,9 +160,10 @@ struct battery_thresh spitz_battery_levels_noac[] = { | |||
160 | /* | 160 | /* |
161 | * Prototypes | 161 | * Prototypes |
162 | */ | 162 | */ |
163 | static int sharpsl_read_MainBattery(void); | 163 | static int sharpsl_read_main_battery(void); |
164 | static int sharpsl_off_charge_battery(void); | 164 | static int sharpsl_off_charge_battery(void); |
165 | static int sharpsl_check_battery(int mode); | 165 | static int sharpsl_check_battery_temp(void); |
166 | static int sharpsl_check_battery_voltage(void); | ||
166 | static int sharpsl_ac_check(void); | 167 | static int sharpsl_ac_check(void); |
167 | static int sharpsl_fatal_check(void); | 168 | static int sharpsl_fatal_check(void); |
168 | static int sharpsl_average_value(int ad); | 169 | static int sharpsl_average_value(int ad); |
@@ -228,7 +229,7 @@ static void sharpsl_battery_thread(void *private_) | |||
228 | if (!sharpsl_pm.machinfo) | 229 | if (!sharpsl_pm.machinfo) |
229 | return; | 230 | return; |
230 | 231 | ||
231 | sharpsl_pm.battstat.ac_status = (!(STATUS_AC_IN) ? APM_AC_OFFLINE : APM_AC_ONLINE); | 232 | sharpsl_pm.battstat.ac_status = (STATUS_AC_IN() ? APM_AC_ONLINE : APM_AC_OFFLINE); |
232 | 233 | ||
233 | /* Corgi cannot confirm when battery fully charged so periodically kick! */ | 234 | /* Corgi cannot confirm when battery fully charged so periodically kick! */ |
234 | if (machine_is_corgi() && (sharpsl_pm.charge_mode == CHRG_ON) | 235 | if (machine_is_corgi() && (sharpsl_pm.charge_mode == CHRG_ON) |
@@ -236,7 +237,7 @@ static void sharpsl_battery_thread(void *private_) | |||
236 | schedule_work(&toggle_charger); | 237 | schedule_work(&toggle_charger); |
237 | 238 | ||
238 | while(1) { | 239 | while(1) { |
239 | voltage = sharpsl_read_MainBattery(); | 240 | voltage = sharpsl_read_main_battery(); |
240 | if (voltage > 0) break; | 241 | if (voltage > 0) break; |
241 | if (i++ > 5) { | 242 | if (i++ > 5) { |
242 | voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage; | 243 | voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage; |
@@ -317,10 +318,10 @@ static void sharpsl_charge_toggle(void *private_) | |||
317 | { | 318 | { |
318 | dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies); | 319 | dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies); |
319 | 320 | ||
320 | if (STATUS_AC_IN == 0) { | 321 | if (STATUS_AC_IN() == 0) { |
321 | sharpsl_charge_off(); | 322 | sharpsl_charge_off(); |
322 | return; | 323 | return; |
323 | } else if ((sharpsl_check_battery(1) < 0) || (sharpsl_ac_check() < 0)) { | 324 | } else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) { |
324 | sharpsl_charge_error(); | 325 | sharpsl_charge_error(); |
325 | return; | 326 | return; |
326 | } | 327 | } |
@@ -335,7 +336,7 @@ static void sharpsl_charge_toggle(void *private_) | |||
335 | 336 | ||
336 | static void sharpsl_ac_timer(unsigned long data) | 337 | static void sharpsl_ac_timer(unsigned long data) |
337 | { | 338 | { |
338 | int acin = STATUS_AC_IN; | 339 | int acin = STATUS_AC_IN(); |
339 | 340 | ||
340 | dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin); | 341 | dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin); |
341 | 342 | ||
@@ -364,7 +365,7 @@ static void sharpsl_chrg_full_timer(unsigned long data) | |||
364 | 365 | ||
365 | sharpsl_pm.full_count++; | 366 | sharpsl_pm.full_count++; |
366 | 367 | ||
367 | if (STATUS_AC_IN == 0) { | 368 | if (STATUS_AC_IN() == 0) { |
368 | dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n"); | 369 | dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n"); |
369 | if (sharpsl_pm.charge_mode == CHRG_ON) | 370 | if (sharpsl_pm.charge_mode == CHRG_ON) |
370 | sharpsl_charge_off(); | 371 | sharpsl_charge_off(); |
@@ -399,12 +400,12 @@ static irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id, struct pt_regs *fp) | |||
399 | { | 400 | { |
400 | int is_fatal = 0; | 401 | int is_fatal = 0; |
401 | 402 | ||
402 | if (STATUS_BATT_LOCKED == 0) { | 403 | if (STATUS_BATT_LOCKED() == 0) { |
403 | dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n"); | 404 | dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n"); |
404 | is_fatal = 1; | 405 | is_fatal = 1; |
405 | } | 406 | } |
406 | 407 | ||
407 | if (sharpsl_pm.machinfo->gpio_fatal && (STATUS_FATAL == 0)) { | 408 | if (sharpsl_pm.machinfo->gpio_fatal && (STATUS_FATAL() == 0)) { |
408 | dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n"); | 409 | dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n"); |
409 | is_fatal = 1; | 410 | is_fatal = 1; |
410 | } | 411 | } |
@@ -461,12 +462,12 @@ static int read_max1111(int channel) | |||
461 | | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR); | 462 | | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR); |
462 | } | 463 | } |
463 | 464 | ||
464 | static int sharpsl_read_MainBattery(void) | 465 | static int sharpsl_read_main_battery(void) |
465 | { | 466 | { |
466 | return read_max1111(BATT_AD); | 467 | return read_max1111(BATT_AD); |
467 | } | 468 | } |
468 | 469 | ||
469 | static int sharpsl_read_Temp(void) | 470 | static int sharpsl_read_temp(void) |
470 | { | 471 | { |
471 | int temp; | 472 | int temp; |
472 | 473 | ||
@@ -480,7 +481,7 @@ static int sharpsl_read_Temp(void) | |||
480 | return temp; | 481 | return temp; |
481 | } | 482 | } |
482 | 483 | ||
483 | static int sharpsl_read_jkvad(void) | 484 | static int sharpsl_read_acin(void) |
484 | { | 485 | { |
485 | return read_max1111(JK_VAD); | 486 | return read_max1111(JK_VAD); |
486 | } | 487 | } |
@@ -522,16 +523,14 @@ static int get_select_val(int *val) | |||
522 | return (sum/3); | 523 | return (sum/3); |
523 | } | 524 | } |
524 | 525 | ||
525 | /* mode 0 - Check temperature and voltage | 526 | static int sharpsl_check_battery_temp(void) |
526 | * 1 - Check temperature only */ | ||
527 | static int sharpsl_check_battery(int mode) | ||
528 | { | 527 | { |
529 | int val, i, buff[5]; | 528 | int val, i, buff[5]; |
530 | 529 | ||
531 | /* Check battery temperature */ | 530 | /* Check battery temperature */ |
532 | for (i=0; i<5; i++) { | 531 | for (i=0; i<5; i++) { |
533 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); | 532 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); |
534 | buff[i] = sharpsl_read_Temp(); | 533 | buff[i] = sharpsl_read_temp(); |
535 | } | 534 | } |
536 | 535 | ||
537 | val = get_select_val(buff); | 536 | val = get_select_val(buff); |
@@ -539,8 +538,13 @@ static int sharpsl_check_battery(int mode) | |||
539 | dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val); | 538 | dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val); |
540 | if (val > SHARPSL_CHARGE_ON_TEMP) | 539 | if (val > SHARPSL_CHARGE_ON_TEMP) |
541 | return -1; | 540 | return -1; |
542 | if (mode == 1) | 541 | |
543 | return 0; | 542 | return 0; |
543 | } | ||
544 | |||
545 | static int sharpsl_check_battery_voltage(void) | ||
546 | { | ||
547 | int val, i, buff[5]; | ||
544 | 548 | ||
545 | /* disable charge, enable discharge */ | 549 | /* disable charge, enable discharge */ |
546 | CHARGE_OFF(); | 550 | CHARGE_OFF(); |
@@ -552,7 +556,7 @@ static int sharpsl_check_battery(int mode) | |||
552 | 556 | ||
553 | /* Check battery voltage */ | 557 | /* Check battery voltage */ |
554 | for (i=0; i<5; i++) { | 558 | for (i=0; i<5; i++) { |
555 | buff[i] = sharpsl_read_MainBattery(); | 559 | buff[i] = sharpsl_read_main_battery(); |
556 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); | 560 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); |
557 | } | 561 | } |
558 | 562 | ||
@@ -575,14 +579,14 @@ static int sharpsl_ac_check(void) | |||
575 | int temp, i, buff[5]; | 579 | int temp, i, buff[5]; |
576 | 580 | ||
577 | for (i=0; i<5; i++) { | 581 | for (i=0; i<5; i++) { |
578 | buff[i] = sharpsl_read_jkvad(); | 582 | buff[i] = sharpsl_read_acin(); |
579 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_JKVAD); | 583 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN); |
580 | } | 584 | } |
581 | 585 | ||
582 | temp = get_select_val(buff); | 586 | temp = get_select_val(buff); |
583 | dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp); | 587 | dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp); |
584 | 588 | ||
585 | if ((temp > SHARPSL_CHARGE_ON_JKVAD_HIGH) || (temp < SHARPSL_CHARGE_ON_JKVAD_LOW)) { | 589 | if ((temp > SHARPSL_CHARGE_ON_ACIN_HIGH) || (temp < SHARPSL_CHARGE_ON_ACIN_LOW)) { |
586 | dev_err(sharpsl_pm.dev, "Error: AC check failed.\n"); | 590 | dev_err(sharpsl_pm.dev, "Error: AC check failed.\n"); |
587 | return -1; | 591 | return -1; |
588 | } | 592 | } |
@@ -591,7 +595,7 @@ static int sharpsl_ac_check(void) | |||
591 | } | 595 | } |
592 | 596 | ||
593 | #ifdef CONFIG_PM | 597 | #ifdef CONFIG_PM |
594 | static int sharpsl_pm_suspend(struct device *dev, pm_message_t state) | 598 | static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state) |
595 | { | 599 | { |
596 | sharpsl_pm.flags |= SHARPSL_SUSPENDED; | 600 | sharpsl_pm.flags |= SHARPSL_SUSPENDED; |
597 | flush_scheduled_work(); | 601 | flush_scheduled_work(); |
@@ -604,7 +608,7 @@ static int sharpsl_pm_suspend(struct device *dev, pm_message_t state) | |||
604 | return 0; | 608 | return 0; |
605 | } | 609 | } |
606 | 610 | ||
607 | static int sharpsl_pm_resume(struct device *dev) | 611 | static int sharpsl_pm_resume(struct platform_device *pdev) |
608 | { | 612 | { |
609 | /* Clear the reset source indicators as they break the bootloader upon reboot */ | 613 | /* Clear the reset source indicators as they break the bootloader upon reboot */ |
610 | RCSR = 0x0f; | 614 | RCSR = 0x0f; |
@@ -622,7 +626,7 @@ static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable | |||
622 | dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG); | 626 | dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG); |
623 | /* not charging and AC-IN! */ | 627 | /* not charging and AC-IN! */ |
624 | 628 | ||
625 | if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (STATUS_AC_IN != 0)) { | 629 | if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (STATUS_AC_IN() != 0)) { |
626 | dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n"); | 630 | dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n"); |
627 | sharpsl_pm.charge_mode = CHRG_OFF; | 631 | sharpsl_pm.charge_mode = CHRG_OFF; |
628 | sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; | 632 | sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; |
@@ -671,7 +675,7 @@ static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enab | |||
671 | dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n"); | 675 | dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n"); |
672 | } | 676 | } |
673 | 677 | ||
674 | if ((STATUS_BATT_LOCKED == 0) || (sharpsl_fatal_check() < 0) ) | 678 | if ((STATUS_BATT_LOCKED() == 0) || (sharpsl_fatal_check() < 0) ) |
675 | { | 679 | { |
676 | dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n"); | 680 | dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n"); |
677 | corgi_goto_sleep(alarm_time, alarm_enable, state); | 681 | corgi_goto_sleep(alarm_time, alarm_enable, state); |
@@ -711,7 +715,7 @@ static int sharpsl_fatal_check(void) | |||
711 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n"); | 715 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n"); |
712 | 716 | ||
713 | /* Check AC-Adapter */ | 717 | /* Check AC-Adapter */ |
714 | acin = STATUS_AC_IN; | 718 | acin = STATUS_AC_IN(); |
715 | 719 | ||
716 | if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { | 720 | if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { |
717 | CHARGE_OFF(); | 721 | CHARGE_OFF(); |
@@ -725,7 +729,7 @@ static int sharpsl_fatal_check(void) | |||
725 | 729 | ||
726 | /* Check battery : check inserting battery ? */ | 730 | /* Check battery : check inserting battery ? */ |
727 | for (i=0; i<5; i++) { | 731 | for (i=0; i<5; i++) { |
728 | buff[i] = sharpsl_read_MainBattery(); | 732 | buff[i] = sharpsl_read_main_battery(); |
729 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); | 733 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); |
730 | } | 734 | } |
731 | 735 | ||
@@ -739,7 +743,7 @@ static int sharpsl_fatal_check(void) | |||
739 | } | 743 | } |
740 | 744 | ||
741 | temp = get_select_val(buff); | 745 | temp = get_select_val(buff); |
742 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_read_MainBattery()); | 746 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_read_main_battery()); |
743 | 747 | ||
744 | if ((acin && (temp < SHARPSL_FATAL_ACIN_VOLT)) || | 748 | if ((acin && (temp < SHARPSL_FATAL_ACIN_VOLT)) || |
745 | (!acin && (temp < SHARPSL_FATAL_NOACIN_VOLT))) | 749 | (!acin && (temp < SHARPSL_FATAL_NOACIN_VOLT))) |
@@ -771,7 +775,7 @@ static int sharpsl_off_charge_battery(void) | |||
771 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n"); | 775 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n"); |
772 | 776 | ||
773 | /* AC Check */ | 777 | /* AC Check */ |
774 | if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery(1) < 0)) | 778 | if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0)) |
775 | return sharpsl_off_charge_error(); | 779 | return sharpsl_off_charge_error(); |
776 | 780 | ||
777 | /* Start Charging */ | 781 | /* Start Charging */ |
@@ -793,7 +797,7 @@ static int sharpsl_off_charge_battery(void) | |||
793 | 797 | ||
794 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n"); | 798 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n"); |
795 | 799 | ||
796 | if (sharpsl_check_battery(0) < 0) | 800 | if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0)) |
797 | return sharpsl_off_charge_error(); | 801 | return sharpsl_off_charge_error(); |
798 | 802 | ||
799 | CHARGE_OFF(); | 803 | CHARGE_OFF(); |
@@ -811,7 +815,7 @@ static int sharpsl_off_charge_battery(void) | |||
811 | /* Check for timeout */ | 815 | /* Check for timeout */ |
812 | if ((RCNR - time) > SHARPSL_WAIT_CO_TIME) | 816 | if ((RCNR - time) > SHARPSL_WAIT_CO_TIME) |
813 | return 1; | 817 | return 1; |
814 | if (STATUS_CHRG_FULL) { | 818 | if (STATUS_CHRG_FULL()) { |
815 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occured. Retrying to check\n"); | 819 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occured. Retrying to check\n"); |
816 | sharpsl_pm.full_count++; | 820 | sharpsl_pm.full_count++; |
817 | CHARGE_OFF(); | 821 | CHARGE_OFF(); |
@@ -840,7 +844,7 @@ static int sharpsl_off_charge_battery(void) | |||
840 | sharpsl_pm.full_count++; | 844 | sharpsl_pm.full_count++; |
841 | return 1; | 845 | return 1; |
842 | } | 846 | } |
843 | if (STATUS_CHRG_FULL) { | 847 | if (STATUS_CHRG_FULL()) { |
844 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n"); | 848 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n"); |
845 | CHARGE_LED_OFF(); | 849 | CHARGE_LED_OFF(); |
846 | CHARGE_OFF(); | 850 | CHARGE_OFF(); |
@@ -886,13 +890,13 @@ static struct pm_ops sharpsl_pm_ops = { | |||
886 | .finish = pxa_pm_finish, | 890 | .finish = pxa_pm_finish, |
887 | }; | 891 | }; |
888 | 892 | ||
889 | static int __init sharpsl_pm_probe(struct device *dev) | 893 | static int __init sharpsl_pm_probe(struct platform_device *pdev) |
890 | { | 894 | { |
891 | if (!dev->platform_data) | 895 | if (!pdev->dev.platform_data) |
892 | return -EINVAL; | 896 | return -EINVAL; |
893 | 897 | ||
894 | sharpsl_pm.dev = dev; | 898 | sharpsl_pm.dev = &pdev->dev; |
895 | sharpsl_pm.machinfo = dev->platform_data; | 899 | sharpsl_pm.machinfo = pdev->dev.platform_data; |
896 | sharpsl_pm.charge_mode = CHRG_OFF; | 900 | sharpsl_pm.charge_mode = CHRG_OFF; |
897 | sharpsl_pm.flags = 0; | 901 | sharpsl_pm.flags = 0; |
898 | 902 | ||
@@ -935,8 +939,8 @@ static int __init sharpsl_pm_probe(struct device *dev) | |||
935 | else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQT_RISING); | 939 | else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQT_RISING); |
936 | } | 940 | } |
937 | 941 | ||
938 | device_create_file(dev, &dev_attr_battery_percentage); | 942 | device_create_file(&pdev->dev, &dev_attr_battery_percentage); |
939 | device_create_file(dev, &dev_attr_battery_voltage); | 943 | device_create_file(&pdev->dev, &dev_attr_battery_voltage); |
940 | 944 | ||
941 | apm_get_power_status = sharpsl_apm_get_power_status; | 945 | apm_get_power_status = sharpsl_apm_get_power_status; |
942 | 946 | ||
@@ -947,12 +951,12 @@ static int __init sharpsl_pm_probe(struct device *dev) | |||
947 | return 0; | 951 | return 0; |
948 | } | 952 | } |
949 | 953 | ||
950 | static int sharpsl_pm_remove(struct device *dev) | 954 | static int sharpsl_pm_remove(struct platform_device *pdev) |
951 | { | 955 | { |
952 | pm_set_ops(NULL); | 956 | pm_set_ops(NULL); |
953 | 957 | ||
954 | device_remove_file(dev, &dev_attr_battery_percentage); | 958 | device_remove_file(&pdev->dev, &dev_attr_battery_percentage); |
955 | device_remove_file(dev, &dev_attr_battery_voltage); | 959 | device_remove_file(&pdev->dev, &dev_attr_battery_voltage); |
956 | 960 | ||
957 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr); | 961 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr); |
958 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr); | 962 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr); |
@@ -969,23 +973,24 @@ static int sharpsl_pm_remove(struct device *dev) | |||
969 | return 0; | 973 | return 0; |
970 | } | 974 | } |
971 | 975 | ||
972 | static struct device_driver sharpsl_pm_driver = { | 976 | static struct platform_driver sharpsl_pm_driver = { |
973 | .name = "sharpsl-pm", | ||
974 | .bus = &platform_bus_type, | ||
975 | .probe = sharpsl_pm_probe, | 977 | .probe = sharpsl_pm_probe, |
976 | .remove = sharpsl_pm_remove, | 978 | .remove = sharpsl_pm_remove, |
977 | .suspend = sharpsl_pm_suspend, | 979 | .suspend = sharpsl_pm_suspend, |
978 | .resume = sharpsl_pm_resume, | 980 | .resume = sharpsl_pm_resume, |
981 | .driver = { | ||
982 | .name = "sharpsl-pm", | ||
983 | }, | ||
979 | }; | 984 | }; |
980 | 985 | ||
981 | static int __devinit sharpsl_pm_init(void) | 986 | static int __devinit sharpsl_pm_init(void) |
982 | { | 987 | { |
983 | return driver_register(&sharpsl_pm_driver); | 988 | return platform_driver_register(&sharpsl_pm_driver); |
984 | } | 989 | } |
985 | 990 | ||
986 | static void sharpsl_pm_exit(void) | 991 | static void sharpsl_pm_exit(void) |
987 | { | 992 | { |
988 | driver_unregister(&sharpsl_pm_driver); | 993 | platform_driver_unregister(&sharpsl_pm_driver); |
989 | } | 994 | } |
990 | 995 | ||
991 | late_initcall(sharpsl_pm_init); | 996 | late_initcall(sharpsl_pm_init); |
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 4e9a699ee428..2df1b56615b1 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c | |||
@@ -345,6 +345,16 @@ static void spitz_irda_transceiver_mode(struct device *dev, int mode) | |||
345 | reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON); | 345 | reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON); |
346 | } | 346 | } |
347 | 347 | ||
348 | #ifdef CONFIG_MACH_AKITA | ||
349 | static void akita_irda_transceiver_mode(struct device *dev, int mode) | ||
350 | { | ||
351 | if (mode & IR_OFF) | ||
352 | akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_IR_ON); | ||
353 | else | ||
354 | akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_IR_ON); | ||
355 | } | ||
356 | #endif | ||
357 | |||
348 | static struct pxaficp_platform_data spitz_ficp_platform_data = { | 358 | static struct pxaficp_platform_data spitz_ficp_platform_data = { |
349 | .transceiver_cap = IR_SIRMODE | IR_OFF, | 359 | .transceiver_cap = IR_SIRMODE | IR_OFF, |
350 | .transceiver_mode = spitz_irda_transceiver_mode, | 360 | .transceiver_mode = spitz_irda_transceiver_mode, |
@@ -417,6 +427,32 @@ static void __init spitz_init(void) | |||
417 | platform_device_register(&spitzscoop2_device); | 427 | platform_device_register(&spitzscoop2_device); |
418 | } | 428 | } |
419 | 429 | ||
430 | #ifdef CONFIG_MACH_AKITA | ||
431 | /* | ||
432 | * Akita IO Expander | ||
433 | */ | ||
434 | struct platform_device akitaioexp_device = { | ||
435 | .name = "akita-ioexp", | ||
436 | .id = -1, | ||
437 | }; | ||
438 | |||
439 | static void __init akita_init(void) | ||
440 | { | ||
441 | spitz_ficp_platform_data.transceiver_mode = akita_irda_transceiver_mode; | ||
442 | |||
443 | /* We just pretend the second element of the array doesn't exist */ | ||
444 | spitz_pcmcia_config.num_devs = 1; | ||
445 | platform_scoop_config = &spitz_pcmcia_config; | ||
446 | spitz_bl_machinfo.set_bl_intensity = akita_bl_set_intensity; | ||
447 | |||
448 | platform_device_register(&akitaioexp_device); | ||
449 | |||
450 | spitzscoop_device.dev.parent = &akitaioexp_device.dev; | ||
451 | common_init(); | ||
452 | } | ||
453 | #endif | ||
454 | |||
455 | |||
420 | static void __init fixup_spitz(struct machine_desc *desc, | 456 | static void __init fixup_spitz(struct machine_desc *desc, |
421 | struct tag *tags, char **cmdline, struct meminfo *mi) | 457 | struct tag *tags, char **cmdline, struct meminfo *mi) |
422 | { | 458 | { |
@@ -452,3 +488,16 @@ MACHINE_START(BORZOI, "SHARP Borzoi") | |||
452 | .timer = &pxa_timer, | 488 | .timer = &pxa_timer, |
453 | MACHINE_END | 489 | MACHINE_END |
454 | #endif | 490 | #endif |
491 | |||
492 | #ifdef CONFIG_MACH_AKITA | ||
493 | MACHINE_START(AKITA, "SHARP Akita") | ||
494 | .phys_ram = 0xa0000000, | ||
495 | .phys_io = 0x40000000, | ||
496 | .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, | ||
497 | .fixup = fixup_spitz, | ||
498 | .map_io = pxa_map_io, | ||
499 | .init_irq = pxa_init_irq, | ||
500 | .init_machine = akita_init, | ||
501 | .timer = &pxa_timer, | ||
502 | MACHINE_END | ||
503 | #endif | ||
diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c new file mode 100644 index 000000000000..3ce7486daa51 --- /dev/null +++ b/arch/arm/mach-pxa/spitz_pm.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /* | ||
2 | * Battery and Power Management code for the Sharp SL-Cxx00 | ||
3 | * | ||
4 | * Copyright (c) 2005 Richard Purdie | ||
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 | #include <linux/module.h> | ||
13 | #include <linux/stat.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <asm/apm.h> | ||
20 | #include <asm/irq.h> | ||
21 | #include <asm/mach-types.h> | ||
22 | #include <asm/hardware.h> | ||
23 | #include <asm/hardware/scoop.h> | ||
24 | |||
25 | #include <asm/arch/sharpsl.h> | ||
26 | #include <asm/arch/spitz.h> | ||
27 | #include <asm/arch/pxa-regs.h> | ||
28 | #include "sharpsl.h" | ||
29 | |||
30 | static int spitz_last_ac_status; | ||
31 | |||
32 | static void spitz_charger_init(void) | ||
33 | { | ||
34 | pxa_gpio_mode(SPITZ_GPIO_KEY_INT | GPIO_IN); | ||
35 | pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN); | ||
36 | } | ||
37 | |||
38 | static void spitz_charge_led(int val) | ||
39 | { | ||
40 | if (val == SHARPSL_LED_ERROR) { | ||
41 | dev_dbg(sharpsl_pm.dev, "Charge LED Error\n"); | ||
42 | } else if (val == SHARPSL_LED_ON) { | ||
43 | dev_dbg(sharpsl_pm.dev, "Charge LED On\n"); | ||
44 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); | ||
45 | } else { | ||
46 | dev_dbg(sharpsl_pm.dev, "Charge LED Off\n"); | ||
47 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | static void spitz_measure_temp(int on) | ||
52 | { | ||
53 | if (on) | ||
54 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_ADC_TEMP_ON); | ||
55 | else | ||
56 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_ADC_TEMP_ON); | ||
57 | } | ||
58 | |||
59 | static void spitz_charge(int on) | ||
60 | { | ||
61 | if (on) { | ||
62 | if (sharpsl_pm.flags & SHARPSL_SUSPENDED) { | ||
63 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_B); | ||
64 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CHRG_ON); | ||
65 | } else { | ||
66 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_B); | ||
67 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CHRG_ON); | ||
68 | } | ||
69 | } else { | ||
70 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_B); | ||
71 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CHRG_ON); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | static void spitz_discharge(int on) | ||
76 | { | ||
77 | if (on) | ||
78 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_A); | ||
79 | else | ||
80 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_A); | ||
81 | } | ||
82 | |||
83 | /* HACK - For unknown reasons, accurate voltage readings are only made with a load | ||
84 | on the power bus which the green led on spitz provides */ | ||
85 | static void spitz_discharge1(int on) | ||
86 | { | ||
87 | if (on) | ||
88 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); | ||
89 | else | ||
90 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); | ||
91 | } | ||
92 | |||
93 | static void spitz_presuspend(void) | ||
94 | { | ||
95 | spitz_last_ac_status = STATUS_AC_IN(); | ||
96 | |||
97 | /* GPIO Sleep Register */ | ||
98 | PGSR0 = 0x00144018; | ||
99 | PGSR1 = 0x00EF0000; | ||
100 | if (machine_is_akita()) { | ||
101 | PGSR2 = 0x2121C000; | ||
102 | PGSR3 = 0x00600400; | ||
103 | } else { | ||
104 | PGSR2 = 0x0121C000; | ||
105 | PGSR3 = 0x00600000; | ||
106 | } | ||
107 | |||
108 | PGSR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
109 | PGSR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
110 | PGSR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
111 | PGSR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
112 | PGSR2 |= GPIO_bit(SPITZ_GPIO_KEY_STROBE0); | ||
113 | |||
114 | pxa_gpio_mode(GPIO18_RDY|GPIO_OUT | GPIO_DFLT_HIGH); | ||
115 | |||
116 | PRER = GPIO_bit(SPITZ_GPIO_KEY_INT); | ||
117 | PFER = GPIO_bit(SPITZ_GPIO_KEY_INT) | GPIO_bit(SPITZ_GPIO_RESET); | ||
118 | PWER = GPIO_bit(SPITZ_GPIO_KEY_INT) | GPIO_bit(SPITZ_GPIO_RESET) | PWER_RTC; | ||
119 | PKWR = GPIO_bit(SPITZ_GPIO_SYNC) | GPIO_bit(SPITZ_GPIO_KEY_INT) | GPIO_bit(SPITZ_GPIO_RESET); | ||
120 | PKSR = 0xffffffff; // clear | ||
121 | |||
122 | /* nRESET_OUT Disable */ | ||
123 | PSLR |= PSLR_SL_ROD; | ||
124 | |||
125 | /* Clear reset status */ | ||
126 | RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; | ||
127 | |||
128 | /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ | ||
129 | PCFR = PCFR_GPR_EN | PCFR_OPDE; | ||
130 | } | ||
131 | |||
132 | static void spitz_postsuspend(void) | ||
133 | { | ||
134 | pxa_gpio_mode(GPIO18_RDY_MD); | ||
135 | pxa_gpio_mode(10 | GPIO_IN); | ||
136 | } | ||
137 | |||
138 | static int spitz_should_wakeup(unsigned int resume_on_alarm) | ||
139 | { | ||
140 | int is_resume = 0; | ||
141 | int acin = STATUS_AC_IN(); | ||
142 | |||
143 | if (spitz_last_ac_status != acin) { | ||
144 | if (acin) { | ||
145 | /* charge on */ | ||
146 | sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG; | ||
147 | dev_dbg(sharpsl_pm.dev, "AC Inserted\n"); | ||
148 | } else { | ||
149 | /* charge off */ | ||
150 | dev_dbg(sharpsl_pm.dev, "AC Removed\n"); | ||
151 | CHARGE_LED_OFF(); | ||
152 | CHARGE_OFF(); | ||
153 | sharpsl_pm.charge_mode = CHRG_OFF; | ||
154 | } | ||
155 | spitz_last_ac_status = acin; | ||
156 | /* Return to suspend as this must be what we were woken for */ | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | if (PEDR & GPIO_bit(SPITZ_GPIO_KEY_INT)) | ||
161 | is_resume |= GPIO_bit(SPITZ_GPIO_KEY_INT); | ||
162 | |||
163 | if (PKSR & GPIO_bit(SPITZ_GPIO_SYNC)) | ||
164 | is_resume |= GPIO_bit(SPITZ_GPIO_SYNC); | ||
165 | |||
166 | if (resume_on_alarm && (PEDR & PWER_RTC)) | ||
167 | is_resume |= PWER_RTC; | ||
168 | |||
169 | dev_dbg(sharpsl_pm.dev, "is_resume: %x\n",is_resume); | ||
170 | return is_resume; | ||
171 | } | ||
172 | |||
173 | static unsigned long spitz_charger_wakeup(void) | ||
174 | { | ||
175 | return (~GPLR0 & GPIO_bit(SPITZ_GPIO_KEY_INT)) | (GPLR0 & GPIO_bit(SPITZ_GPIO_SYNC)); | ||
176 | } | ||
177 | |||
178 | static int spitz_acin_status(void) | ||
179 | { | ||
180 | return (((~GPLR(SPITZ_GPIO_AC_IN)) & GPIO_bit(SPITZ_GPIO_AC_IN)) != 0); | ||
181 | } | ||
182 | |||
183 | struct sharpsl_charger_machinfo spitz_pm_machinfo = { | ||
184 | .init = spitz_charger_init, | ||
185 | .gpio_batlock = SPITZ_GPIO_BAT_COVER, | ||
186 | .gpio_acin = SPITZ_GPIO_AC_IN, | ||
187 | .gpio_batfull = SPITZ_GPIO_CHRG_FULL, | ||
188 | .gpio_fatal = SPITZ_GPIO_FATAL_BAT, | ||
189 | .status_acin = spitz_acin_status, | ||
190 | .discharge = spitz_discharge, | ||
191 | .discharge1 = spitz_discharge1, | ||
192 | .charge = spitz_charge, | ||
193 | .chargeled = spitz_charge_led, | ||
194 | .measure_temp = spitz_measure_temp, | ||
195 | .presuspend = spitz_presuspend, | ||
196 | .postsuspend = spitz_postsuspend, | ||
197 | .charger_wakeup = spitz_charger_wakeup, | ||
198 | .should_wakeup = spitz_should_wakeup, | ||
199 | .bat_levels = 40, | ||
200 | .bat_levels_noac = spitz_battery_levels_noac, | ||
201 | .bat_levels_acin = spitz_battery_levels_acin, | ||
202 | .status_high_acin = 188, | ||
203 | .status_low_acin = 178, | ||
204 | .status_high_noac = 185, | ||
205 | .status_low_noac = 175, | ||
206 | }; | ||
207 | |||
208 | static struct platform_device *spitzpm_device; | ||
209 | |||
210 | static int __devinit spitzpm_init(void) | ||
211 | { | ||
212 | int ret; | ||
213 | |||
214 | spitzpm_device = platform_device_alloc("sharpsl-pm", -1); | ||
215 | if (!spitzpm_device) | ||
216 | return -ENOMEM; | ||
217 | |||
218 | spitzpm_device->dev.platform_data = &spitz_pm_machinfo; | ||
219 | ret = platform_device_add(spitzpm_device); | ||
220 | |||
221 | if (ret) | ||
222 | platform_device_put(spitzpm_device); | ||
223 | |||
224 | return ret; | ||
225 | } | ||
226 | |||
227 | static void spitzpm_exit(void) | ||
228 | { | ||
229 | platform_device_unregister(spitzpm_device); | ||
230 | } | ||
231 | |||
232 | module_init(spitzpm_init); | ||
233 | module_exit(spitzpm_exit); | ||
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c index 1a1e8a119c3d..712c3c24c954 100644 --- a/arch/frv/kernel/pm.c +++ b/arch/frv/kernel/pm.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/config.h> | 14 | #include <linux/config.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/pm.h> | 16 | #include <linux/pm.h> |
17 | #include <linux/pm_legacy.h> | ||
17 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
18 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
19 | #include <linux/sysctl.h> | 20 | #include <linux/sysctl.h> |
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index dbf90ad6eac3..6004bb0795e0 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig | |||
@@ -699,7 +699,7 @@ depends on PM && !X86_VISWS | |||
699 | 699 | ||
700 | config APM | 700 | config APM |
701 | tristate "APM (Advanced Power Management) BIOS support" | 701 | tristate "APM (Advanced Power Management) BIOS support" |
702 | depends on PM | 702 | depends on PM && PM_LEGACY |
703 | ---help--- | 703 | ---help--- |
704 | APM is a BIOS specification for saving power using several different | 704 | APM is a BIOS specification for saving power using several different |
705 | techniques. This is mostly useful for battery powered laptops with | 705 | techniques. This is mostly useful for battery powered laptops with |
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 003548b8735f..1e60acbed3c1 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c | |||
@@ -218,6 +218,7 @@ | |||
218 | #include <linux/time.h> | 218 | #include <linux/time.h> |
219 | #include <linux/sched.h> | 219 | #include <linux/sched.h> |
220 | #include <linux/pm.h> | 220 | #include <linux/pm.h> |
221 | #include <linux/pm_legacy.h> | ||
221 | #include <linux/device.h> | 222 | #include <linux/device.h> |
222 | #include <linux/kernel.h> | 223 | #include <linux/kernel.h> |
223 | #include <linux/smp.h> | 224 | #include <linux/smp.h> |
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index 43601de0f633..c28d26fb5f24 100644 --- a/arch/i386/kernel/cpu/intel.c +++ b/arch/i386/kernel/cpu/intel.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/bitops.h> | 6 | #include <linux/bitops.h> |
7 | #include <linux/smp.h> | 7 | #include <linux/smp.h> |
8 | #include <linux/thread_info.h> | 8 | #include <linux/thread_info.h> |
9 | #include <linux/module.h> | ||
9 | 10 | ||
10 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
11 | #include <asm/msr.h> | 12 | #include <asm/msr.h> |
@@ -264,5 +265,52 @@ __init int intel_cpu_init(void) | |||
264 | return 0; | 265 | return 0; |
265 | } | 266 | } |
266 | 267 | ||
268 | #ifndef CONFIG_X86_CMPXCHG | ||
269 | unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new) | ||
270 | { | ||
271 | u8 prev; | ||
272 | unsigned long flags; | ||
273 | |||
274 | /* Poor man's cmpxchg for 386. Unsuitable for SMP */ | ||
275 | local_irq_save(flags); | ||
276 | prev = *(u8 *)ptr; | ||
277 | if (prev == old) | ||
278 | *(u8 *)ptr = new; | ||
279 | local_irq_restore(flags); | ||
280 | return prev; | ||
281 | } | ||
282 | EXPORT_SYMBOL(cmpxchg_386_u8); | ||
283 | |||
284 | unsigned long cmpxchg_386_u16(volatile void *ptr, u16 old, u16 new) | ||
285 | { | ||
286 | u16 prev; | ||
287 | unsigned long flags; | ||
288 | |||
289 | /* Poor man's cmpxchg for 386. Unsuitable for SMP */ | ||
290 | local_irq_save(flags); | ||
291 | prev = *(u16 *)ptr; | ||
292 | if (prev == old) | ||
293 | *(u16 *)ptr = new; | ||
294 | local_irq_restore(flags); | ||
295 | return prev; | ||
296 | } | ||
297 | EXPORT_SYMBOL(cmpxchg_386_u16); | ||
298 | |||
299 | unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new) | ||
300 | { | ||
301 | u32 prev; | ||
302 | unsigned long flags; | ||
303 | |||
304 | /* Poor man's cmpxchg for 386. Unsuitable for SMP */ | ||
305 | local_irq_save(flags); | ||
306 | prev = *(u32 *)ptr; | ||
307 | if (prev == old) | ||
308 | *(u32 *)ptr = new; | ||
309 | local_irq_restore(flags); | ||
310 | return prev; | ||
311 | } | ||
312 | EXPORT_SYMBOL(cmpxchg_386_u32); | ||
313 | #endif | ||
314 | |||
267 | // arch_initcall(intel_cpu_init); | 315 | // arch_initcall(intel_cpu_init); |
268 | 316 | ||
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 9e24f7b207ee..e50b93155249 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S | |||
@@ -560,11 +560,10 @@ nmi_stack_fixup: | |||
560 | nmi_debug_stack_check: | 560 | nmi_debug_stack_check: |
561 | cmpw $__KERNEL_CS,16(%esp) | 561 | cmpw $__KERNEL_CS,16(%esp) |
562 | jne nmi_stack_correct | 562 | jne nmi_stack_correct |
563 | cmpl $debug - 1,(%esp) | 563 | cmpl $debug,(%esp) |
564 | jle nmi_stack_correct | 564 | jb nmi_stack_correct |
565 | cmpl $debug_esp_fix_insn,(%esp) | 565 | cmpl $debug_esp_fix_insn,(%esp) |
566 | jle nmi_debug_stack_fixup | 566 | ja nmi_stack_correct |
567 | nmi_debug_stack_fixup: | ||
568 | FIX_STACK(24,nmi_stack_correct, 1) | 567 | FIX_STACK(24,nmi_stack_correct, 1) |
569 | jmp nmi_stack_correct | 568 | jmp nmi_stack_correct |
570 | 569 | ||
diff --git a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c index e42e46d35159..b9b6bd56b9ba 100644 --- a/arch/i386/kernel/timers/timer_pit.c +++ b/arch/i386/kernel/timers/timer_pit.c | |||
@@ -25,8 +25,9 @@ static int __init init_pit(char* override) | |||
25 | { | 25 | { |
26 | /* check clock override */ | 26 | /* check clock override */ |
27 | if (override[0] && strncmp(override,"pit",3)) | 27 | if (override[0] && strncmp(override,"pit",3)) |
28 | printk(KERN_ERR "Warning: clock= override failed. Defaulting to PIT\n"); | 28 | printk(KERN_ERR "Warning: clock= override failed. Defaulting " |
29 | 29 | "to PIT\n"); | |
30 | init_cpu_khz(); | ||
30 | count_p = LATCH; | 31 | count_p = LATCH; |
31 | return 0; | 32 | return 0; |
32 | } | 33 | } |
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 542d9298da5e..06e26f006238 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/proc_fs.h> | 28 | #include <linux/proc_fs.h> |
29 | #include <linux/efi.h> | 29 | #include <linux/efi.h> |
30 | #include <linux/memory_hotplug.h> | 30 | #include <linux/memory_hotplug.h> |
31 | #include <linux/initrd.h> | ||
31 | 32 | ||
32 | #include <asm/processor.h> | 33 | #include <asm/processor.h> |
33 | #include <asm/system.h> | 34 | #include <asm/system.h> |
@@ -267,7 +268,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base) | |||
267 | pkmap_page_table = pte; | 268 | pkmap_page_table = pte; |
268 | } | 269 | } |
269 | 270 | ||
270 | void __devinit free_new_highpage(struct page *page) | 271 | static void __devinit free_new_highpage(struct page *page) |
271 | { | 272 | { |
272 | set_page_count(page, 1); | 273 | set_page_count(page, 1); |
273 | __free_page(page); | 274 | __free_page(page); |
diff --git a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S index 9571a21d6ad4..a1629194e3fd 100644 --- a/arch/m68k/fpsp040/skeleton.S +++ b/arch/m68k/fpsp040/skeleton.S | |||
@@ -381,10 +381,8 @@ fpsp_done: | |||
381 | .Lnotkern: | 381 | .Lnotkern: |
382 | SAVE_ALL_INT | 382 | SAVE_ALL_INT |
383 | GET_CURRENT(%d0) | 383 | GET_CURRENT(%d0) |
384 | tstb %curptr@(TASK_NEEDRESCHED) | 384 | | deliver signals, reschedule etc.. |
385 | jne ret_from_exception | deliver signals, | 385 | jra ret_from_exception |
386 | | reschedule etc.. | ||
387 | RESTORE_ALL | ||
388 | 386 | ||
389 | | | 387 | | |
390 | | mem_write --- write to user or supervisor address space | 388 | | mem_write --- write to user or supervisor address space |
diff --git a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S index 4ba2c74da93d..b2dbdf5ee309 100644 --- a/arch/m68k/ifpsp060/iskeleton.S +++ b/arch/m68k/ifpsp060/iskeleton.S | |||
@@ -75,10 +75,8 @@ _060_isp_done: | |||
75 | .Lnotkern: | 75 | .Lnotkern: |
76 | SAVE_ALL_INT | 76 | SAVE_ALL_INT |
77 | GET_CURRENT(%d0) | 77 | GET_CURRENT(%d0) |
78 | tstb %curptr@(TASK_NEEDRESCHED) | 78 | | deliver signals, reschedule etc.. |
79 | jne ret_from_exception | deliver signals, | 79 | jra ret_from_exception |
80 | | reschedule etc.. | ||
81 | RESTORE_ALL | ||
82 | 80 | ||
83 | | | 81 | | |
84 | | _060_real_chk(): | 82 | | _060_real_chk(): |
diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c index cee3317b8665..c787c5ba9513 100644 --- a/arch/m68k/kernel/asm-offsets.c +++ b/arch/m68k/kernel/asm-offsets.c | |||
@@ -25,12 +25,8 @@ int main(void) | |||
25 | DEFINE(TASK_STATE, offsetof(struct task_struct, state)); | 25 | DEFINE(TASK_STATE, offsetof(struct task_struct, state)); |
26 | DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); | 26 | DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); |
27 | DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); | 27 | DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); |
28 | DEFINE(TASK_WORK, offsetof(struct task_struct, thread.work)); | ||
29 | DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, thread.work.need_resched)); | ||
30 | DEFINE(TASK_SYSCALL_TRACE, offsetof(struct task_struct, thread.work.syscall_trace)); | ||
31 | DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, thread.work.sigpending)); | ||
32 | DEFINE(TASK_NOTIFY_RESUME, offsetof(struct task_struct, thread.work.notify_resume)); | ||
33 | DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); | 28 | DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); |
29 | DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info)); | ||
34 | DEFINE(TASK_MM, offsetof(struct task_struct, mm)); | 30 | DEFINE(TASK_MM, offsetof(struct task_struct, mm)); |
35 | DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); | 31 | DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); |
36 | 32 | ||
@@ -45,6 +41,10 @@ int main(void) | |||
45 | DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); | 41 | DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); |
46 | DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); | 42 | DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); |
47 | 43 | ||
44 | /* offsets into the thread_info struct */ | ||
45 | DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count)); | ||
46 | DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags)); | ||
47 | |||
48 | /* offsets into the pt_regs */ | 48 | /* offsets into the pt_regs */ |
49 | DEFINE(PT_D0, offsetof(struct pt_regs, d0)); | 49 | DEFINE(PT_D0, offsetof(struct pt_regs, d0)); |
50 | DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0)); | 50 | DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0)); |
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 23ca60a45552..320fde05dc63 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S | |||
@@ -44,9 +44,7 @@ | |||
44 | 44 | ||
45 | #include <asm/asm-offsets.h> | 45 | #include <asm/asm-offsets.h> |
46 | 46 | ||
47 | .globl system_call, buserr, trap | 47 | .globl system_call, buserr, trap, resume |
48 | .globl resume, ret_from_exception | ||
49 | .globl ret_from_signal | ||
50 | .globl inthandler, sys_call_table | 48 | .globl inthandler, sys_call_table |
51 | .globl sys_fork, sys_clone, sys_vfork | 49 | .globl sys_fork, sys_clone, sys_vfork |
52 | .globl ret_from_interrupt, bad_interrupt | 50 | .globl ret_from_interrupt, bad_interrupt |
@@ -58,7 +56,7 @@ ENTRY(buserr) | |||
58 | movel %sp,%sp@- | stack frame pointer argument | 56 | movel %sp,%sp@- | stack frame pointer argument |
59 | bsrl buserr_c | 57 | bsrl buserr_c |
60 | addql #4,%sp | 58 | addql #4,%sp |
61 | jra ret_from_exception | 59 | jra .Lret_from_exception |
62 | 60 | ||
63 | ENTRY(trap) | 61 | ENTRY(trap) |
64 | SAVE_ALL_INT | 62 | SAVE_ALL_INT |
@@ -66,7 +64,7 @@ ENTRY(trap) | |||
66 | movel %sp,%sp@- | stack frame pointer argument | 64 | movel %sp,%sp@- | stack frame pointer argument |
67 | bsrl trap_c | 65 | bsrl trap_c |
68 | addql #4,%sp | 66 | addql #4,%sp |
69 | jra ret_from_exception | 67 | jra .Lret_from_exception |
70 | 68 | ||
71 | | After a fork we jump here directly from resume, | 69 | | After a fork we jump here directly from resume, |
72 | | so that %d1 contains the previous task | 70 | | so that %d1 contains the previous task |
@@ -75,30 +73,31 @@ ENTRY(ret_from_fork) | |||
75 | movel %d1,%sp@- | 73 | movel %d1,%sp@- |
76 | jsr schedule_tail | 74 | jsr schedule_tail |
77 | addql #4,%sp | 75 | addql #4,%sp |
78 | jra ret_from_exception | 76 | jra .Lret_from_exception |
79 | 77 | ||
80 | badsys: | 78 | do_trace_entry: |
81 | movel #-ENOSYS,%sp@(PT_D0) | ||
82 | jra ret_from_exception | ||
83 | |||
84 | do_trace: | ||
85 | movel #-ENOSYS,%sp@(PT_D0) | needed for strace | 79 | movel #-ENOSYS,%sp@(PT_D0) | needed for strace |
86 | subql #4,%sp | 80 | subql #4,%sp |
87 | SAVE_SWITCH_STACK | 81 | SAVE_SWITCH_STACK |
88 | jbsr syscall_trace | 82 | jbsr syscall_trace |
89 | RESTORE_SWITCH_STACK | 83 | RESTORE_SWITCH_STACK |
90 | addql #4,%sp | 84 | addql #4,%sp |
91 | movel %sp@(PT_ORIG_D0),%d1 | 85 | movel %sp@(PT_ORIG_D0),%d0 |
92 | movel #-ENOSYS,%d0 | 86 | cmpl #NR_syscalls,%d0 |
93 | cmpl #NR_syscalls,%d1 | 87 | jcs syscall |
94 | jcc 1f | 88 | badsys: |
95 | jbsr @(sys_call_table,%d1:l:4)@(0) | 89 | movel #-ENOSYS,%sp@(PT_D0) |
96 | 1: movel %d0,%sp@(PT_D0) | save the return value | 90 | jra ret_from_syscall |
97 | subql #4,%sp | dummy return address | 91 | |
92 | do_trace_exit: | ||
93 | subql #4,%sp | ||
98 | SAVE_SWITCH_STACK | 94 | SAVE_SWITCH_STACK |
99 | jbsr syscall_trace | 95 | jbsr syscall_trace |
96 | RESTORE_SWITCH_STACK | ||
97 | addql #4,%sp | ||
98 | jra .Lret_from_exception | ||
100 | 99 | ||
101 | ret_from_signal: | 100 | ENTRY(ret_from_signal) |
102 | RESTORE_SWITCH_STACK | 101 | RESTORE_SWITCH_STACK |
103 | addql #4,%sp | 102 | addql #4,%sp |
104 | /* on 68040 complete pending writebacks if any */ | 103 | /* on 68040 complete pending writebacks if any */ |
@@ -111,7 +110,7 @@ ret_from_signal: | |||
111 | addql #4,%sp | 110 | addql #4,%sp |
112 | 1: | 111 | 1: |
113 | #endif | 112 | #endif |
114 | jra ret_from_exception | 113 | jra .Lret_from_exception |
115 | 114 | ||
116 | ENTRY(system_call) | 115 | ENTRY(system_call) |
117 | SAVE_ALL_SYS | 116 | SAVE_ALL_SYS |
@@ -120,30 +119,34 @@ ENTRY(system_call) | |||
120 | | save top of frame | 119 | | save top of frame |
121 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) | 120 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) |
122 | 121 | ||
123 | tstb %curptr@(TASK_SYSCALL_TRACE) | 122 | | syscall trace? |
124 | jne do_trace | 123 | tstb %curptr@(TASK_INFO+TINFO_FLAGS+2) |
124 | jmi do_trace_entry | ||
125 | cmpl #NR_syscalls,%d0 | 125 | cmpl #NR_syscalls,%d0 |
126 | jcc badsys | 126 | jcc badsys |
127 | syscall: | ||
127 | jbsr @(sys_call_table,%d0:l:4)@(0) | 128 | jbsr @(sys_call_table,%d0:l:4)@(0) |
128 | movel %d0,%sp@(PT_D0) | save the return value | 129 | movel %d0,%sp@(PT_D0) | save the return value |
129 | 130 | ret_from_syscall: | |
130 | |oriw #0x0700,%sr | 131 | |oriw #0x0700,%sr |
131 | movel %curptr@(TASK_WORK),%d0 | 132 | movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0 |
132 | jne syscall_exit_work | 133 | jne syscall_exit_work |
133 | 1: RESTORE_ALL | 134 | 1: RESTORE_ALL |
134 | 135 | ||
135 | syscall_exit_work: | 136 | syscall_exit_work: |
136 | btst #5,%sp@(PT_SR) | check if returning to kernel | 137 | btst #5,%sp@(PT_SR) | check if returning to kernel |
137 | bnes 1b | if so, skip resched, signals | 138 | bnes 1b | if so, skip resched, signals |
138 | tstw %d0 | 139 | lslw #1,%d0 |
139 | jeq do_signal_return | 140 | jcs do_trace_exit |
140 | tstb %d0 | 141 | jmi do_delayed_trace |
141 | jne do_delayed_trace | 142 | lslw #8,%d0 |
142 | 143 | jmi do_signal_return | |
143 | pea resume_userspace | 144 | pea resume_userspace |
144 | jmp schedule | 145 | jra schedule |
146 | |||
145 | 147 | ||
146 | ret_from_exception: | 148 | ENTRY(ret_from_exception) |
149 | .Lret_from_exception: | ||
147 | btst #5,%sp@(PT_SR) | check if returning to kernel | 150 | btst #5,%sp@(PT_SR) | check if returning to kernel |
148 | bnes 1f | if so, skip resched, signals | 151 | bnes 1f | if so, skip resched, signals |
149 | | only allow interrupts when we are really the last one on the | 152 | | only allow interrupts when we are really the last one on the |
@@ -152,19 +155,18 @@ ret_from_exception: | |||
152 | andw #ALLOWINT,%sr | 155 | andw #ALLOWINT,%sr |
153 | 156 | ||
154 | resume_userspace: | 157 | resume_userspace: |
155 | movel %curptr@(TASK_WORK),%d0 | 158 | moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0 |
156 | lsrl #8,%d0 | ||
157 | jne exit_work | 159 | jne exit_work |
158 | 1: RESTORE_ALL | 160 | 1: RESTORE_ALL |
159 | 161 | ||
160 | exit_work: | 162 | exit_work: |
161 | | save top of frame | 163 | | save top of frame |
162 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) | 164 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) |
163 | tstb %d0 | 165 | lslb #1,%d0 |
164 | jeq do_signal_return | 166 | jmi do_signal_return |
165 | |||
166 | pea resume_userspace | 167 | pea resume_userspace |
167 | jmp schedule | 168 | jra schedule |
169 | |||
168 | 170 | ||
169 | do_signal_return: | 171 | do_signal_return: |
170 | |andw #ALLOWINT,%sr | 172 | |andw #ALLOWINT,%sr |
@@ -254,7 +256,7 @@ ret_from_interrupt: | |||
254 | 256 | ||
255 | /* check if we need to do software interrupts */ | 257 | /* check if we need to do software interrupts */ |
256 | tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING | 258 | tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING |
257 | jeq ret_from_exception | 259 | jeq .Lret_from_exception |
258 | pea ret_from_exception | 260 | pea ret_from_exception |
259 | jra do_softirq | 261 | jra do_softirq |
260 | 262 | ||
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 7e54422685cf..540638ca81f9 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c | |||
@@ -109,7 +109,7 @@ static inline void singlestep_disable(struct task_struct *child) | |||
109 | { | 109 | { |
110 | unsigned long tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); | 110 | unsigned long tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); |
111 | put_reg(child, PT_SR, tmp); | 111 | put_reg(child, PT_SR, tmp); |
112 | child->thread.work.delayed_trace = 0; | 112 | clear_tsk_thread_flag(child, TIF_DELAYED_TRACE); |
113 | } | 113 | } |
114 | 114 | ||
115 | /* | 115 | /* |
@@ -118,7 +118,7 @@ static inline void singlestep_disable(struct task_struct *child) | |||
118 | void ptrace_disable(struct task_struct *child) | 118 | void ptrace_disable(struct task_struct *child) |
119 | { | 119 | { |
120 | singlestep_disable(child); | 120 | singlestep_disable(child); |
121 | child->thread.work.syscall_trace = 0; | 121 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
122 | } | 122 | } |
123 | 123 | ||
124 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 124 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
@@ -198,9 +198,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
198 | goto out_eio; | 198 | goto out_eio; |
199 | 199 | ||
200 | if (request == PTRACE_SYSCALL) | 200 | if (request == PTRACE_SYSCALL) |
201 | child->thread.work.syscall_trace = ~0; | 201 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
202 | else | 202 | else |
203 | child->thread.work.syscall_trace = 0; | 203 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
204 | child->exit_code = data; | 204 | child->exit_code = data; |
205 | singlestep_disable(child); | 205 | singlestep_disable(child); |
206 | wake_up_process(child); | 206 | wake_up_process(child); |
@@ -223,10 +223,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
223 | if (!valid_signal(data)) | 223 | if (!valid_signal(data)) |
224 | goto out_eio; | 224 | goto out_eio; |
225 | 225 | ||
226 | child->thread.work.syscall_trace = 0; | 226 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
227 | tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); | 227 | tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); |
228 | put_reg(child, PT_SR, tmp); | 228 | put_reg(child, PT_SR, tmp); |
229 | child->thread.work.delayed_trace = 1; | 229 | set_tsk_thread_flag(child, TIF_DELAYED_TRACE); |
230 | 230 | ||
231 | child->exit_code = data; | 231 | child->exit_code = data; |
232 | /* give it a chance to run. */ | 232 | /* give it a chance to run. */ |
@@ -288,9 +288,6 @@ out_eio: | |||
288 | 288 | ||
289 | asmlinkage void syscall_trace(void) | 289 | asmlinkage void syscall_trace(void) |
290 | { | 290 | { |
291 | if (!current->thread.work.delayed_trace && | ||
292 | !current->thread.work.syscall_trace) | ||
293 | return; | ||
294 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) | 291 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) |
295 | ? 0x80 : 0)); | 292 | ? 0x80 : 0)); |
296 | /* | 293 | /* |
diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c index f85093b8d54d..f4926315fb68 100644 --- a/arch/mips/au1000/common/power.c +++ b/arch/mips/au1000/common/power.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/config.h> | 32 | #include <linux/config.h> |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | #include <linux/pm.h> | 34 | #include <linux/pm.h> |
35 | #include <linux/pm_legacy.h> | ||
35 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
36 | #include <linux/sysctl.h> | 37 | #include <linux/sysctl.h> |
37 | #include <linux/jiffies.h> | 38 | #include <linux/jiffies.h> |
diff --git a/arch/mips/au1000/common/usbdev.c b/arch/mips/au1000/common/usbdev.c index 0b21bed7ee55..2cab7629702c 100644 --- a/arch/mips/au1000/common/usbdev.c +++ b/arch/mips/au1000/common/usbdev.c | |||
@@ -348,7 +348,7 @@ endpoint_stall(endpoint_t * ep) | |||
348 | { | 348 | { |
349 | u32 cs; | 349 | u32 cs; |
350 | 350 | ||
351 | warn(__FUNCTION__); | 351 | warn("%s", __FUNCTION__); |
352 | 352 | ||
353 | cs = au_readl(ep->reg->ctrl_stat) | USBDEV_CS_STALL; | 353 | cs = au_readl(ep->reg->ctrl_stat) | USBDEV_CS_STALL; |
354 | au_writel(cs, ep->reg->ctrl_stat); | 354 | au_writel(cs, ep->reg->ctrl_stat); |
@@ -360,7 +360,7 @@ endpoint_unstall(endpoint_t * ep) | |||
360 | { | 360 | { |
361 | u32 cs; | 361 | u32 cs; |
362 | 362 | ||
363 | warn(__FUNCTION__); | 363 | warn("%s", __FUNCTION__); |
364 | 364 | ||
365 | cs = au_readl(ep->reg->ctrl_stat) & ~USBDEV_CS_STALL; | 365 | cs = au_readl(ep->reg->ctrl_stat) & ~USBDEV_CS_STALL; |
366 | au_writel(cs, ep->reg->ctrl_stat); | 366 | au_writel(cs, ep->reg->ctrl_stat); |
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 5063c603fad4..8d60fa99fc4b 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
@@ -24,7 +24,7 @@ | |||
24 | * Copyright 2002-2004 MontaVista Software, Inc. | 24 | * Copyright 2002-2004 MontaVista Software, Inc. |
25 | * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> | 25 | * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> |
26 | * Copyright 2004 Freescale Semiconductor, Inc | 26 | * Copyright 2004 Freescale Semiconductor, Inc |
27 | * PowerPC e500 modifications, Kumar Gala <kumar.gala@freescale.com> | 27 | * PowerPC e500 modifications, Kumar Gala <galak@kernel.crashing.org> |
28 | * | 28 | * |
29 | * This program is free software; you can redistribute it and/or modify it | 29 | * This program is free software; you can redistribute it and/or modify it |
30 | * under the terms of the GNU General Public License as published by the | 30 | * under the terms of the GNU General Public License as published by the |
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index af9ca0eb6d55..5d581bb3aa12 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Modifications by Kumar Gala (kumar.gala@freescale.com) to support | 2 | * Modifications by Kumar Gala (galak@kernel.crashing.org) to support |
3 | * E500 Book E processors. | 3 | * E500 Book E processors. |
4 | * | 4 | * |
5 | * Copyright 2004 Freescale Semiconductor, Inc | 5 | * Copyright 2004 Freescale Semiconductor, Inc |
diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_booke.c index 86124a94c9af..26539cda6023 100644 --- a/arch/powerpc/oprofile/op_model_fsl_booke.c +++ b/arch/powerpc/oprofile/op_model_fsl_booke.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Copyright (c) 2004 Freescale Semiconductor, Inc | 7 | * Copyright (c) 2004 Freescale Semiconductor, Inc |
8 | * | 8 | * |
9 | * Author: Andy Fleming | 9 | * Author: Andy Fleming |
10 | * Maintainer: Kumar Gala <Kumar.Gala@freescale.com> | 10 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 13 | * modify it under the terms of the GNU General Public License |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index ef4356b29a97..c45a6ad5f3b7 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/cpumask.h> | 19 | #include <linux/cpumask.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/sysrq.h> | 21 | #include <linux/sysrq.h> |
22 | #include <linux/interrupt.h> | ||
22 | 23 | ||
23 | #include <asm/ptrace.h> | 24 | #include <asm/ptrace.h> |
24 | #include <asm/string.h> | 25 | #include <asm/string.h> |
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S index 5063c603fad4..8d60fa99fc4b 100644 --- a/arch/ppc/kernel/head_fsl_booke.S +++ b/arch/ppc/kernel/head_fsl_booke.S | |||
@@ -24,7 +24,7 @@ | |||
24 | * Copyright 2002-2004 MontaVista Software, Inc. | 24 | * Copyright 2002-2004 MontaVista Software, Inc. |
25 | * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> | 25 | * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> |
26 | * Copyright 2004 Freescale Semiconductor, Inc | 26 | * Copyright 2004 Freescale Semiconductor, Inc |
27 | * PowerPC e500 modifications, Kumar Gala <kumar.gala@freescale.com> | 27 | * PowerPC e500 modifications, Kumar Gala <galak@kernel.crashing.org> |
28 | * | 28 | * |
29 | * This program is free software; you can redistribute it and/or modify it | 29 | * This program is free software; you can redistribute it and/or modify it |
30 | * under the terms of the GNU General Public License as published by the | 30 | * under the terms of the GNU General Public License as published by the |
diff --git a/arch/ppc/mm/fsl_booke_mmu.c b/arch/ppc/mm/fsl_booke_mmu.c index af9ca0eb6d55..5d581bb3aa12 100644 --- a/arch/ppc/mm/fsl_booke_mmu.c +++ b/arch/ppc/mm/fsl_booke_mmu.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Modifications by Kumar Gala (kumar.gala@freescale.com) to support | 2 | * Modifications by Kumar Gala (galak@kernel.crashing.org) to support |
3 | * E500 Book E processors. | 3 | * E500 Book E processors. |
4 | * | 4 | * |
5 | * Copyright 2004 Freescale Semiconductor, Inc | 5 | * Copyright 2004 Freescale Semiconductor, Inc |
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 98edc75f4105..04bdc39bf47b 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC834x SYS board specific routines | 4 | * MPC834x SYS board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
@@ -73,12 +73,19 @@ mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | |||
73 | * A B C D | 73 | * A B C D |
74 | */ | 74 | */ |
75 | { | 75 | { |
76 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */ | 76 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */ |
77 | {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */ | 77 | {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */ |
78 | {PIRQD, PIRQA, PIRQB, PIRQC} /* idsel 0x13 */ | 78 | {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x13 */ |
79 | {0, 0, 0, 0}, | ||
80 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */ | ||
81 | {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */ | ||
82 | {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */ | ||
83 | {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */ | ||
84 | {0, 0, 0, 0}, /* idsel 0x19 */ | ||
85 | {0, 0, 0, 0}, /* idsel 0x20 */ | ||
79 | }; | 86 | }; |
80 | 87 | ||
81 | const long min_idsel = 0x11, max_idsel = 0x13, irqs_per_slot = 4; | 88 | const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4; |
82 | return PCI_IRQ_TABLE_LOOKUP; | 89 | return PCI_IRQ_TABLE_LOOKUP; |
83 | } | 90 | } |
84 | 91 | ||
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h index 58e44c042535..2e514d316fb8 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.h +++ b/arch/ppc/platforms/83xx/mpc834x_sys.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC834X SYS common board definitions | 4 | * MPC834X SYS common board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor, Inc. | 8 | * Copyright 2005 Freescale Semiconductor, Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index 7e952c1228cb..c5cde97c6ef0 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8540ADS board specific routines | 4 | * MPC8540ADS board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.h b/arch/ppc/platforms/85xx/mpc8540_ads.h index 3d05d7c4a938..e48ca3a97397 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.h +++ b/arch/ppc/platforms/85xx/mpc8540_ads.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8540ADS board definitions | 4 | * MPC8540ADS board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8555_cds.h b/arch/ppc/platforms/85xx/mpc8555_cds.h index e0e75568bc57..1a8e6c67355d 100644 --- a/arch/ppc/platforms/85xx/mpc8555_cds.h +++ b/arch/ppc/platforms/85xx/mpc8555_cds.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8555CDS board definitions | 4 | * MPC8555CDS board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index 208433f1e93a..8e39a5517092 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8560ADS board specific routines | 4 | * MPC8560ADS board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.h b/arch/ppc/platforms/85xx/mpc8560_ads.h index 7df885d73e9d..143ae7eefa7c 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.h +++ b/arch/ppc/platforms/85xx/mpc8560_ads.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8540ADS board definitions | 4 | * MPC8540ADS board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c index 16ad092d8a06..17ce48fe3503 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx ADS board common routines | 4 | * MPC85xx ADS board common routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h index 84acf6e8d45e..7b26bcc5d10d 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85XX ADS common board definitions | 4 | * MPC85XX ADS common board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index a21156967a5e..d8991b88dc9c 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx CDS board specific routines | 4 | * MPC85xx CDS board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor, Inc | 8 | * Copyright 2004 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h index 12b292c6ae32..5b588cfd0e41 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx CDS board definitions | 4 | * MPC85xx CDS board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor, Inc | 8 | * Copyright 2004 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index b4ee1707a836..45a5b81b4ed1 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Wind River SBC8560 board specific routines | 4 | * Wind River SBC8560 board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c index 58884a63ebdb..1e69b0593162 100644 --- a/arch/ppc/platforms/pmac_feature.c +++ b/arch/ppc/platforms/pmac_feature.c | |||
@@ -2317,6 +2317,14 @@ static struct pmac_mb_def pmac_mb_defs[] = { | |||
2317 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | 2317 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, |
2318 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | 2318 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, |
2319 | }, | 2319 | }, |
2320 | { "PowerBook5,8", "PowerBook G4 15\"", | ||
2321 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2322 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2323 | }, | ||
2324 | { "PowerBook5,9", "PowerBook G4 17\"", | ||
2325 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2326 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2327 | }, | ||
2320 | { "PowerBook6,1", "PowerBook G4 12\"", | 2328 | { "PowerBook6,1", "PowerBook G4 12\"", |
2321 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | 2329 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, |
2322 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | 2330 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, |
diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c index 6a1475c1e128..71c9fca1fe9b 100644 --- a/arch/ppc/platforms/pq2ads.c +++ b/arch/ppc/platforms/pq2ads.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PQ2ADS platform support | 4 | * PQ2ADS platform support |
5 | * | 5 | * |
6 | * Author: Kumar Gala <kumar.gala@freescale.com> | 6 | * Author: Kumar Gala <galak@kernel.crashing.org> |
7 | * Derived from: est8260_setup.c by Allen Curtis | 7 | * Derived from: est8260_setup.c by Allen Curtis |
8 | * | 8 | * |
9 | * Copyright 2004 Freescale Semiconductor, Inc. | 9 | * Copyright 2004 Freescale Semiconductor, Inc. |
diff --git a/arch/ppc/syslib/ipic.h b/arch/ppc/syslib/ipic.h index 2b56a4fcf373..a7ce7da8785c 100644 --- a/arch/ppc/syslib/ipic.h +++ b/arch/ppc/syslib/ipic.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * IPIC private definitions and structure. | 4 | * IPIC private definitions and structure. |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor, Inc | 8 | * Copyright 2005 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index f43fbf9a9389..847df4409982 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83xx Device descriptions | 4 | * MPC83xx Device descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc83xx_sys.c b/arch/ppc/syslib/mpc83xx_sys.c index da743446789b..a1523989aff4 100644 --- a/arch/ppc/syslib/mpc83xx_sys.c +++ b/arch/ppc/syslib/mpc83xx_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83xx System descriptions | 4 | * MPC83xx System descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c index 2ede677a0a53..69949d255658 100644 --- a/arch/ppc/syslib/mpc85xx_devices.c +++ b/arch/ppc/syslib/mpc85xx_devices.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx Device descriptions | 4 | * MPC85xx Device descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc85xx_sys.c b/arch/ppc/syslib/mpc85xx_sys.c index cb68d8c58348..397cfbcce5ea 100644 --- a/arch/ppc/syslib/mpc85xx_sys.c +++ b/arch/ppc/syslib/mpc85xx_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx System descriptions | 4 | * MPC85xx System descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c index 2b5f0e701687..92dc98b36bde 100644 --- a/arch/ppc/syslib/mpc8xx_devices.c +++ b/arch/ppc/syslib/mpc8xx_devices.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8xx Device descriptions | 4 | * MPC8xx Device descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug<vbordug@ru.mvista.com> | 8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug<vbordug@ru.mvista.com> |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c index 3cc27d29e3af..d3c617521603 100644 --- a/arch/ppc/syslib/mpc8xx_sys.c +++ b/arch/ppc/syslib/mpc8xx_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8xx System descriptions | 4 | * MPC8xx System descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> | 8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c index 4da168a6ad03..1b5fe9e398d4 100644 --- a/arch/ppc/syslib/ppc83xx_setup.c +++ b/arch/ppc/syslib/ppc83xx_setup.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83XX common board code | 4 | * MPC83XX common board code |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc83xx_setup.h b/arch/ppc/syslib/ppc83xx_setup.h index c766c1a5f786..a122a7322e5e 100644 --- a/arch/ppc/syslib/ppc83xx_setup.h +++ b/arch/ppc/syslib/ppc83xx_setup.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83XX common board definitions | 4 | * MPC83XX common board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc85xx_common.c b/arch/ppc/syslib/ppc85xx_common.c index da841dacdc13..19ad537225e4 100644 --- a/arch/ppc/syslib/ppc85xx_common.c +++ b/arch/ppc/syslib/ppc85xx_common.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx support routines | 4 | * MPC85xx support routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc85xx_common.h b/arch/ppc/syslib/ppc85xx_common.h index 2c8f304441bf..94edf32151dd 100644 --- a/arch/ppc/syslib/ppc85xx_common.h +++ b/arch/ppc/syslib/ppc85xx_common.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx support routines | 4 | * MPC85xx support routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c index de2f90576577..1a47ff4b831d 100644 --- a/arch/ppc/syslib/ppc85xx_setup.c +++ b/arch/ppc/syslib/ppc85xx_setup.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85XX common board code | 4 | * MPC85XX common board code |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc85xx_setup.h b/arch/ppc/syslib/ppc85xx_setup.h index 6e6cfe162faf..e340b0545fb5 100644 --- a/arch/ppc/syslib/ppc85xx_setup.h +++ b/arch/ppc/syslib/ppc85xx_setup.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85XX common board definitions | 4 | * MPC85XX common board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c index 603f01190816..c0b93c4191ee 100644 --- a/arch/ppc/syslib/ppc_sys.c +++ b/arch/ppc/syslib/ppc_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PPC System library functions | 4 | * PPC System library functions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * Copyright 2005 MontaVista, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> | 9 | * Copyright 2005 MontaVista, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> |
diff --git a/arch/ppc/syslib/pq2_devices.c b/arch/ppc/syslib/pq2_devices.c index e960fe935325..6ff3aab82fc3 100644 --- a/arch/ppc/syslib/pq2_devices.c +++ b/arch/ppc/syslib/pq2_devices.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PQ2 Device descriptions | 4 | * PQ2 Device descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * This file is licensed under the terms of the GNU General Public License | 8 | * This file is licensed under the terms of the GNU General Public License |
9 | * version 2. This program is licensed "as is" without any warranty of any | 9 | * version 2. This program is licensed "as is" without any warranty of any |
diff --git a/arch/ppc/syslib/pq2_sys.c b/arch/ppc/syslib/pq2_sys.c index 7b6c9ebdb9e3..36d6e2179940 100644 --- a/arch/ppc/syslib/pq2_sys.c +++ b/arch/ppc/syslib/pq2_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PQ2 System descriptions | 4 | * PQ2 System descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * This file is licensed under the terms of the GNU General Public License | 8 | * This file is licensed under the terms of the GNU General Public License |
9 | * version 2. This program is licensed "as is" without any warranty of any | 9 | * version 2. This program is licensed "as is" without any warranty of any |
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index fbad2c360784..47cc26e78957 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c | |||
@@ -1261,6 +1261,7 @@ prom_n_addr_cells(struct device_node* np) | |||
1261 | /* No #address-cells property for the root node, default to 1 */ | 1261 | /* No #address-cells property for the root node, default to 1 */ |
1262 | return 1; | 1262 | return 1; |
1263 | } | 1263 | } |
1264 | EXPORT_SYMBOL_GPL(prom_n_addr_cells); | ||
1264 | 1265 | ||
1265 | int | 1266 | int |
1266 | prom_n_size_cells(struct device_node* np) | 1267 | prom_n_size_cells(struct device_node* np) |
@@ -1276,6 +1277,7 @@ prom_n_size_cells(struct device_node* np) | |||
1276 | /* No #size-cells property for the root node, default to 1 */ | 1277 | /* No #size-cells property for the root node, default to 1 */ |
1277 | return 1; | 1278 | return 1; |
1278 | } | 1279 | } |
1280 | EXPORT_SYMBOL_GPL(prom_n_size_cells); | ||
1279 | 1281 | ||
1280 | /** | 1282 | /** |
1281 | * Work out the sense (active-low level / active-high edge) | 1283 | * Work out the sense (active-low level / active-high edge) |
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c index 2e64e8c3e8e5..cb3cf0f22822 100644 --- a/arch/sparc/lib/atomic32.c +++ b/arch/sparc/lib/atomic32.c | |||
@@ -37,17 +37,43 @@ int __atomic_add_return(int i, atomic_t *v) | |||
37 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); | 37 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); |
38 | return ret; | 38 | return ret; |
39 | } | 39 | } |
40 | EXPORT_SYMBOL(__atomic_add_return); | ||
40 | 41 | ||
41 | void atomic_set(atomic_t *v, int i) | 42 | int atomic_cmpxchg(atomic_t *v, int old, int new) |
42 | { | 43 | { |
44 | int ret; | ||
43 | unsigned long flags; | 45 | unsigned long flags; |
46 | |||
44 | spin_lock_irqsave(ATOMIC_HASH(v), flags); | 47 | spin_lock_irqsave(ATOMIC_HASH(v), flags); |
48 | ret = v->counter; | ||
49 | if (likely(ret == old)) | ||
50 | v->counter = new; | ||
45 | 51 | ||
46 | v->counter = i; | 52 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); |
53 | return ret; | ||
54 | } | ||
55 | |||
56 | int atomic_add_unless(atomic_t *v, int a, int u) | ||
57 | { | ||
58 | int ret; | ||
59 | unsigned long flags; | ||
47 | 60 | ||
61 | spin_lock_irqsave(ATOMIC_HASH(v), flags); | ||
62 | ret = v->counter; | ||
63 | if (ret != u) | ||
64 | v->counter += a; | ||
48 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); | 65 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); |
66 | return ret != u; | ||
49 | } | 67 | } |
50 | 68 | ||
51 | EXPORT_SYMBOL(__atomic_add_return); | 69 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) |
52 | EXPORT_SYMBOL(atomic_set); | 70 | /* Atomic operations are already serializing */ |
71 | void atomic_set(atomic_t *v, int i) | ||
72 | { | ||
73 | unsigned long flags; | ||
53 | 74 | ||
75 | spin_lock_irqsave(ATOMIC_HASH(v), flags); | ||
76 | v->counter = i; | ||
77 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); | ||
78 | } | ||
79 | EXPORT_SYMBOL(atomic_set); | ||
diff --git a/arch/sparc/lib/bitext.c b/arch/sparc/lib/bitext.c index 94b05e8c906c..2e168d16547f 100644 --- a/arch/sparc/lib/bitext.c +++ b/arch/sparc/lib/bitext.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
13 | #include <linux/string.h> | ||
13 | #include <linux/bitops.h> | 14 | #include <linux/bitops.h> |
14 | 15 | ||
15 | #include <asm/bitext.h> | 16 | #include <asm/bitext.h> |
diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 3b5f47c46907..563301fe5df8 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig | |||
@@ -7,7 +7,6 @@ config UML | |||
7 | bool | 7 | bool |
8 | default y | 8 | default y |
9 | 9 | ||
10 | # XXX: does UM have a mmu/swap? | ||
11 | config MMU | 10 | config MMU |
12 | bool | 11 | bool |
13 | default y | 12 | default y |
@@ -36,12 +35,6 @@ config IRQ_RELEASE_METHOD | |||
36 | bool | 35 | bool |
37 | default y | 36 | default y |
38 | 37 | ||
39 | menu "Host processor type and features" | ||
40 | |||
41 | source "arch/i386/Kconfig.cpu" | ||
42 | |||
43 | endmenu | ||
44 | |||
45 | menu "UML-specific options" | 38 | menu "UML-specific options" |
46 | 39 | ||
47 | config MODE_TT | 40 | config MODE_TT |
@@ -209,7 +202,8 @@ config MAGIC_SYSRQ | |||
209 | config SMP | 202 | config SMP |
210 | bool "Symmetric multi-processing support (EXPERIMENTAL)" | 203 | bool "Symmetric multi-processing support (EXPERIMENTAL)" |
211 | default n | 204 | default n |
212 | depends on (MODE_TT && EXPERIMENTAL && !SMP_BROKEN) || (BROKEN && SMP_BROKEN) | 205 | #SMP_BROKEN is for x86_64. |
206 | depends on MODE_TT && EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN)) | ||
213 | help | 207 | help |
214 | This option enables UML SMP support. | 208 | This option enables UML SMP support. |
215 | It is NOT related to having a real SMP box. Not directly, at least. | 209 | It is NOT related to having a real SMP box. Not directly, at least. |
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index 5d92cacd56c6..c71b39a677aa 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 | |||
@@ -1,3 +1,9 @@ | |||
1 | menu "Host processor type and features" | ||
2 | |||
3 | source "arch/i386/Kconfig.cpu" | ||
4 | |||
5 | endmenu | ||
6 | |||
1 | config UML_X86 | 7 | config UML_X86 |
2 | bool | 8 | bool |
3 | default y | 9 | default y |
@@ -42,7 +48,3 @@ config ARCH_HAS_SC_SIGNALS | |||
42 | config ARCH_REUSE_HOST_VSYSCALL_AREA | 48 | config ARCH_REUSE_HOST_VSYSCALL_AREA |
43 | bool | 49 | bool |
44 | default y | 50 | default y |
45 | |||
46 | config X86_CMPXCHG | ||
47 | bool | ||
48 | default y | ||
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 1f7dcb064aee..7a0e04e34bf9 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 | |||
@@ -35,4 +35,3 @@ cflags-y += $(call cc-option,-mpreferred-stack-boundary=2) | |||
35 | 35 | ||
36 | CFLAGS += $(cflags-y) | 36 | CFLAGS += $(cflags-y) |
37 | USER_CFLAGS += $(cflags-y) | 37 | USER_CFLAGS += $(cflags-y) |
38 | |||
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 16e7dc89f61d..5b58fad45290 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c | |||
@@ -89,8 +89,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data) | |||
89 | return(-EIO); | 89 | return(-EIO); |
90 | } | 90 | } |
91 | 91 | ||
92 | static int not_configged_console_write(int fd, const char *buf, int len, | 92 | static int not_configged_console_write(int fd, const char *buf, int len) |
93 | void *data) | ||
94 | { | 93 | { |
95 | my_puts("Using a channel type which is configured out of " | 94 | my_puts("Using a channel type which is configured out of " |
96 | "UML\n"); | 95 | "UML\n"); |
@@ -299,7 +298,7 @@ int console_write_chan(struct list_head *chans, const char *buf, int len) | |||
299 | chan = list_entry(ele, struct chan, list); | 298 | chan = list_entry(ele, struct chan, list); |
300 | if(!chan->output || (chan->ops->console_write == NULL)) | 299 | if(!chan->output || (chan->ops->console_write == NULL)) |
301 | continue; | 300 | continue; |
302 | n = chan->ops->console_write(chan->fd, buf, len, chan->data); | 301 | n = chan->ops->console_write(chan->fd, buf, len); |
303 | if(chan->primary) ret = n; | 302 | if(chan->primary) ret = n; |
304 | } | 303 | } |
305 | return(ret); | 304 | return(ret); |
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 1c55d5802489..5d50d4a44abf 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include "choose-mode.h" | 20 | #include "choose-mode.h" |
21 | #include "mode.h" | 21 | #include "mode.h" |
22 | 22 | ||
23 | int generic_console_write(int fd, const char *buf, int n, void *unused) | 23 | int generic_console_write(int fd, const char *buf, int n) |
24 | { | 24 | { |
25 | struct termios save, new; | 25 | struct termios save, new; |
26 | int err; | 26 | int err; |
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index c1b03f7c1daa..1bb085b2824d 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c | |||
@@ -98,7 +98,7 @@ static int connect_to_switch(struct daemon_data *pri) | |||
98 | printk("daemon_open : control setup request failed, err = %d\n", | 98 | printk("daemon_open : control setup request failed, err = %d\n", |
99 | -n); | 99 | -n); |
100 | err = -ENOTCONN; | 100 | err = -ENOTCONN; |
101 | goto out; | 101 | goto out_free; |
102 | } | 102 | } |
103 | 103 | ||
104 | n = os_read_file(pri->control, sun, sizeof(*sun)); | 104 | n = os_read_file(pri->control, sun, sizeof(*sun)); |
@@ -106,12 +106,14 @@ static int connect_to_switch(struct daemon_data *pri) | |||
106 | printk("daemon_open : read of data socket failed, err = %d\n", | 106 | printk("daemon_open : read of data socket failed, err = %d\n", |
107 | -n); | 107 | -n); |
108 | err = -ENOTCONN; | 108 | err = -ENOTCONN; |
109 | goto out_close; | 109 | goto out_free; |
110 | } | 110 | } |
111 | 111 | ||
112 | pri->data_addr = sun; | 112 | pri->data_addr = sun; |
113 | return(fd); | 113 | return(fd); |
114 | 114 | ||
115 | out_free: | ||
116 | kfree(sun); | ||
115 | out_close: | 117 | out_close: |
116 | os_close_file(fd); | 118 | os_close_file(fd); |
117 | out: | 119 | out: |
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index f0b888f66e05..3296e86a03a5 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c | |||
@@ -76,13 +76,6 @@ static void fd_close(int fd, void *d) | |||
76 | } | 76 | } |
77 | } | 77 | } |
78 | 78 | ||
79 | static int fd_console_write(int fd, const char *buf, int n, void *d) | ||
80 | { | ||
81 | struct fd_chan *data = d; | ||
82 | |||
83 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
84 | } | ||
85 | |||
86 | struct chan_ops fd_ops = { | 79 | struct chan_ops fd_ops = { |
87 | .type = "fd", | 80 | .type = "fd", |
88 | .init = fd_init, | 81 | .init = fd_init, |
@@ -90,7 +83,7 @@ struct chan_ops fd_ops = { | |||
90 | .close = fd_close, | 83 | .close = fd_close, |
91 | .read = generic_read, | 84 | .read = generic_read, |
92 | .write = generic_write, | 85 | .write = generic_write, |
93 | .console_write = fd_console_write, | 86 | .console_write = generic_console_write, |
94 | .window_size = generic_window_size, | 87 | .window_size = generic_window_size, |
95 | .free = generic_free, | 88 | .free = generic_free, |
96 | .winch = 1, | 89 | .winch = 1, |
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 5db136e2651c..afe85bfa66e0 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c | |||
@@ -54,7 +54,7 @@ static int mcast_open(void *data) | |||
54 | struct mcast_data *pri = data; | 54 | struct mcast_data *pri = data; |
55 | struct sockaddr_in *sin = pri->mcast_addr; | 55 | struct sockaddr_in *sin = pri->mcast_addr; |
56 | struct ip_mreq mreq; | 56 | struct ip_mreq mreq; |
57 | int fd, yes = 1, err = 0; | 57 | int fd, yes = 1, err = -EINVAL; |
58 | 58 | ||
59 | 59 | ||
60 | if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) | 60 | if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) |
@@ -63,40 +63,40 @@ static int mcast_open(void *data) | |||
63 | fd = socket(AF_INET, SOCK_DGRAM, 0); | 63 | fd = socket(AF_INET, SOCK_DGRAM, 0); |
64 | 64 | ||
65 | if (fd < 0){ | 65 | if (fd < 0){ |
66 | err = -errno; | ||
66 | printk("mcast_open : data socket failed, errno = %d\n", | 67 | printk("mcast_open : data socket failed, errno = %d\n", |
67 | errno); | 68 | errno); |
68 | err = -errno; | ||
69 | goto out; | 69 | goto out; |
70 | } | 70 | } |
71 | 71 | ||
72 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { | 72 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { |
73 | err = -errno; | ||
73 | printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", | 74 | printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", |
74 | errno); | 75 | errno); |
75 | err = -errno; | ||
76 | goto out_close; | 76 | goto out_close; |
77 | } | 77 | } |
78 | 78 | ||
79 | /* set ttl according to config */ | 79 | /* set ttl according to config */ |
80 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, | 80 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, |
81 | sizeof(pri->ttl)) < 0) { | 81 | sizeof(pri->ttl)) < 0) { |
82 | err = -errno; | ||
82 | printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", | 83 | printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", |
83 | errno); | 84 | errno); |
84 | err = -errno; | ||
85 | goto out_close; | 85 | goto out_close; |
86 | } | 86 | } |
87 | 87 | ||
88 | /* set LOOP, so data does get fed back to local sockets */ | 88 | /* set LOOP, so data does get fed back to local sockets */ |
89 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { | 89 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { |
90 | err = -errno; | ||
90 | printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", | 91 | printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", |
91 | errno); | 92 | errno); |
92 | err = -errno; | ||
93 | goto out_close; | 93 | goto out_close; |
94 | } | 94 | } |
95 | 95 | ||
96 | /* bind socket to mcast address */ | 96 | /* bind socket to mcast address */ |
97 | if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { | 97 | if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { |
98 | printk("mcast_open : data bind failed, errno = %d\n", errno); | ||
99 | err = -errno; | 98 | err = -errno; |
99 | printk("mcast_open : data bind failed, errno = %d\n", errno); | ||
100 | goto out_close; | 100 | goto out_close; |
101 | } | 101 | } |
102 | 102 | ||
@@ -105,22 +105,22 @@ static int mcast_open(void *data) | |||
105 | mreq.imr_interface.s_addr = 0; | 105 | mreq.imr_interface.s_addr = 0; |
106 | if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, | 106 | if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, |
107 | &mreq, sizeof(mreq)) < 0) { | 107 | &mreq, sizeof(mreq)) < 0) { |
108 | err = -errno; | ||
108 | printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", | 109 | printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", |
109 | errno); | 110 | errno); |
110 | printk("There appears not to be a multicast-capable network " | 111 | printk("There appears not to be a multicast-capable network " |
111 | "interface on the host.\n"); | 112 | "interface on the host.\n"); |
112 | printk("eth0 should be configured in order to use the " | 113 | printk("eth0 should be configured in order to use the " |
113 | "multicast transport.\n"); | 114 | "multicast transport.\n"); |
114 | err = -errno; | 115 | goto out_close; |
115 | goto out_close; | ||
116 | } | 116 | } |
117 | 117 | ||
118 | return fd; | 118 | return fd; |
119 | 119 | ||
120 | out_close: | 120 | out_close: |
121 | os_close_file(fd); | 121 | os_close_file(fd); |
122 | out: | 122 | out: |
123 | return err; | 123 | return err; |
124 | } | 124 | } |
125 | 125 | ||
126 | static void mcast_close(int fd, void *data) | 126 | static void mcast_close(int fd, void *data) |
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index ed4a1a6c5d83..c43e8bb32502 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c | |||
@@ -100,13 +100,6 @@ static void port_close(int fd, void *d) | |||
100 | os_close_file(fd); | 100 | os_close_file(fd); |
101 | } | 101 | } |
102 | 102 | ||
103 | static int port_console_write(int fd, const char *buf, int n, void *d) | ||
104 | { | ||
105 | struct port_chan *data = d; | ||
106 | |||
107 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
108 | } | ||
109 | |||
110 | struct chan_ops port_ops = { | 103 | struct chan_ops port_ops = { |
111 | .type = "port", | 104 | .type = "port", |
112 | .init = port_init, | 105 | .init = port_init, |
@@ -114,7 +107,7 @@ struct chan_ops port_ops = { | |||
114 | .close = port_close, | 107 | .close = port_close, |
115 | .read = generic_read, | 108 | .read = generic_read, |
116 | .write = generic_write, | 109 | .write = generic_write, |
117 | .console_write = port_console_write, | 110 | .console_write = generic_console_write, |
118 | .window_size = generic_window_size, | 111 | .window_size = generic_window_size, |
119 | .free = port_free, | 112 | .free = port_free, |
120 | .winch = 1, | 113 | .winch = 1, |
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index 0306a1b215b7..1c555c38de4d 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c | |||
@@ -118,13 +118,6 @@ static int pty_open(int input, int output, int primary, void *d, | |||
118 | return(fd); | 118 | return(fd); |
119 | } | 119 | } |
120 | 120 | ||
121 | static int pty_console_write(int fd, const char *buf, int n, void *d) | ||
122 | { | ||
123 | struct pty_chan *data = d; | ||
124 | |||
125 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
126 | } | ||
127 | |||
128 | struct chan_ops pty_ops = { | 121 | struct chan_ops pty_ops = { |
129 | .type = "pty", | 122 | .type = "pty", |
130 | .init = pty_chan_init, | 123 | .init = pty_chan_init, |
@@ -132,7 +125,7 @@ struct chan_ops pty_ops = { | |||
132 | .close = generic_close, | 125 | .close = generic_close, |
133 | .read = generic_read, | 126 | .read = generic_read, |
134 | .write = generic_write, | 127 | .write = generic_write, |
135 | .console_write = pty_console_write, | 128 | .console_write = generic_console_write, |
136 | .window_size = generic_window_size, | 129 | .window_size = generic_window_size, |
137 | .free = generic_free, | 130 | .free = generic_free, |
138 | .winch = 0, | 131 | .winch = 0, |
@@ -145,7 +138,7 @@ struct chan_ops pts_ops = { | |||
145 | .close = generic_close, | 138 | .close = generic_close, |
146 | .read = generic_read, | 139 | .read = generic_read, |
147 | .write = generic_write, | 140 | .write = generic_write, |
148 | .console_write = pty_console_write, | 141 | .console_write = generic_console_write, |
149 | .window_size = generic_window_size, | 142 | .window_size = generic_window_size, |
150 | .free = generic_free, | 143 | .free = generic_free, |
151 | .winch = 0, | 144 | .winch = 0, |
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index 6fbb670ee274..94c9265a4f2c 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c | |||
@@ -60,13 +60,6 @@ static int tty_open(int input, int output, int primary, void *d, | |||
60 | return(fd); | 60 | return(fd); |
61 | } | 61 | } |
62 | 62 | ||
63 | static int tty_console_write(int fd, const char *buf, int n, void *d) | ||
64 | { | ||
65 | struct tty_chan *data = d; | ||
66 | |||
67 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
68 | } | ||
69 | |||
70 | struct chan_ops tty_ops = { | 63 | struct chan_ops tty_ops = { |
71 | .type = "tty", | 64 | .type = "tty", |
72 | .init = tty_chan_init, | 65 | .init = tty_chan_init, |
@@ -74,7 +67,7 @@ struct chan_ops tty_ops = { | |||
74 | .close = generic_close, | 67 | .close = generic_close, |
75 | .read = generic_read, | 68 | .read = generic_read, |
76 | .write = generic_write, | 69 | .write = generic_write, |
77 | .console_write = tty_console_write, | 70 | .console_write = generic_console_write, |
78 | .window_size = generic_window_size, | 71 | .window_size = generic_window_size, |
79 | .free = generic_free, | 72 | .free = generic_free, |
80 | .winch = 0, | 73 | .winch = 0, |
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index b530f1a6540d..aaa636661043 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c | |||
@@ -194,13 +194,6 @@ static void xterm_free(void *d) | |||
194 | free(d); | 194 | free(d); |
195 | } | 195 | } |
196 | 196 | ||
197 | static int xterm_console_write(int fd, const char *buf, int n, void *d) | ||
198 | { | ||
199 | struct xterm_chan *data = d; | ||
200 | |||
201 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
202 | } | ||
203 | |||
204 | struct chan_ops xterm_ops = { | 197 | struct chan_ops xterm_ops = { |
205 | .type = "xterm", | 198 | .type = "xterm", |
206 | .init = xterm_init, | 199 | .init = xterm_init, |
@@ -208,7 +201,7 @@ struct chan_ops xterm_ops = { | |||
208 | .close = xterm_close, | 201 | .close = xterm_close, |
209 | .read = generic_read, | 202 | .read = generic_read, |
210 | .write = generic_write, | 203 | .write = generic_write, |
211 | .console_write = xterm_console_write, | 204 | .console_write = generic_console_write, |
212 | .window_size = generic_window_size, | 205 | .window_size = generic_window_size, |
213 | .free = xterm_free, | 206 | .free = xterm_free, |
214 | .winch = 1, | 207 | .winch = 1, |
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h index f77d9aa4c164..659bb3cac32f 100644 --- a/arch/um/include/chan_user.h +++ b/arch/um/include/chan_user.h | |||
@@ -25,7 +25,7 @@ struct chan_ops { | |||
25 | void (*close)(int, void *); | 25 | void (*close)(int, void *); |
26 | int (*read)(int, char *, void *); | 26 | int (*read)(int, char *, void *); |
27 | int (*write)(int, const char *, int, void *); | 27 | int (*write)(int, const char *, int, void *); |
28 | int (*console_write)(int, const char *, int, void *); | 28 | int (*console_write)(int, const char *, int); |
29 | int (*window_size)(int, void *, unsigned short *, unsigned short *); | 29 | int (*window_size)(int, void *, unsigned short *, unsigned short *); |
30 | void (*free)(void *); | 30 | void (*free)(void *); |
31 | int winch; | 31 | int winch; |
@@ -37,7 +37,7 @@ extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops, | |||
37 | extern void generic_close(int fd, void *unused); | 37 | extern void generic_close(int fd, void *unused); |
38 | extern int generic_read(int fd, char *c_out, void *unused); | 38 | extern int generic_read(int fd, char *c_out, void *unused); |
39 | extern int generic_write(int fd, const char *buf, int n, void *unused); | 39 | extern int generic_write(int fd, const char *buf, int n, void *unused); |
40 | extern int generic_console_write(int fd, const char *buf, int n, void *state); | 40 | extern int generic_console_write(int fd, const char *buf, int n); |
41 | extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, | 41 | extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, |
42 | unsigned short *cols_out); | 42 | unsigned short *cols_out); |
43 | extern void generic_free(void *data); | 43 | extern void generic_free(void *data); |
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h index 84c0868cd561..f8760a3f43b0 100644 --- a/arch/um/include/um_uaccess.h +++ b/arch/um/include/um_uaccess.h | |||
@@ -17,8 +17,25 @@ | |||
17 | #include "uaccess-skas.h" | 17 | #include "uaccess-skas.h" |
18 | #endif | 18 | #endif |
19 | 19 | ||
20 | #define __under_task_size(addr, size) \ | ||
21 | (((unsigned long) (addr) < TASK_SIZE) && \ | ||
22 | (((unsigned long) (addr) + (size)) < TASK_SIZE)) | ||
23 | |||
24 | #define __access_ok_vsyscall(type, addr, size) \ | ||
25 | ((type == VERIFY_READ) && \ | ||
26 | ((unsigned long) (addr) >= FIXADDR_USER_START) && \ | ||
27 | ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ | ||
28 | ((unsigned long) (addr) + (size) >= (unsigned long)(addr))) | ||
29 | |||
30 | #define __addr_range_nowrap(addr, size) \ | ||
31 | ((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) | ||
32 | |||
20 | #define access_ok(type, addr, size) \ | 33 | #define access_ok(type, addr, size) \ |
21 | CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size) | 34 | (__addr_range_nowrap(addr, size) && \ |
35 | (__under_task_size(addr, size) || \ | ||
36 | __access_ok_vsyscall(type, addr, size) || \ | ||
37 | segment_eq(get_fs(), KERNEL_DS) || \ | ||
38 | CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size))) | ||
22 | 39 | ||
23 | static inline int copy_from_user(void *to, const void __user *from, int n) | 40 | static inline int copy_from_user(void *to, const void __user *from, int n) |
24 | { | 41 | { |
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h index 7da0c2def0ef..f611f83ad4ff 100644 --- a/arch/um/kernel/skas/include/uaccess-skas.h +++ b/arch/um/kernel/skas/include/uaccess-skas.h | |||
@@ -9,14 +9,8 @@ | |||
9 | #include "asm/errno.h" | 9 | #include "asm/errno.h" |
10 | #include "asm/fixmap.h" | 10 | #include "asm/fixmap.h" |
11 | 11 | ||
12 | #define access_ok_skas(type, addr, size) \ | 12 | /* No SKAS-specific checking. */ |
13 | ((segment_eq(get_fs(), KERNEL_DS)) || \ | 13 | #define access_ok_skas(type, addr, size) 0 |
14 | (((unsigned long) (addr) < TASK_SIZE) && \ | ||
15 | ((unsigned long) (addr) + (size) <= TASK_SIZE)) || \ | ||
16 | ((type == VERIFY_READ ) && \ | ||
17 | ((unsigned long) (addr) >= FIXADDR_USER_START) && \ | ||
18 | ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ | ||
19 | ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))) | ||
20 | 14 | ||
21 | extern int copy_from_user_skas(void *to, const void __user *from, int n); | 15 | extern int copy_from_user_skas(void *to, const void __user *from, int n); |
22 | extern int copy_to_user_skas(void __user *to, const void *from, int n); | 16 | extern int copy_to_user_skas(void __user *to, const void *from, int n); |
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 75195281081e..a5a47528dec7 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c | |||
@@ -143,7 +143,7 @@ int copy_from_user_skas(void *to, const void __user *from, int n) | |||
143 | return(0); | 143 | return(0); |
144 | } | 144 | } |
145 | 145 | ||
146 | return(access_ok_skas(VERIFY_READ, from, n) ? | 146 | return(access_ok(VERIFY_READ, from, n) ? |
147 | buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): | 147 | buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): |
148 | n); | 148 | n); |
149 | } | 149 | } |
@@ -164,7 +164,7 @@ int copy_to_user_skas(void __user *to, const void *from, int n) | |||
164 | return(0); | 164 | return(0); |
165 | } | 165 | } |
166 | 166 | ||
167 | return(access_ok_skas(VERIFY_WRITE, to, n) ? | 167 | return(access_ok(VERIFY_WRITE, to, n) ? |
168 | buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : | 168 | buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : |
169 | n); | 169 | n); |
170 | } | 170 | } |
@@ -193,7 +193,7 @@ int strncpy_from_user_skas(char *dst, const char __user *src, int count) | |||
193 | return(strnlen(dst, count)); | 193 | return(strnlen(dst, count)); |
194 | } | 194 | } |
195 | 195 | ||
196 | if(!access_ok_skas(VERIFY_READ, src, 1)) | 196 | if(!access_ok(VERIFY_READ, src, 1)) |
197 | return(-EFAULT); | 197 | return(-EFAULT); |
198 | 198 | ||
199 | n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, | 199 | n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, |
@@ -221,7 +221,7 @@ int clear_user_skas(void __user *mem, int len) | |||
221 | return(0); | 221 | return(0); |
222 | } | 222 | } |
223 | 223 | ||
224 | return(access_ok_skas(VERIFY_WRITE, mem, len) ? | 224 | return(access_ok(VERIFY_WRITE, mem, len) ? |
225 | buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); | 225 | buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); |
226 | } | 226 | } |
227 | 227 | ||
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 95c8f8733baf..0d4c10a73607 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c | |||
@@ -95,7 +95,16 @@ survive: | |||
95 | pte = pte_offset_kernel(pmd, address); | 95 | pte = pte_offset_kernel(pmd, address); |
96 | } while(!pte_present(*pte)); | 96 | } while(!pte_present(*pte)); |
97 | err = 0; | 97 | err = 0; |
98 | /* The below warning was added in place of | ||
99 | * pte_mkyoung(); if (is_write) pte_mkdirty(); | ||
100 | * If it's triggered, we'd see normally a hang here (a clean pte is | ||
101 | * marked read-only to emulate the dirty bit). | ||
102 | * However, the generic code can mark a PTE writable but clean on a | ||
103 | * concurrent read fault, triggering this harmlessly. So comment it out. | ||
104 | */ | ||
105 | #if 0 | ||
98 | WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte))); | 106 | WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte))); |
107 | #endif | ||
99 | flush_tlb_page(vma, address); | 108 | flush_tlb_page(vma, address); |
100 | out: | 109 | out: |
101 | up_read(&mm->mmap_sem); | 110 | up_read(&mm->mmap_sem); |
diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h index dc2ebfa8c54f..b9bfe9c481c4 100644 --- a/arch/um/kernel/tt/include/uaccess-tt.h +++ b/arch/um/kernel/tt/include/uaccess-tt.h | |||
@@ -19,19 +19,13 @@ | |||
19 | extern unsigned long end_vm; | 19 | extern unsigned long end_vm; |
20 | extern unsigned long uml_physmem; | 20 | extern unsigned long uml_physmem; |
21 | 21 | ||
22 | #define under_task_size(addr, size) \ | ||
23 | (((unsigned long) (addr) < TASK_SIZE) && \ | ||
24 | (((unsigned long) (addr) + (size)) < TASK_SIZE)) | ||
25 | |||
26 | #define is_stack(addr, size) \ | 22 | #define is_stack(addr, size) \ |
27 | (((unsigned long) (addr) < STACK_TOP) && \ | 23 | (((unsigned long) (addr) < STACK_TOP) && \ |
28 | ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ | 24 | ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ |
29 | (((unsigned long) (addr) + (size)) <= STACK_TOP)) | 25 | (((unsigned long) (addr) + (size)) <= STACK_TOP)) |
30 | 26 | ||
31 | #define access_ok_tt(type, addr, size) \ | 27 | #define access_ok_tt(type, addr, size) \ |
32 | ((type == VERIFY_READ) || (segment_eq(get_fs(), KERNEL_DS)) || \ | 28 | (is_stack(addr, size)) |
33 | (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ | ||
34 | (under_task_size(addr, size) || is_stack(addr, size)))) | ||
35 | 29 | ||
36 | extern unsigned long get_fault_addr(void); | 30 | extern unsigned long get_fault_addr(void); |
37 | 31 | ||
diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c index a72aa632972f..1cb60726567e 100644 --- a/arch/um/kernel/tt/uaccess.c +++ b/arch/um/kernel/tt/uaccess.c | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | int copy_from_user_tt(void *to, const void __user *from, int n) | 9 | int copy_from_user_tt(void *to, const void __user *from, int n) |
10 | { | 10 | { |
11 | if(!access_ok_tt(VERIFY_READ, from, n)) | 11 | if(!access_ok(VERIFY_READ, from, n)) |
12 | return(n); | 12 | return(n); |
13 | 13 | ||
14 | return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, | 14 | return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, |
@@ -17,7 +17,7 @@ int copy_from_user_tt(void *to, const void __user *from, int n) | |||
17 | 17 | ||
18 | int copy_to_user_tt(void __user *to, const void *from, int n) | 18 | int copy_to_user_tt(void __user *to, const void *from, int n) |
19 | { | 19 | { |
20 | if(!access_ok_tt(VERIFY_WRITE, to, n)) | 20 | if(!access_ok(VERIFY_WRITE, to, n)) |
21 | return(n); | 21 | return(n); |
22 | 22 | ||
23 | return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, | 23 | return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, |
@@ -28,7 +28,7 @@ int strncpy_from_user_tt(char *dst, const char __user *src, int count) | |||
28 | { | 28 | { |
29 | int n; | 29 | int n; |
30 | 30 | ||
31 | if(!access_ok_tt(VERIFY_READ, src, 1)) | 31 | if(!access_ok(VERIFY_READ, src, 1)) |
32 | return(-EFAULT); | 32 | return(-EFAULT); |
33 | 33 | ||
34 | n = __do_strncpy_from_user(dst, src, count, | 34 | n = __do_strncpy_from_user(dst, src, count, |
@@ -47,7 +47,7 @@ int __clear_user_tt(void __user *mem, int len) | |||
47 | 47 | ||
48 | int clear_user_tt(void __user *mem, int len) | 48 | int clear_user_tt(void __user *mem, int len) |
49 | { | 49 | { |
50 | if(!access_ok_tt(VERIFY_WRITE, mem, len)) | 50 | if(!access_ok(VERIFY_WRITE, mem, len)) |
51 | return(len); | 51 | return(len); |
52 | 52 | ||
53 | return(__do_clear_user(mem, len, ¤t->thread.fault_addr, | 53 | return(__do_clear_user(mem, len, ¤t->thread.fault_addr, |
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c index c6c9791d77c1..a9368d4c4aba 100644 --- a/arch/x86_64/kernel/i8259.c +++ b/arch/x86_64/kernel/i8259.c | |||
@@ -515,7 +515,7 @@ void i8254_timer_resume(void) | |||
515 | } | 515 | } |
516 | 516 | ||
517 | static struct sysdev_class timer_sysclass = { | 517 | static struct sysdev_class timer_sysclass = { |
518 | set_kset_name("timer"), | 518 | set_kset_name("timer_pit"), |
519 | .resume = timer_resume, | 519 | .resume = timer_resume, |
520 | }; | 520 | }; |
521 | 521 | ||
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 6a4da417c16b..606f8733a776 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
29 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
30 | #include <linux/pm.h> | 30 | #include <linux/pm.h> |
31 | #include <linux/pm_legacy.h> | ||
31 | #include <linux/device.h> | 32 | #include <linux/device.h> |
32 | #include <linux/proc_fs.h> | 33 | #include <linux/proc_fs.h> |
33 | #ifdef CONFIG_X86 | 34 | #ifdef CONFIG_X86 |
@@ -754,7 +755,7 @@ static int __init acpi_init(void) | |||
754 | result = acpi_bus_init(); | 755 | result = acpi_bus_init(); |
755 | 756 | ||
756 | if (!result) { | 757 | if (!result) { |
757 | #ifdef CONFIG_PM | 758 | #ifdef CONFIG_PM_LEGACY |
758 | if (!PM_IS_ACTIVE()) | 759 | if (!PM_IS_ACTIVE()) |
759 | pm_active = 1; | 760 | pm_active = 1; |
760 | else { | 761 | else { |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 98f6c02d6790..59dacb6552c0 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -526,18 +526,23 @@ request_firmware_work_func(void *arg) | |||
526 | { | 526 | { |
527 | struct firmware_work *fw_work = arg; | 527 | struct firmware_work *fw_work = arg; |
528 | const struct firmware *fw; | 528 | const struct firmware *fw; |
529 | int ret; | ||
529 | if (!arg) { | 530 | if (!arg) { |
530 | WARN_ON(1); | 531 | WARN_ON(1); |
531 | return 0; | 532 | return 0; |
532 | } | 533 | } |
533 | daemonize("%s/%s", "firmware", fw_work->name); | 534 | daemonize("%s/%s", "firmware", fw_work->name); |
534 | _request_firmware(&fw, fw_work->name, fw_work->device, | 535 | ret = _request_firmware(&fw, fw_work->name, fw_work->device, |
535 | fw_work->hotplug); | 536 | fw_work->hotplug); |
536 | fw_work->cont(fw, fw_work->context); | 537 | if (ret < 0) |
537 | release_firmware(fw); | 538 | fw_work->cont(NULL, fw_work->context); |
539 | else { | ||
540 | fw_work->cont(fw, fw_work->context); | ||
541 | release_firmware(fw); | ||
542 | } | ||
538 | module_put(fw_work->module); | 543 | module_put(fw_work->module); |
539 | kfree(fw_work); | 544 | kfree(fw_work); |
540 | return 0; | 545 | return ret; |
541 | } | 546 | } |
542 | 547 | ||
543 | /** | 548 | /** |
@@ -586,6 +591,8 @@ request_firmware_nowait( | |||
586 | 591 | ||
587 | if (ret < 0) { | 592 | if (ret < 0) { |
588 | fw_work->cont(NULL, fw_work->context); | 593 | fw_work->cont(NULL, fw_work->context); |
594 | module_put(fw_work->module); | ||
595 | kfree(fw_work); | ||
589 | return ret; | 596 | return ret; |
590 | } | 597 | } |
591 | return 0; | 598 | return 0; |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 59e5982a5db3..c0233efabeba 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -1188,7 +1188,7 @@ static void pkt_count_states(struct pktcdvd_device *pd, int *states) | |||
1188 | struct packet_data *pkt; | 1188 | struct packet_data *pkt; |
1189 | int i; | 1189 | int i; |
1190 | 1190 | ||
1191 | for (i = 0; i <= PACKET_NUM_STATES; i++) | 1191 | for (i = 0; i < PACKET_NUM_STATES; i++) |
1192 | states[i] = 0; | 1192 | states[i] = 0; |
1193 | 1193 | ||
1194 | spin_lock(&pd->cdrw.active_list_lock); | 1194 | spin_lock(&pd->cdrw.active_list_lock); |
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index c8255312b8c1..50947e38501a 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c | |||
@@ -557,6 +557,10 @@ static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = { | |||
557 | .device_id = PCI_DEVICE_ID_APPLE_U3H_AGP, | 557 | .device_id = PCI_DEVICE_ID_APPLE_U3H_AGP, |
558 | .chipset_name = "U3H", | 558 | .chipset_name = "U3H", |
559 | }, | 559 | }, |
560 | { | ||
561 | .device_id = PCI_DEVICE_ID_APPLE_IPID2_AGP, | ||
562 | .chipset_name = "UniNorth/Intrepid2", | ||
563 | }, | ||
560 | }; | 564 | }; |
561 | 565 | ||
562 | static int __devinit agp_uninorth_probe(struct pci_dev *pdev, | 566 | static int __devinit agp_uninorth_probe(struct pci_dev *pdev, |
diff --git a/drivers/char/pcmcia/Kconfig b/drivers/char/pcmcia/Kconfig index d22bfdc13563..27c1179ee527 100644 --- a/drivers/char/pcmcia/Kconfig +++ b/drivers/char/pcmcia/Kconfig | |||
@@ -18,5 +18,29 @@ config SYNCLINK_CS | |||
18 | The module will be called synclinkmp. If you want to do that, say M | 18 | The module will be called synclinkmp. If you want to do that, say M |
19 | here. | 19 | here. |
20 | 20 | ||
21 | config CARDMAN_4000 | ||
22 | tristate "Omnikey Cardman 4000 support" | ||
23 | depends on PCMCIA | ||
24 | help | ||
25 | Enable support for the Omnikey Cardman 4000 PCMCIA Smartcard | ||
26 | reader. | ||
27 | |||
28 | This kernel driver requires additional userspace support, either | ||
29 | by the vendor-provided PC/SC ifd_handler (http://www.omnikey.com/), | ||
30 | or via the cm4000 backend of OpenCT (http://www.opensc.com/). | ||
31 | |||
32 | config CARDMAN_4040 | ||
33 | tristate "Omnikey CardMan 4040 support" | ||
34 | depends on PCMCIA | ||
35 | help | ||
36 | Enable support for the Omnikey CardMan 4040 PCMCIA Smartcard | ||
37 | reader. | ||
38 | |||
39 | This card is basically a USB CCID device connected to a FIFO | ||
40 | in I/O space. To use the kernel driver, you will need either the | ||
41 | PC/SC ifdhandler provided from the Omnikey homepage | ||
42 | (http://www.omnikey.com/), or a current development version of OpenCT | ||
43 | (http://www.opensc.org/). | ||
44 | |||
21 | endmenu | 45 | endmenu |
22 | 46 | ||
diff --git a/drivers/char/pcmcia/Makefile b/drivers/char/pcmcia/Makefile index 1fcd4c591958..0aae20985d57 100644 --- a/drivers/char/pcmcia/Makefile +++ b/drivers/char/pcmcia/Makefile | |||
@@ -5,3 +5,5 @@ | |||
5 | # | 5 | # |
6 | 6 | ||
7 | obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o | 7 | obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o |
8 | obj-$(CONFIG_CARDMAN_4000) += cm4000_cs.o | ||
9 | obj-$(CONFIG_CARDMAN_4040) += cm4040_cs.o | ||
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c new file mode 100644 index 000000000000..ef011ef5dc46 --- /dev/null +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -0,0 +1,2078 @@ | |||
1 | /* | ||
2 | * A driver for the PCMCIA Smartcard Reader "Omnikey CardMan Mobile 4000" | ||
3 | * | ||
4 | * cm4000_cs.c support.linux@omnikey.com | ||
5 | * | ||
6 | * Tue Oct 23 11:32:43 GMT 2001 herp - cleaned up header files | ||
7 | * Sun Jan 20 10:11:15 MET 2002 herp - added modversion header files | ||
8 | * Thu Nov 14 16:34:11 GMT 2002 mh - added PPS functionality | ||
9 | * Tue Nov 19 16:36:27 GMT 2002 mh - added SUSPEND/RESUME functionailty | ||
10 | * Wed Jul 28 12:55:01 CEST 2004 mh - kernel 2.6 adjustments | ||
11 | * | ||
12 | * current version: 2.4.0gm4 | ||
13 | * | ||
14 | * (C) 2000,2001,2002,2003,2004 Omnikey AG | ||
15 | * | ||
16 | * (C) 2005 Harald Welte <laforge@gnumonks.org> | ||
17 | * - Adhere to Kernel CodingStyle | ||
18 | * - Port to 2.6.13 "new" style PCMCIA | ||
19 | * - Check for copy_{from,to}_user return values | ||
20 | * - Use nonseekable_open() | ||
21 | * | ||
22 | * All rights reserved. Licensed under dual BSD/GPL license. | ||
23 | */ | ||
24 | |||
25 | /* #define PCMCIA_DEBUG 6 */ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/fs.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <asm/uaccess.h> | ||
34 | #include <asm/io.h> | ||
35 | |||
36 | #include <pcmcia/cs_types.h> | ||
37 | #include <pcmcia/cs.h> | ||
38 | #include <pcmcia/cistpl.h> | ||
39 | #include <pcmcia/cisreg.h> | ||
40 | #include <pcmcia/ciscode.h> | ||
41 | #include <pcmcia/ds.h> | ||
42 | |||
43 | #include <linux/cm4000_cs.h> | ||
44 | |||
45 | /* #define ATR_CSUM */ | ||
46 | |||
47 | #ifdef PCMCIA_DEBUG | ||
48 | #define reader_to_dev(x) (&handle_to_dev(x->link.handle)) | ||
49 | static int pc_debug = PCMCIA_DEBUG; | ||
50 | module_param(pc_debug, int, 0600); | ||
51 | #define DEBUGP(n, rdr, x, args...) do { \ | ||
52 | if (pc_debug >= (n)) \ | ||
53 | dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x, \ | ||
54 | __FUNCTION__ , ## args); \ | ||
55 | } while (0) | ||
56 | #else | ||
57 | #define DEBUGP(n, rdr, x, args...) | ||
58 | #endif | ||
59 | static char *version = "cm4000_cs.c v2.4.0gm5 - All bugs added by Harald Welte"; | ||
60 | |||
61 | #define T_1SEC (HZ) | ||
62 | #define T_10MSEC msecs_to_jiffies(10) | ||
63 | #define T_20MSEC msecs_to_jiffies(20) | ||
64 | #define T_40MSEC msecs_to_jiffies(40) | ||
65 | #define T_50MSEC msecs_to_jiffies(50) | ||
66 | #define T_100MSEC msecs_to_jiffies(100) | ||
67 | #define T_500MSEC msecs_to_jiffies(500) | ||
68 | |||
69 | static void cm4000_detach(dev_link_t *link); | ||
70 | static void cm4000_release(dev_link_t *link); | ||
71 | |||
72 | static int major; /* major number we get from the kernel */ | ||
73 | |||
74 | /* note: the first state has to have number 0 always */ | ||
75 | |||
76 | #define M_FETCH_ATR 0 | ||
77 | #define M_TIMEOUT_WAIT 1 | ||
78 | #define M_READ_ATR_LEN 2 | ||
79 | #define M_READ_ATR 3 | ||
80 | #define M_ATR_PRESENT 4 | ||
81 | #define M_BAD_CARD 5 | ||
82 | #define M_CARDOFF 6 | ||
83 | |||
84 | #define LOCK_IO 0 | ||
85 | #define LOCK_MONITOR 1 | ||
86 | |||
87 | #define IS_AUTOPPS_ACT 6 | ||
88 | #define IS_PROCBYTE_PRESENT 7 | ||
89 | #define IS_INVREV 8 | ||
90 | #define IS_ANY_T0 9 | ||
91 | #define IS_ANY_T1 10 | ||
92 | #define IS_ATR_PRESENT 11 | ||
93 | #define IS_ATR_VALID 12 | ||
94 | #define IS_CMM_ABSENT 13 | ||
95 | #define IS_BAD_LENGTH 14 | ||
96 | #define IS_BAD_CSUM 15 | ||
97 | #define IS_BAD_CARD 16 | ||
98 | |||
99 | #define REG_FLAGS0(x) (x + 0) | ||
100 | #define REG_FLAGS1(x) (x + 1) | ||
101 | #define REG_NUM_BYTES(x) (x + 2) | ||
102 | #define REG_BUF_ADDR(x) (x + 3) | ||
103 | #define REG_BUF_DATA(x) (x + 4) | ||
104 | #define REG_NUM_SEND(x) (x + 5) | ||
105 | #define REG_BAUDRATE(x) (x + 6) | ||
106 | #define REG_STOPBITS(x) (x + 7) | ||
107 | |||
108 | struct cm4000_dev { | ||
109 | dev_link_t link; /* pcmcia link */ | ||
110 | dev_node_t node; /* OS node (major,minor) */ | ||
111 | |||
112 | unsigned char atr[MAX_ATR]; | ||
113 | unsigned char rbuf[512]; | ||
114 | unsigned char sbuf[512]; | ||
115 | |||
116 | wait_queue_head_t devq; /* when removing cardman must not be | ||
117 | zeroed! */ | ||
118 | |||
119 | wait_queue_head_t ioq; /* if IO is locked, wait on this Q */ | ||
120 | wait_queue_head_t atrq; /* wait for ATR valid */ | ||
121 | wait_queue_head_t readq; /* used by write to wake blk.read */ | ||
122 | |||
123 | /* warning: do not move this fields. | ||
124 | * initialising to zero depends on it - see ZERO_DEV below. */ | ||
125 | unsigned char atr_csum; | ||
126 | unsigned char atr_len_retry; | ||
127 | unsigned short atr_len; | ||
128 | unsigned short rlen; /* bytes avail. after write */ | ||
129 | unsigned short rpos; /* latest read pos. write zeroes */ | ||
130 | unsigned char procbyte; /* T=0 procedure byte */ | ||
131 | unsigned char mstate; /* state of card monitor */ | ||
132 | unsigned char cwarn; /* slow down warning */ | ||
133 | unsigned char flags0; /* cardman IO-flags 0 */ | ||
134 | unsigned char flags1; /* cardman IO-flags 1 */ | ||
135 | unsigned int mdelay; /* variable monitor speeds, in jiffies */ | ||
136 | |||
137 | unsigned int baudv; /* baud value for speed */ | ||
138 | unsigned char ta1; | ||
139 | unsigned char proto; /* T=0, T=1, ... */ | ||
140 | unsigned long flags; /* lock+flags (MONITOR,IO,ATR) * for concurrent | ||
141 | access */ | ||
142 | |||
143 | unsigned char pts[4]; | ||
144 | |||
145 | struct timer_list timer; /* used to keep monitor running */ | ||
146 | int monitor_running; | ||
147 | }; | ||
148 | |||
149 | #define ZERO_DEV(dev) \ | ||
150 | memset(&dev->atr_csum,0, \ | ||
151 | sizeof(struct cm4000_dev) - \ | ||
152 | /*link*/ sizeof(dev_link_t) - \ | ||
153 | /*node*/ sizeof(dev_node_t) - \ | ||
154 | /*atr*/ MAX_ATR*sizeof(char) - \ | ||
155 | /*rbuf*/ 512*sizeof(char) - \ | ||
156 | /*sbuf*/ 512*sizeof(char) - \ | ||
157 | /*queue*/ 4*sizeof(wait_queue_head_t)) | ||
158 | |||
159 | static dev_info_t dev_info = MODULE_NAME; | ||
160 | static dev_link_t *dev_table[CM4000_MAX_DEV]; | ||
161 | |||
162 | /* This table doesn't use spaces after the comma between fields and thus | ||
163 | * violates CodingStyle. However, I don't really think wrapping it around will | ||
164 | * make it any clearer to read -HW */ | ||
165 | static unsigned char fi_di_table[10][14] = { | ||
166 | /*FI 00 01 02 03 04 05 06 07 08 09 10 11 12 13 */ | ||
167 | /*DI */ | ||
168 | /* 0 */ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, | ||
169 | /* 1 */ {0x01,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x91,0x11,0x11,0x11,0x11}, | ||
170 | /* 2 */ {0x02,0x12,0x22,0x32,0x11,0x11,0x11,0x11,0x11,0x92,0xA2,0xB2,0x11,0x11}, | ||
171 | /* 3 */ {0x03,0x13,0x23,0x33,0x43,0x53,0x63,0x11,0x11,0x93,0xA3,0xB3,0xC3,0xD3}, | ||
172 | /* 4 */ {0x04,0x14,0x24,0x34,0x44,0x54,0x64,0x11,0x11,0x94,0xA4,0xB4,0xC4,0xD4}, | ||
173 | /* 5 */ {0x00,0x15,0x25,0x35,0x45,0x55,0x65,0x11,0x11,0x95,0xA5,0xB5,0xC5,0xD5}, | ||
174 | /* 6 */ {0x06,0x16,0x26,0x36,0x46,0x56,0x66,0x11,0x11,0x96,0xA6,0xB6,0xC6,0xD6}, | ||
175 | /* 7 */ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, | ||
176 | /* 8 */ {0x08,0x11,0x28,0x38,0x48,0x58,0x68,0x11,0x11,0x98,0xA8,0xB8,0xC8,0xD8}, | ||
177 | /* 9 */ {0x09,0x19,0x29,0x39,0x49,0x59,0x69,0x11,0x11,0x99,0xA9,0xB9,0xC9,0xD9} | ||
178 | }; | ||
179 | |||
180 | #ifndef PCMCIA_DEBUG | ||
181 | #define xoutb outb | ||
182 | #define xinb inb | ||
183 | #else | ||
184 | static inline void xoutb(unsigned char val, unsigned short port) | ||
185 | { | ||
186 | if (pc_debug >= 7) | ||
187 | printk(KERN_DEBUG "outb(val=%.2x,port=%.4x)\n", val, port); | ||
188 | outb(val, port); | ||
189 | } | ||
190 | static inline unsigned char xinb(unsigned short port) | ||
191 | { | ||
192 | unsigned char val; | ||
193 | |||
194 | val = inb(port); | ||
195 | if (pc_debug >= 7) | ||
196 | printk(KERN_DEBUG "%.2x=inb(%.4x)\n", val, port); | ||
197 | |||
198 | return val; | ||
199 | } | ||
200 | #endif | ||
201 | |||
202 | #define b_0000 15 | ||
203 | #define b_0001 14 | ||
204 | #define b_0010 13 | ||
205 | #define b_0011 12 | ||
206 | #define b_0100 11 | ||
207 | #define b_0101 10 | ||
208 | #define b_0110 9 | ||
209 | #define b_0111 8 | ||
210 | #define b_1000 7 | ||
211 | #define b_1001 6 | ||
212 | #define b_1010 5 | ||
213 | #define b_1011 4 | ||
214 | #define b_1100 3 | ||
215 | #define b_1101 2 | ||
216 | #define b_1110 1 | ||
217 | #define b_1111 0 | ||
218 | |||
219 | static unsigned char irtab[16] = { | ||
220 | b_0000, b_1000, b_0100, b_1100, | ||
221 | b_0010, b_1010, b_0110, b_1110, | ||
222 | b_0001, b_1001, b_0101, b_1101, | ||
223 | b_0011, b_1011, b_0111, b_1111 | ||
224 | }; | ||
225 | |||
226 | static void str_invert_revert(unsigned char *b, int len) | ||
227 | { | ||
228 | int i; | ||
229 | |||
230 | for (i = 0; i < len; i++) | ||
231 | b[i] = (irtab[b[i] & 0x0f] << 4) | irtab[b[i] >> 4]; | ||
232 | } | ||
233 | |||
234 | static unsigned char invert_revert(unsigned char ch) | ||
235 | { | ||
236 | return (irtab[ch & 0x0f] << 4) | irtab[ch >> 4]; | ||
237 | } | ||
238 | |||
239 | #define ATRLENCK(dev,pos) \ | ||
240 | if (pos>=dev->atr_len || pos>=MAX_ATR) \ | ||
241 | goto return_0; | ||
242 | |||
243 | static unsigned int calc_baudv(unsigned char fidi) | ||
244 | { | ||
245 | unsigned int wcrcf, wbrcf, fi_rfu, di_rfu; | ||
246 | |||
247 | fi_rfu = 372; | ||
248 | di_rfu = 1; | ||
249 | |||
250 | /* FI */ | ||
251 | switch ((fidi >> 4) & 0x0F) { | ||
252 | case 0x00: | ||
253 | wcrcf = 372; | ||
254 | break; | ||
255 | case 0x01: | ||
256 | wcrcf = 372; | ||
257 | break; | ||
258 | case 0x02: | ||
259 | wcrcf = 558; | ||
260 | break; | ||
261 | case 0x03: | ||
262 | wcrcf = 744; | ||
263 | break; | ||
264 | case 0x04: | ||
265 | wcrcf = 1116; | ||
266 | break; | ||
267 | case 0x05: | ||
268 | wcrcf = 1488; | ||
269 | break; | ||
270 | case 0x06: | ||
271 | wcrcf = 1860; | ||
272 | break; | ||
273 | case 0x07: | ||
274 | wcrcf = fi_rfu; | ||
275 | break; | ||
276 | case 0x08: | ||
277 | wcrcf = fi_rfu; | ||
278 | break; | ||
279 | case 0x09: | ||
280 | wcrcf = 512; | ||
281 | break; | ||
282 | case 0x0A: | ||
283 | wcrcf = 768; | ||
284 | break; | ||
285 | case 0x0B: | ||
286 | wcrcf = 1024; | ||
287 | break; | ||
288 | case 0x0C: | ||
289 | wcrcf = 1536; | ||
290 | break; | ||
291 | case 0x0D: | ||
292 | wcrcf = 2048; | ||
293 | break; | ||
294 | default: | ||
295 | wcrcf = fi_rfu; | ||
296 | break; | ||
297 | } | ||
298 | |||
299 | /* DI */ | ||
300 | switch (fidi & 0x0F) { | ||
301 | case 0x00: | ||
302 | wbrcf = di_rfu; | ||
303 | break; | ||
304 | case 0x01: | ||
305 | wbrcf = 1; | ||
306 | break; | ||
307 | case 0x02: | ||
308 | wbrcf = 2; | ||
309 | break; | ||
310 | case 0x03: | ||
311 | wbrcf = 4; | ||
312 | break; | ||
313 | case 0x04: | ||
314 | wbrcf = 8; | ||
315 | break; | ||
316 | case 0x05: | ||
317 | wbrcf = 16; | ||
318 | break; | ||
319 | case 0x06: | ||
320 | wbrcf = 32; | ||
321 | break; | ||
322 | case 0x07: | ||
323 | wbrcf = di_rfu; | ||
324 | break; | ||
325 | case 0x08: | ||
326 | wbrcf = 12; | ||
327 | break; | ||
328 | case 0x09: | ||
329 | wbrcf = 20; | ||
330 | break; | ||
331 | default: | ||
332 | wbrcf = di_rfu; | ||
333 | break; | ||
334 | } | ||
335 | |||
336 | return (wcrcf / wbrcf); | ||
337 | } | ||
338 | |||
339 | static unsigned short io_read_num_rec_bytes(ioaddr_t iobase, unsigned short *s) | ||
340 | { | ||
341 | unsigned short tmp; | ||
342 | |||
343 | tmp = *s = 0; | ||
344 | do { | ||
345 | *s = tmp; | ||
346 | tmp = inb(REG_NUM_BYTES(iobase)) | | ||
347 | (inb(REG_FLAGS0(iobase)) & 4 ? 0x100 : 0); | ||
348 | } while (tmp != *s); | ||
349 | |||
350 | return *s; | ||
351 | } | ||
352 | |||
353 | static int parse_atr(struct cm4000_dev *dev) | ||
354 | { | ||
355 | unsigned char any_t1, any_t0; | ||
356 | unsigned char ch, ifno; | ||
357 | int ix, done; | ||
358 | |||
359 | DEBUGP(3, dev, "-> parse_atr: dev->atr_len = %i\n", dev->atr_len); | ||
360 | |||
361 | if (dev->atr_len < 3) { | ||
362 | DEBUGP(5, dev, "parse_atr: atr_len < 3\n"); | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | if (dev->atr[0] == 0x3f) | ||
367 | set_bit(IS_INVREV, &dev->flags); | ||
368 | else | ||
369 | clear_bit(IS_INVREV, &dev->flags); | ||
370 | ix = 1; | ||
371 | ifno = 1; | ||
372 | ch = dev->atr[1]; | ||
373 | dev->proto = 0; /* XXX PROTO */ | ||
374 | any_t1 = any_t0 = done = 0; | ||
375 | dev->ta1 = 0x11; /* defaults to 9600 baud */ | ||
376 | do { | ||
377 | if (ifno == 1 && (ch & 0x10)) { | ||
378 | /* read first interface byte and TA1 is present */ | ||
379 | dev->ta1 = dev->atr[2]; | ||
380 | DEBUGP(5, dev, "Card says FiDi is 0x%.2x\n", dev->ta1); | ||
381 | ifno++; | ||
382 | } else if ((ifno == 2) && (ch & 0x10)) { /* TA(2) */ | ||
383 | dev->ta1 = 0x11; | ||
384 | ifno++; | ||
385 | } | ||
386 | |||
387 | DEBUGP(5, dev, "Yi=%.2x\n", ch & 0xf0); | ||
388 | ix += ((ch & 0x10) >> 4) /* no of int.face chars */ | ||
389 | +((ch & 0x20) >> 5) | ||
390 | + ((ch & 0x40) >> 6) | ||
391 | + ((ch & 0x80) >> 7); | ||
392 | /* ATRLENCK(dev,ix); */ | ||
393 | if (ch & 0x80) { /* TDi */ | ||
394 | ch = dev->atr[ix]; | ||
395 | if ((ch & 0x0f)) { | ||
396 | any_t1 = 1; | ||
397 | DEBUGP(5, dev, "card is capable of T=1\n"); | ||
398 | } else { | ||
399 | any_t0 = 1; | ||
400 | DEBUGP(5, dev, "card is capable of T=0\n"); | ||
401 | } | ||
402 | } else | ||
403 | done = 1; | ||
404 | } while (!done); | ||
405 | |||
406 | DEBUGP(5, dev, "ix=%d noHist=%d any_t1=%d\n", | ||
407 | ix, dev->atr[1] & 15, any_t1); | ||
408 | if (ix + 1 + (dev->atr[1] & 0x0f) + any_t1 != dev->atr_len) { | ||
409 | DEBUGP(5, dev, "length error\n"); | ||
410 | return 0; | ||
411 | } | ||
412 | if (any_t0) | ||
413 | set_bit(IS_ANY_T0, &dev->flags); | ||
414 | |||
415 | if (any_t1) { /* compute csum */ | ||
416 | dev->atr_csum = 0; | ||
417 | #ifdef ATR_CSUM | ||
418 | for (i = 1; i < dev->atr_len; i++) | ||
419 | dev->atr_csum ^= dev->atr[i]; | ||
420 | if (dev->atr_csum) { | ||
421 | set_bit(IS_BAD_CSUM, &dev->flags); | ||
422 | DEBUGP(5, dev, "bad checksum\n"); | ||
423 | goto return_0; | ||
424 | } | ||
425 | #endif | ||
426 | if (any_t0 == 0) | ||
427 | dev->proto = 1; /* XXX PROTO */ | ||
428 | set_bit(IS_ANY_T1, &dev->flags); | ||
429 | } | ||
430 | |||
431 | return 1; | ||
432 | } | ||
433 | |||
434 | struct card_fixup { | ||
435 | char atr[12]; | ||
436 | u_int8_t atr_len; | ||
437 | u_int8_t stopbits; | ||
438 | }; | ||
439 | |||
440 | static struct card_fixup card_fixups[] = { | ||
441 | { /* ACOS */ | ||
442 | .atr = { 0x3b, 0xb3, 0x11, 0x00, 0x00, 0x41, 0x01 }, | ||
443 | .atr_len = 7, | ||
444 | .stopbits = 0x03, | ||
445 | }, | ||
446 | { /* Motorola */ | ||
447 | .atr = {0x3b, 0x76, 0x13, 0x00, 0x00, 0x80, 0x62, 0x07, | ||
448 | 0x41, 0x81, 0x81 }, | ||
449 | .atr_len = 11, | ||
450 | .stopbits = 0x04, | ||
451 | }, | ||
452 | }; | ||
453 | |||
454 | static void set_cardparameter(struct cm4000_dev *dev) | ||
455 | { | ||
456 | int i; | ||
457 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
458 | u_int8_t stopbits = 0x02; /* ISO default */ | ||
459 | |||
460 | DEBUGP(3, dev, "-> set_cardparameter\n"); | ||
461 | |||
462 | dev->flags1 = dev->flags1 | (((dev->baudv - 1) & 0x0100) >> 8); | ||
463 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
464 | DEBUGP(5, dev, "flags1 = 0x%02x\n", dev->flags1); | ||
465 | |||
466 | /* set baudrate */ | ||
467 | xoutb((unsigned char)((dev->baudv - 1) & 0xFF), REG_BAUDRATE(iobase)); | ||
468 | |||
469 | DEBUGP(5, dev, "baudv = %i -> write 0x%02x\n", dev->baudv, | ||
470 | ((dev->baudv - 1) & 0xFF)); | ||
471 | |||
472 | /* set stopbits */ | ||
473 | for (i = 0; i < ARRAY_SIZE(card_fixups); i++) { | ||
474 | if (!memcmp(dev->atr, card_fixups[i].atr, | ||
475 | card_fixups[i].atr_len)) | ||
476 | stopbits = card_fixups[i].stopbits; | ||
477 | } | ||
478 | xoutb(stopbits, REG_STOPBITS(iobase)); | ||
479 | |||
480 | DEBUGP(3, dev, "<- set_cardparameter\n"); | ||
481 | } | ||
482 | |||
483 | static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq) | ||
484 | { | ||
485 | |||
486 | unsigned long tmp, i; | ||
487 | unsigned short num_bytes_read; | ||
488 | unsigned char pts_reply[4]; | ||
489 | ssize_t rc; | ||
490 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
491 | |||
492 | rc = 0; | ||
493 | |||
494 | DEBUGP(3, dev, "-> set_protocol\n"); | ||
495 | DEBUGP(5, dev, "ptsreq->Protocol = 0x%.8x, ptsreq->Flags=0x%.8x, " | ||
496 | "ptsreq->pts1=0x%.2x, ptsreq->pts2=0x%.2x, " | ||
497 | "ptsreq->pts3=0x%.2x\n", (unsigned int)ptsreq->protocol, | ||
498 | (unsigned int)ptsreq->flags, ptsreq->pts1, ptsreq->pts2, | ||
499 | ptsreq->pts3); | ||
500 | |||
501 | /* Fill PTS structure */ | ||
502 | dev->pts[0] = 0xff; | ||
503 | dev->pts[1] = 0x00; | ||
504 | tmp = ptsreq->protocol; | ||
505 | while ((tmp = (tmp >> 1)) > 0) | ||
506 | dev->pts[1]++; | ||
507 | dev->proto = dev->pts[1]; /* Set new protocol */ | ||
508 | dev->pts[1] = (0x01 << 4) | (dev->pts[1]); | ||
509 | |||
510 | /* Correct Fi/Di according to CM4000 Fi/Di table */ | ||
511 | DEBUGP(5, dev, "Ta(1) from ATR is 0x%.2x\n", dev->ta1); | ||
512 | /* set Fi/Di according to ATR TA(1) */ | ||
513 | dev->pts[2] = fi_di_table[dev->ta1 & 0x0F][(dev->ta1 >> 4) & 0x0F]; | ||
514 | |||
515 | /* Calculate PCK character */ | ||
516 | dev->pts[3] = dev->pts[0] ^ dev->pts[1] ^ dev->pts[2]; | ||
517 | |||
518 | DEBUGP(5, dev, "pts0=%.2x, pts1=%.2x, pts2=%.2x, pts3=%.2x\n", | ||
519 | dev->pts[0], dev->pts[1], dev->pts[2], dev->pts[3]); | ||
520 | |||
521 | /* check card convention */ | ||
522 | if (test_bit(IS_INVREV, &dev->flags)) | ||
523 | str_invert_revert(dev->pts, 4); | ||
524 | |||
525 | /* reset SM */ | ||
526 | xoutb(0x80, REG_FLAGS0(iobase)); | ||
527 | |||
528 | /* Enable access to the message buffer */ | ||
529 | DEBUGP(5, dev, "Enable access to the messages buffer\n"); | ||
530 | dev->flags1 = 0x20 /* T_Active */ | ||
531 | | (test_bit(IS_INVREV, &dev->flags) ? 0x02 : 0x00) /* inv parity */ | ||
532 | | ((dev->baudv >> 8) & 0x01); /* MSB-baud */ | ||
533 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
534 | |||
535 | DEBUGP(5, dev, "Enable message buffer -> flags1 = 0x%.2x\n", | ||
536 | dev->flags1); | ||
537 | |||
538 | /* write challenge to the buffer */ | ||
539 | DEBUGP(5, dev, "Write challenge to buffer: "); | ||
540 | for (i = 0; i < 4; i++) { | ||
541 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
542 | xoutb(dev->pts[i], REG_BUF_DATA(iobase)); /* buf data */ | ||
543 | #ifdef PCMCIA_DEBUG | ||
544 | if (pc_debug >= 5) | ||
545 | printk("0x%.2x ", dev->pts[i]); | ||
546 | } | ||
547 | if (pc_debug >= 5) | ||
548 | printk("\n"); | ||
549 | #else | ||
550 | } | ||
551 | #endif | ||
552 | |||
553 | /* set number of bytes to write */ | ||
554 | DEBUGP(5, dev, "Set number of bytes to write\n"); | ||
555 | xoutb(0x04, REG_NUM_SEND(iobase)); | ||
556 | |||
557 | /* Trigger CARDMAN CONTROLLER */ | ||
558 | xoutb(0x50, REG_FLAGS0(iobase)); | ||
559 | |||
560 | /* Monitor progress */ | ||
561 | /* wait for xmit done */ | ||
562 | DEBUGP(5, dev, "Waiting for NumRecBytes getting valid\n"); | ||
563 | |||
564 | for (i = 0; i < 100; i++) { | ||
565 | if (inb(REG_FLAGS0(iobase)) & 0x08) { | ||
566 | DEBUGP(5, dev, "NumRecBytes is valid\n"); | ||
567 | break; | ||
568 | } | ||
569 | mdelay(10); | ||
570 | } | ||
571 | if (i == 100) { | ||
572 | DEBUGP(5, dev, "Timeout waiting for NumRecBytes getting " | ||
573 | "valid\n"); | ||
574 | rc = -EIO; | ||
575 | goto exit_setprotocol; | ||
576 | } | ||
577 | |||
578 | DEBUGP(5, dev, "Reading NumRecBytes\n"); | ||
579 | for (i = 0; i < 100; i++) { | ||
580 | io_read_num_rec_bytes(iobase, &num_bytes_read); | ||
581 | if (num_bytes_read >= 4) { | ||
582 | DEBUGP(2, dev, "NumRecBytes = %i\n", num_bytes_read); | ||
583 | break; | ||
584 | } | ||
585 | mdelay(10); | ||
586 | } | ||
587 | |||
588 | /* check whether it is a short PTS reply? */ | ||
589 | if (num_bytes_read == 3) | ||
590 | i = 0; | ||
591 | |||
592 | if (i == 100) { | ||
593 | DEBUGP(5, dev, "Timeout reading num_bytes_read\n"); | ||
594 | rc = -EIO; | ||
595 | goto exit_setprotocol; | ||
596 | } | ||
597 | |||
598 | DEBUGP(5, dev, "Reset the CARDMAN CONTROLLER\n"); | ||
599 | xoutb(0x80, REG_FLAGS0(iobase)); | ||
600 | |||
601 | /* Read PPS reply */ | ||
602 | DEBUGP(5, dev, "Read PPS reply\n"); | ||
603 | for (i = 0; i < num_bytes_read; i++) { | ||
604 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
605 | pts_reply[i] = inb(REG_BUF_DATA(iobase)); | ||
606 | } | ||
607 | |||
608 | #ifdef PCMCIA_DEBUG | ||
609 | DEBUGP(2, dev, "PTSreply: "); | ||
610 | for (i = 0; i < num_bytes_read; i++) { | ||
611 | if (pc_debug >= 5) | ||
612 | printk("0x%.2x ", pts_reply[i]); | ||
613 | } | ||
614 | printk("\n"); | ||
615 | #endif /* PCMCIA_DEBUG */ | ||
616 | |||
617 | DEBUGP(5, dev, "Clear Tactive in Flags1\n"); | ||
618 | xoutb(0x20, REG_FLAGS1(iobase)); | ||
619 | |||
620 | /* Compare ptsreq and ptsreply */ | ||
621 | if ((dev->pts[0] == pts_reply[0]) && | ||
622 | (dev->pts[1] == pts_reply[1]) && | ||
623 | (dev->pts[2] == pts_reply[2]) && (dev->pts[3] == pts_reply[3])) { | ||
624 | /* setcardparameter according to PPS */ | ||
625 | dev->baudv = calc_baudv(dev->pts[2]); | ||
626 | set_cardparameter(dev); | ||
627 | } else if ((dev->pts[0] == pts_reply[0]) && | ||
628 | ((dev->pts[1] & 0xef) == pts_reply[1]) && | ||
629 | ((pts_reply[0] ^ pts_reply[1]) == pts_reply[2])) { | ||
630 | /* short PTS reply, set card parameter to default values */ | ||
631 | dev->baudv = calc_baudv(0x11); | ||
632 | set_cardparameter(dev); | ||
633 | } else | ||
634 | rc = -EIO; | ||
635 | |||
636 | exit_setprotocol: | ||
637 | DEBUGP(3, dev, "<- set_protocol\n"); | ||
638 | return rc; | ||
639 | } | ||
640 | |||
641 | static int io_detect_cm4000(ioaddr_t iobase, struct cm4000_dev *dev) | ||
642 | { | ||
643 | |||
644 | /* note: statemachine is assumed to be reset */ | ||
645 | if (inb(REG_FLAGS0(iobase)) & 8) { | ||
646 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
647 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
648 | return 0; /* detect CMM = 1 -> failure */ | ||
649 | } | ||
650 | /* xoutb(0x40, REG_FLAGS1(iobase)); detectCMM */ | ||
651 | xoutb(dev->flags1 | 0x40, REG_FLAGS1(iobase)); | ||
652 | if ((inb(REG_FLAGS0(iobase)) & 8) == 0) { | ||
653 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
654 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
655 | return 0; /* detect CMM=0 -> failure */ | ||
656 | } | ||
657 | /* clear detectCMM again by restoring original flags1 */ | ||
658 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
659 | return 1; | ||
660 | } | ||
661 | |||
662 | static void terminate_monitor(struct cm4000_dev *dev) | ||
663 | { | ||
664 | |||
665 | /* tell the monitor to stop and wait until | ||
666 | * it terminates. | ||
667 | */ | ||
668 | DEBUGP(3, dev, "-> terminate_monitor\n"); | ||
669 | wait_event_interruptible(dev->devq, | ||
670 | test_and_set_bit(LOCK_MONITOR, | ||
671 | (void *)&dev->flags)); | ||
672 | |||
673 | /* now, LOCK_MONITOR has been set. | ||
674 | * allow a last cycle in the monitor. | ||
675 | * the monitor will indicate that it has | ||
676 | * finished by clearing this bit. | ||
677 | */ | ||
678 | DEBUGP(5, dev, "Now allow last cycle of monitor!\n"); | ||
679 | while (test_bit(LOCK_MONITOR, (void *)&dev->flags)) | ||
680 | msleep(25); | ||
681 | |||
682 | DEBUGP(5, dev, "Delete timer\n"); | ||
683 | del_timer_sync(&dev->timer); | ||
684 | #ifdef PCMCIA_DEBUG | ||
685 | dev->monitor_running = 0; | ||
686 | #endif | ||
687 | |||
688 | DEBUGP(3, dev, "<- terminate_monitor\n"); | ||
689 | } | ||
690 | |||
691 | /* | ||
692 | * monitor the card every 50msec. as a side-effect, retrieve the | ||
693 | * atr once a card is inserted. another side-effect of retrieving the | ||
694 | * atr is that the card will be powered on, so there is no need to | ||
695 | * power on the card explictely from the application: the driver | ||
696 | * is already doing that for you. | ||
697 | */ | ||
698 | |||
699 | static void monitor_card(unsigned long p) | ||
700 | { | ||
701 | struct cm4000_dev *dev = (struct cm4000_dev *) p; | ||
702 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
703 | unsigned short s; | ||
704 | struct ptsreq ptsreq; | ||
705 | int i, atrc; | ||
706 | |||
707 | DEBUGP(7, dev, "-> monitor_card\n"); | ||
708 | |||
709 | /* if someone has set the lock for us: we're done! */ | ||
710 | if (test_and_set_bit(LOCK_MONITOR, &dev->flags)) { | ||
711 | DEBUGP(4, dev, "About to stop monitor\n"); | ||
712 | /* no */ | ||
713 | dev->rlen = | ||
714 | dev->rpos = | ||
715 | dev->atr_csum = dev->atr_len_retry = dev->cwarn = 0; | ||
716 | dev->mstate = M_FETCH_ATR; | ||
717 | clear_bit(LOCK_MONITOR, &dev->flags); | ||
718 | /* close et al. are sleeping on devq, so wake it */ | ||
719 | wake_up_interruptible(&dev->devq); | ||
720 | DEBUGP(2, dev, "<- monitor_card (we are done now)\n"); | ||
721 | return; | ||
722 | } | ||
723 | |||
724 | /* try to lock io: if it is already locked, just add another timer */ | ||
725 | if (test_and_set_bit(LOCK_IO, (void *)&dev->flags)) { | ||
726 | DEBUGP(4, dev, "Couldn't get IO lock\n"); | ||
727 | goto return_with_timer; | ||
728 | } | ||
729 | |||
730 | /* is a card/a reader inserted at all ? */ | ||
731 | dev->flags0 = xinb(REG_FLAGS0(iobase)); | ||
732 | DEBUGP(7, dev, "dev->flags0 = 0x%2x\n", dev->flags0); | ||
733 | DEBUGP(7, dev, "smartcard present: %s\n", | ||
734 | dev->flags0 & 1 ? "yes" : "no"); | ||
735 | DEBUGP(7, dev, "cardman present: %s\n", | ||
736 | dev->flags0 == 0xff ? "no" : "yes"); | ||
737 | |||
738 | if ((dev->flags0 & 1) == 0 /* no smartcard inserted */ | ||
739 | || dev->flags0 == 0xff) { /* no cardman inserted */ | ||
740 | /* no */ | ||
741 | dev->rlen = | ||
742 | dev->rpos = | ||
743 | dev->atr_csum = dev->atr_len_retry = dev->cwarn = 0; | ||
744 | dev->mstate = M_FETCH_ATR; | ||
745 | |||
746 | dev->flags &= 0x000000ff; /* only keep IO and MONITOR locks */ | ||
747 | |||
748 | if (dev->flags0 == 0xff) { | ||
749 | DEBUGP(4, dev, "set IS_CMM_ABSENT bit\n"); | ||
750 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
751 | } else if (test_bit(IS_CMM_ABSENT, &dev->flags)) { | ||
752 | DEBUGP(4, dev, "clear IS_CMM_ABSENT bit " | ||
753 | "(card is removed)\n"); | ||
754 | clear_bit(IS_CMM_ABSENT, &dev->flags); | ||
755 | } | ||
756 | |||
757 | goto release_io; | ||
758 | } else if ((dev->flags0 & 1) && test_bit(IS_CMM_ABSENT, &dev->flags)) { | ||
759 | /* cardman and card present but cardman was absent before | ||
760 | * (after suspend with inserted card) */ | ||
761 | DEBUGP(4, dev, "clear IS_CMM_ABSENT bit (card is inserted)\n"); | ||
762 | clear_bit(IS_CMM_ABSENT, &dev->flags); | ||
763 | } | ||
764 | |||
765 | if (test_bit(IS_ATR_VALID, &dev->flags) == 1) { | ||
766 | DEBUGP(7, dev, "believe ATR is already valid (do nothing)\n"); | ||
767 | goto release_io; | ||
768 | } | ||
769 | |||
770 | switch (dev->mstate) { | ||
771 | unsigned char flags0; | ||
772 | case M_CARDOFF: | ||
773 | DEBUGP(4, dev, "M_CARDOFF\n"); | ||
774 | flags0 = inb(REG_FLAGS0(iobase)); | ||
775 | if (flags0 & 0x02) { | ||
776 | /* wait until Flags0 indicate power is off */ | ||
777 | dev->mdelay = T_10MSEC; | ||
778 | } else { | ||
779 | /* Flags0 indicate power off and no card inserted now; | ||
780 | * Reset CARDMAN CONTROLLER */ | ||
781 | xoutb(0x80, REG_FLAGS0(iobase)); | ||
782 | |||
783 | /* prepare for fetching ATR again: after card off ATR | ||
784 | * is read again automatically */ | ||
785 | dev->rlen = | ||
786 | dev->rpos = | ||
787 | dev->atr_csum = | ||
788 | dev->atr_len_retry = dev->cwarn = 0; | ||
789 | dev->mstate = M_FETCH_ATR; | ||
790 | |||
791 | /* minimal gap between CARDOFF and read ATR is 50msec */ | ||
792 | dev->mdelay = T_50MSEC; | ||
793 | } | ||
794 | break; | ||
795 | case M_FETCH_ATR: | ||
796 | DEBUGP(4, dev, "M_FETCH_ATR\n"); | ||
797 | xoutb(0x80, REG_FLAGS0(iobase)); | ||
798 | DEBUGP(4, dev, "Reset BAUDV to 9600\n"); | ||
799 | dev->baudv = 0x173; /* 9600 */ | ||
800 | xoutb(0x02, REG_STOPBITS(iobase)); /* stopbits=2 */ | ||
801 | xoutb(0x73, REG_BAUDRATE(iobase)); /* baud value */ | ||
802 | xoutb(0x21, REG_FLAGS1(iobase)); /* T_Active=1, baud | ||
803 | value */ | ||
804 | /* warm start vs. power on: */ | ||
805 | xoutb(dev->flags0 & 2 ? 0x46 : 0x44, REG_FLAGS0(iobase)); | ||
806 | dev->mdelay = T_40MSEC; | ||
807 | dev->mstate = M_TIMEOUT_WAIT; | ||
808 | break; | ||
809 | case M_TIMEOUT_WAIT: | ||
810 | DEBUGP(4, dev, "M_TIMEOUT_WAIT\n"); | ||
811 | /* numRecBytes */ | ||
812 | io_read_num_rec_bytes(iobase, &dev->atr_len); | ||
813 | dev->mdelay = T_10MSEC; | ||
814 | dev->mstate = M_READ_ATR_LEN; | ||
815 | break; | ||
816 | case M_READ_ATR_LEN: | ||
817 | DEBUGP(4, dev, "M_READ_ATR_LEN\n"); | ||
818 | /* infinite loop possible, since there is no timeout */ | ||
819 | |||
820 | #define MAX_ATR_LEN_RETRY 100 | ||
821 | |||
822 | if (dev->atr_len == io_read_num_rec_bytes(iobase, &s)) { | ||
823 | if (dev->atr_len_retry++ >= MAX_ATR_LEN_RETRY) { /* + XX msec */ | ||
824 | dev->mdelay = T_10MSEC; | ||
825 | dev->mstate = M_READ_ATR; | ||
826 | } | ||
827 | } else { | ||
828 | dev->atr_len = s; | ||
829 | dev->atr_len_retry = 0; /* set new timeout */ | ||
830 | } | ||
831 | |||
832 | DEBUGP(4, dev, "Current ATR_LEN = %i\n", dev->atr_len); | ||
833 | break; | ||
834 | case M_READ_ATR: | ||
835 | DEBUGP(4, dev, "M_READ_ATR\n"); | ||
836 | xoutb(0x80, REG_FLAGS0(iobase)); /* reset SM */ | ||
837 | for (i = 0; i < dev->atr_len; i++) { | ||
838 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
839 | dev->atr[i] = inb(REG_BUF_DATA(iobase)); | ||
840 | } | ||
841 | /* Deactivate T_Active flags */ | ||
842 | DEBUGP(4, dev, "Deactivate T_Active flags\n"); | ||
843 | dev->flags1 = 0x01; | ||
844 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
845 | |||
846 | /* atr is present (which doesnt mean it's valid) */ | ||
847 | set_bit(IS_ATR_PRESENT, &dev->flags); | ||
848 | if (dev->atr[0] == 0x03) | ||
849 | str_invert_revert(dev->atr, dev->atr_len); | ||
850 | atrc = parse_atr(dev); | ||
851 | if (atrc == 0) { /* atr invalid */ | ||
852 | dev->mdelay = 0; | ||
853 | dev->mstate = M_BAD_CARD; | ||
854 | } else { | ||
855 | dev->mdelay = T_50MSEC; | ||
856 | dev->mstate = M_ATR_PRESENT; | ||
857 | set_bit(IS_ATR_VALID, &dev->flags); | ||
858 | } | ||
859 | |||
860 | if (test_bit(IS_ATR_VALID, &dev->flags) == 1) { | ||
861 | DEBUGP(4, dev, "monitor_card: ATR valid\n"); | ||
862 | /* if ta1 == 0x11, no PPS necessary (default values) */ | ||
863 | /* do not do PPS with multi protocol cards */ | ||
864 | if ((test_bit(IS_AUTOPPS_ACT, &dev->flags) == 0) && | ||
865 | (dev->ta1 != 0x11) && | ||
866 | !(test_bit(IS_ANY_T0, &dev->flags) && | ||
867 | test_bit(IS_ANY_T1, &dev->flags))) { | ||
868 | DEBUGP(4, dev, "Perform AUTOPPS\n"); | ||
869 | set_bit(IS_AUTOPPS_ACT, &dev->flags); | ||
870 | ptsreq.protocol = ptsreq.protocol = | ||
871 | (0x01 << dev->proto); | ||
872 | ptsreq.flags = 0x01; | ||
873 | ptsreq.pts1 = 0x00; | ||
874 | ptsreq.pts2 = 0x00; | ||
875 | ptsreq.pts3 = 0x00; | ||
876 | if (set_protocol(dev, &ptsreq) == 0) { | ||
877 | DEBUGP(4, dev, "AUTOPPS ret SUCC\n"); | ||
878 | clear_bit(IS_AUTOPPS_ACT, &dev->flags); | ||
879 | wake_up_interruptible(&dev->atrq); | ||
880 | } else { | ||
881 | DEBUGP(4, dev, "AUTOPPS failed: " | ||
882 | "repower using defaults\n"); | ||
883 | /* prepare for repowering */ | ||
884 | clear_bit(IS_ATR_PRESENT, &dev->flags); | ||
885 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
886 | dev->rlen = | ||
887 | dev->rpos = | ||
888 | dev->atr_csum = | ||
889 | dev->atr_len_retry = dev->cwarn = 0; | ||
890 | dev->mstate = M_FETCH_ATR; | ||
891 | |||
892 | dev->mdelay = T_50MSEC; | ||
893 | } | ||
894 | } else { | ||
895 | /* for cards which use slightly different | ||
896 | * params (extra guard time) */ | ||
897 | set_cardparameter(dev); | ||
898 | if (test_bit(IS_AUTOPPS_ACT, &dev->flags) == 1) | ||
899 | DEBUGP(4, dev, "AUTOPPS already active " | ||
900 | "2nd try:use default values\n"); | ||
901 | if (dev->ta1 == 0x11) | ||
902 | DEBUGP(4, dev, "No AUTOPPS necessary " | ||
903 | "TA(1)==0x11\n"); | ||
904 | if (test_bit(IS_ANY_T0, &dev->flags) | ||
905 | && test_bit(IS_ANY_T1, &dev->flags)) | ||
906 | DEBUGP(4, dev, "Do NOT perform AUTOPPS " | ||
907 | "with multiprotocol cards\n"); | ||
908 | clear_bit(IS_AUTOPPS_ACT, &dev->flags); | ||
909 | wake_up_interruptible(&dev->atrq); | ||
910 | } | ||
911 | } else { | ||
912 | DEBUGP(4, dev, "ATR invalid\n"); | ||
913 | wake_up_interruptible(&dev->atrq); | ||
914 | } | ||
915 | break; | ||
916 | case M_BAD_CARD: | ||
917 | DEBUGP(4, dev, "M_BAD_CARD\n"); | ||
918 | /* slow down warning, but prompt immediately after insertion */ | ||
919 | if (dev->cwarn == 0 || dev->cwarn == 10) { | ||
920 | set_bit(IS_BAD_CARD, &dev->flags); | ||
921 | printk(KERN_WARNING MODULE_NAME ": device %s: ", | ||
922 | dev->node.dev_name); | ||
923 | if (test_bit(IS_BAD_CSUM, &dev->flags)) { | ||
924 | DEBUGP(4, dev, "ATR checksum (0x%.2x, should " | ||
925 | "be zero) failed\n", dev->atr_csum); | ||
926 | } | ||
927 | #ifdef PCMCIA_DEBUG | ||
928 | else if (test_bit(IS_BAD_LENGTH, &dev->flags)) { | ||
929 | DEBUGP(4, dev, "ATR length error\n"); | ||
930 | } else { | ||
931 | DEBUGP(4, dev, "card damaged or wrong way " | ||
932 | "inserted\n"); | ||
933 | } | ||
934 | #endif | ||
935 | dev->cwarn = 0; | ||
936 | wake_up_interruptible(&dev->atrq); /* wake open */ | ||
937 | } | ||
938 | dev->cwarn++; | ||
939 | dev->mdelay = T_100MSEC; | ||
940 | dev->mstate = M_FETCH_ATR; | ||
941 | break; | ||
942 | default: | ||
943 | DEBUGP(7, dev, "Unknown action\n"); | ||
944 | break; /* nothing */ | ||
945 | } | ||
946 | |||
947 | release_io: | ||
948 | DEBUGP(7, dev, "release_io\n"); | ||
949 | clear_bit(LOCK_IO, &dev->flags); | ||
950 | wake_up_interruptible(&dev->ioq); /* whoever needs IO */ | ||
951 | |||
952 | return_with_timer: | ||
953 | DEBUGP(7, dev, "<- monitor_card (returns with timer)\n"); | ||
954 | dev->timer.expires = jiffies + dev->mdelay; | ||
955 | add_timer(&dev->timer); | ||
956 | clear_bit(LOCK_MONITOR, &dev->flags); | ||
957 | } | ||
958 | |||
959 | /* Interface to userland (file_operations) */ | ||
960 | |||
961 | static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, | ||
962 | loff_t *ppos) | ||
963 | { | ||
964 | struct cm4000_dev *dev = filp->private_data; | ||
965 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
966 | ssize_t rc; | ||
967 | int i, j, k; | ||
968 | |||
969 | DEBUGP(2, dev, "-> cmm_read(%s,%d)\n", current->comm, current->pid); | ||
970 | |||
971 | if (count == 0) /* according to manpage */ | ||
972 | return 0; | ||
973 | |||
974 | if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */ | ||
975 | test_bit(IS_CMM_ABSENT, &dev->flags)) | ||
976 | return -ENODEV; | ||
977 | |||
978 | if (test_bit(IS_BAD_CSUM, &dev->flags)) | ||
979 | return -EIO; | ||
980 | |||
981 | /* also see the note about this in cmm_write */ | ||
982 | if (wait_event_interruptible | ||
983 | (dev->atrq, | ||
984 | ((filp->f_flags & O_NONBLOCK) | ||
985 | || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) != 0)))) { | ||
986 | if (filp->f_flags & O_NONBLOCK) | ||
987 | return -EAGAIN; | ||
988 | return -ERESTARTSYS; | ||
989 | } | ||
990 | |||
991 | if (test_bit(IS_ATR_VALID, &dev->flags) == 0) | ||
992 | return -EIO; | ||
993 | |||
994 | /* this one implements blocking IO */ | ||
995 | if (wait_event_interruptible | ||
996 | (dev->readq, | ||
997 | ((filp->f_flags & O_NONBLOCK) || (dev->rpos < dev->rlen)))) { | ||
998 | if (filp->f_flags & O_NONBLOCK) | ||
999 | return -EAGAIN; | ||
1000 | return -ERESTARTSYS; | ||
1001 | } | ||
1002 | |||
1003 | /* lock io */ | ||
1004 | if (wait_event_interruptible | ||
1005 | (dev->ioq, | ||
1006 | ((filp->f_flags & O_NONBLOCK) | ||
1007 | || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) == 0)))) { | ||
1008 | if (filp->f_flags & O_NONBLOCK) | ||
1009 | return -EAGAIN; | ||
1010 | return -ERESTARTSYS; | ||
1011 | } | ||
1012 | |||
1013 | rc = 0; | ||
1014 | dev->flags0 = inb(REG_FLAGS0(iobase)); | ||
1015 | if ((dev->flags0 & 1) == 0 /* no smartcard inserted */ | ||
1016 | || dev->flags0 == 0xff) { /* no cardman inserted */ | ||
1017 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1018 | if (dev->flags0 & 1) { | ||
1019 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
1020 | rc = -ENODEV; | ||
1021 | } | ||
1022 | rc = -EIO; | ||
1023 | goto release_io; | ||
1024 | } | ||
1025 | |||
1026 | DEBUGP(4, dev, "begin read answer\n"); | ||
1027 | j = min(count, (size_t)(dev->rlen - dev->rpos)); | ||
1028 | k = dev->rpos; | ||
1029 | if (k + j > 255) | ||
1030 | j = 256 - k; | ||
1031 | DEBUGP(4, dev, "read1 j=%d\n", j); | ||
1032 | for (i = 0; i < j; i++) { | ||
1033 | xoutb(k++, REG_BUF_ADDR(iobase)); | ||
1034 | dev->rbuf[i] = xinb(REG_BUF_DATA(iobase)); | ||
1035 | } | ||
1036 | j = min(count, (size_t)(dev->rlen - dev->rpos)); | ||
1037 | if (k + j > 255) { | ||
1038 | DEBUGP(4, dev, "read2 j=%d\n", j); | ||
1039 | dev->flags1 |= 0x10; /* MSB buf addr set */ | ||
1040 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1041 | for (; i < j; i++) { | ||
1042 | xoutb(k++, REG_BUF_ADDR(iobase)); | ||
1043 | dev->rbuf[i] = xinb(REG_BUF_DATA(iobase)); | ||
1044 | } | ||
1045 | } | ||
1046 | |||
1047 | if (dev->proto == 0 && count > dev->rlen - dev->rpos) { | ||
1048 | DEBUGP(4, dev, "T=0 and count > buffer\n"); | ||
1049 | dev->rbuf[i] = dev->rbuf[i - 1]; | ||
1050 | dev->rbuf[i - 1] = dev->procbyte; | ||
1051 | j++; | ||
1052 | } | ||
1053 | count = j; | ||
1054 | |||
1055 | dev->rpos = dev->rlen + 1; | ||
1056 | |||
1057 | /* Clear T1Active */ | ||
1058 | DEBUGP(4, dev, "Clear T1Active\n"); | ||
1059 | dev->flags1 &= 0xdf; | ||
1060 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1061 | |||
1062 | xoutb(0, REG_FLAGS1(iobase)); /* clear detectCMM */ | ||
1063 | /* last check before exit */ | ||
1064 | if (!io_detect_cm4000(iobase, dev)) | ||
1065 | count = -ENODEV; | ||
1066 | |||
1067 | if (test_bit(IS_INVREV, &dev->flags) && count > 0) | ||
1068 | str_invert_revert(dev->rbuf, count); | ||
1069 | |||
1070 | if (copy_to_user(buf, dev->rbuf, count)) | ||
1071 | return -EFAULT; | ||
1072 | |||
1073 | release_io: | ||
1074 | clear_bit(LOCK_IO, &dev->flags); | ||
1075 | wake_up_interruptible(&dev->ioq); | ||
1076 | |||
1077 | DEBUGP(2, dev, "<- cmm_read returns: rc = %Zi\n", | ||
1078 | (rc < 0 ? rc : count)); | ||
1079 | return rc < 0 ? rc : count; | ||
1080 | } | ||
1081 | |||
1082 | static ssize_t cmm_write(struct file *filp, const char __user *buf, | ||
1083 | size_t count, loff_t *ppos) | ||
1084 | { | ||
1085 | struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data; | ||
1086 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
1087 | unsigned short s; | ||
1088 | unsigned char tmp; | ||
1089 | unsigned char infolen; | ||
1090 | unsigned char sendT0; | ||
1091 | unsigned short nsend; | ||
1092 | unsigned short nr; | ||
1093 | ssize_t rc; | ||
1094 | int i; | ||
1095 | |||
1096 | DEBUGP(2, dev, "-> cmm_write(%s,%d)\n", current->comm, current->pid); | ||
1097 | |||
1098 | if (count == 0) /* according to manpage */ | ||
1099 | return 0; | ||
1100 | |||
1101 | if (dev->proto == 0 && count < 4) { | ||
1102 | /* T0 must have at least 4 bytes */ | ||
1103 | DEBUGP(4, dev, "T0 short write\n"); | ||
1104 | return -EIO; | ||
1105 | } | ||
1106 | |||
1107 | nr = count & 0x1ff; /* max bytes to write */ | ||
1108 | |||
1109 | sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0; | ||
1110 | |||
1111 | if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */ | ||
1112 | test_bit(IS_CMM_ABSENT, &dev->flags)) | ||
1113 | return -ENODEV; | ||
1114 | |||
1115 | if (test_bit(IS_BAD_CSUM, &dev->flags)) { | ||
1116 | DEBUGP(4, dev, "bad csum\n"); | ||
1117 | return -EIO; | ||
1118 | } | ||
1119 | |||
1120 | /* | ||
1121 | * wait for atr to become valid. | ||
1122 | * note: it is important to lock this code. if we dont, the monitor | ||
1123 | * could be run between test_bit and the the call the sleep on the | ||
1124 | * atr-queue. if *then* the monitor detects atr valid, it will wake up | ||
1125 | * any process on the atr-queue, *but* since we have been interrupted, | ||
1126 | * we do not yet sleep on this queue. this would result in a missed | ||
1127 | * wake_up and the calling process would sleep forever (until | ||
1128 | * interrupted). also, do *not* restore_flags before sleep_on, because | ||
1129 | * this could result in the same situation! | ||
1130 | */ | ||
1131 | if (wait_event_interruptible | ||
1132 | (dev->atrq, | ||
1133 | ((filp->f_flags & O_NONBLOCK) | ||
1134 | || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) != 0)))) { | ||
1135 | if (filp->f_flags & O_NONBLOCK) | ||
1136 | return -EAGAIN; | ||
1137 | return -ERESTARTSYS; | ||
1138 | } | ||
1139 | |||
1140 | if (test_bit(IS_ATR_VALID, &dev->flags) == 0) { /* invalid atr */ | ||
1141 | DEBUGP(4, dev, "invalid ATR\n"); | ||
1142 | return -EIO; | ||
1143 | } | ||
1144 | |||
1145 | /* lock io */ | ||
1146 | if (wait_event_interruptible | ||
1147 | (dev->ioq, | ||
1148 | ((filp->f_flags & O_NONBLOCK) | ||
1149 | || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) == 0)))) { | ||
1150 | if (filp->f_flags & O_NONBLOCK) | ||
1151 | return -EAGAIN; | ||
1152 | return -ERESTARTSYS; | ||
1153 | } | ||
1154 | |||
1155 | if (copy_from_user(dev->sbuf, buf, ((count > 512) ? 512 : count))) | ||
1156 | return -EFAULT; | ||
1157 | |||
1158 | rc = 0; | ||
1159 | dev->flags0 = inb(REG_FLAGS0(iobase)); | ||
1160 | if ((dev->flags0 & 1) == 0 /* no smartcard inserted */ | ||
1161 | || dev->flags0 == 0xff) { /* no cardman inserted */ | ||
1162 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1163 | if (dev->flags0 & 1) { | ||
1164 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
1165 | rc = -ENODEV; | ||
1166 | } else { | ||
1167 | DEBUGP(4, dev, "IO error\n"); | ||
1168 | rc = -EIO; | ||
1169 | } | ||
1170 | goto release_io; | ||
1171 | } | ||
1172 | |||
1173 | xoutb(0x80, REG_FLAGS0(iobase)); /* reset SM */ | ||
1174 | |||
1175 | if (!io_detect_cm4000(iobase, dev)) { | ||
1176 | rc = -ENODEV; | ||
1177 | goto release_io; | ||
1178 | } | ||
1179 | |||
1180 | /* reflect T=0 send/read mode in flags1 */ | ||
1181 | dev->flags1 |= (sendT0); | ||
1182 | |||
1183 | set_cardparameter(dev); | ||
1184 | |||
1185 | /* dummy read, reset flag procedure received */ | ||
1186 | tmp = inb(REG_FLAGS1(iobase)); | ||
1187 | |||
1188 | dev->flags1 = 0x20 /* T_Active */ | ||
1189 | | (sendT0) | ||
1190 | | (test_bit(IS_INVREV, &dev->flags) ? 2 : 0)/* inverse parity */ | ||
1191 | | (((dev->baudv - 1) & 0x0100) >> 8); /* MSB-Baud */ | ||
1192 | DEBUGP(1, dev, "set dev->flags1 = 0x%.2x\n", dev->flags1); | ||
1193 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1194 | |||
1195 | /* xmit data */ | ||
1196 | DEBUGP(4, dev, "Xmit data\n"); | ||
1197 | for (i = 0; i < nr; i++) { | ||
1198 | if (i >= 256) { | ||
1199 | dev->flags1 = 0x20 /* T_Active */ | ||
1200 | | (sendT0) /* SendT0 */ | ||
1201 | /* inverse parity: */ | ||
1202 | | (test_bit(IS_INVREV, &dev->flags) ? 2 : 0) | ||
1203 | | (((dev->baudv - 1) & 0x0100) >> 8) /* MSB-Baud */ | ||
1204 | | 0x10; /* set address high */ | ||
1205 | DEBUGP(4, dev, "dev->flags = 0x%.2x - set address " | ||
1206 | "high\n", dev->flags1); | ||
1207 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1208 | } | ||
1209 | if (test_bit(IS_INVREV, &dev->flags)) { | ||
1210 | DEBUGP(4, dev, "Apply inverse convention for 0x%.2x " | ||
1211 | "-> 0x%.2x\n", (unsigned char)dev->sbuf[i], | ||
1212 | invert_revert(dev->sbuf[i])); | ||
1213 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
1214 | xoutb(invert_revert(dev->sbuf[i]), | ||
1215 | REG_BUF_DATA(iobase)); | ||
1216 | } else { | ||
1217 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
1218 | xoutb(dev->sbuf[i], REG_BUF_DATA(iobase)); | ||
1219 | } | ||
1220 | } | ||
1221 | DEBUGP(4, dev, "Xmit done\n"); | ||
1222 | |||
1223 | if (dev->proto == 0) { | ||
1224 | /* T=0 proto: 0 byte reply */ | ||
1225 | if (nr == 4) { | ||
1226 | DEBUGP(4, dev, "T=0 assumes 0 byte reply\n"); | ||
1227 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
1228 | if (test_bit(IS_INVREV, &dev->flags)) | ||
1229 | xoutb(0xff, REG_BUF_DATA(iobase)); | ||
1230 | else | ||
1231 | xoutb(0x00, REG_BUF_DATA(iobase)); | ||
1232 | } | ||
1233 | |||
1234 | /* numSendBytes */ | ||
1235 | if (sendT0) | ||
1236 | nsend = nr; | ||
1237 | else { | ||
1238 | if (nr == 4) | ||
1239 | nsend = 5; | ||
1240 | else { | ||
1241 | nsend = 5 + (unsigned char)dev->sbuf[4]; | ||
1242 | if (dev->sbuf[4] == 0) | ||
1243 | nsend += 0x100; | ||
1244 | } | ||
1245 | } | ||
1246 | } else | ||
1247 | nsend = nr; | ||
1248 | |||
1249 | /* T0: output procedure byte */ | ||
1250 | if (test_bit(IS_INVREV, &dev->flags)) { | ||
1251 | DEBUGP(4, dev, "T=0 set Procedure byte (inverse-reverse) " | ||
1252 | "0x%.2x\n", invert_revert(dev->sbuf[1])); | ||
1253 | xoutb(invert_revert(dev->sbuf[1]), REG_NUM_BYTES(iobase)); | ||
1254 | } else { | ||
1255 | DEBUGP(4, dev, "T=0 set Procedure byte 0x%.2x\n", dev->sbuf[1]); | ||
1256 | xoutb(dev->sbuf[1], REG_NUM_BYTES(iobase)); | ||
1257 | } | ||
1258 | |||
1259 | DEBUGP(1, dev, "set NumSendBytes = 0x%.2x\n", | ||
1260 | (unsigned char)(nsend & 0xff)); | ||
1261 | xoutb((unsigned char)(nsend & 0xff), REG_NUM_SEND(iobase)); | ||
1262 | |||
1263 | DEBUGP(1, dev, "Trigger CARDMAN CONTROLLER (0x%.2x)\n", | ||
1264 | 0x40 /* SM_Active */ | ||
1265 | | (dev->flags0 & 2 ? 0 : 4) /* power on if needed */ | ||
1266 | |(dev->proto ? 0x10 : 0x08) /* T=1/T=0 */ | ||
1267 | |(nsend & 0x100) >> 8 /* MSB numSendBytes */ ); | ||
1268 | xoutb(0x40 /* SM_Active */ | ||
1269 | | (dev->flags0 & 2 ? 0 : 4) /* power on if needed */ | ||
1270 | |(dev->proto ? 0x10 : 0x08) /* T=1/T=0 */ | ||
1271 | |(nsend & 0x100) >> 8, /* MSB numSendBytes */ | ||
1272 | REG_FLAGS0(iobase)); | ||
1273 | |||
1274 | /* wait for xmit done */ | ||
1275 | if (dev->proto == 1) { | ||
1276 | DEBUGP(4, dev, "Wait for xmit done\n"); | ||
1277 | for (i = 0; i < 1000; i++) { | ||
1278 | if (inb(REG_FLAGS0(iobase)) & 0x08) | ||
1279 | break; | ||
1280 | msleep_interruptible(10); | ||
1281 | } | ||
1282 | if (i == 1000) { | ||
1283 | DEBUGP(4, dev, "timeout waiting for xmit done\n"); | ||
1284 | rc = -EIO; | ||
1285 | goto release_io; | ||
1286 | } | ||
1287 | } | ||
1288 | |||
1289 | /* T=1: wait for infoLen */ | ||
1290 | |||
1291 | infolen = 0; | ||
1292 | if (dev->proto) { | ||
1293 | /* wait until infoLen is valid */ | ||
1294 | for (i = 0; i < 6000; i++) { /* max waiting time of 1 min */ | ||
1295 | io_read_num_rec_bytes(iobase, &s); | ||
1296 | if (s >= 3) { | ||
1297 | infolen = inb(REG_FLAGS1(iobase)); | ||
1298 | DEBUGP(4, dev, "infolen=%d\n", infolen); | ||
1299 | break; | ||
1300 | } | ||
1301 | msleep_interruptible(10); | ||
1302 | } | ||
1303 | if (i == 6000) { | ||
1304 | DEBUGP(4, dev, "timeout waiting for infoLen\n"); | ||
1305 | rc = -EIO; | ||
1306 | goto release_io; | ||
1307 | } | ||
1308 | } else | ||
1309 | clear_bit(IS_PROCBYTE_PRESENT, &dev->flags); | ||
1310 | |||
1311 | /* numRecBytes | bit9 of numRecytes */ | ||
1312 | io_read_num_rec_bytes(iobase, &dev->rlen); | ||
1313 | for (i = 0; i < 600; i++) { /* max waiting time of 2 sec */ | ||
1314 | if (dev->proto) { | ||
1315 | if (dev->rlen >= infolen + 4) | ||
1316 | break; | ||
1317 | } | ||
1318 | msleep_interruptible(10); | ||
1319 | /* numRecBytes | bit9 of numRecytes */ | ||
1320 | io_read_num_rec_bytes(iobase, &s); | ||
1321 | if (s > dev->rlen) { | ||
1322 | DEBUGP(1, dev, "NumRecBytes inc (reset timeout)\n"); | ||
1323 | i = 0; /* reset timeout */ | ||
1324 | dev->rlen = s; | ||
1325 | } | ||
1326 | /* T=0: we are done when numRecBytes doesn't | ||
1327 | * increment any more and NoProcedureByte | ||
1328 | * is set and numRecBytes == bytes sent + 6 | ||
1329 | * (header bytes + data + 1 for sw2) | ||
1330 | * except when the card replies an error | ||
1331 | * which means, no data will be sent back. | ||
1332 | */ | ||
1333 | else if (dev->proto == 0) { | ||
1334 | if ((inb(REG_BUF_ADDR(iobase)) & 0x80)) { | ||
1335 | /* no procedure byte received since last read */ | ||
1336 | DEBUGP(1, dev, "NoProcedure byte set\n"); | ||
1337 | /* i=0; */ | ||
1338 | } else { | ||
1339 | /* procedure byte received since last read */ | ||
1340 | DEBUGP(1, dev, "NoProcedure byte unset " | ||
1341 | "(reset timeout)\n"); | ||
1342 | dev->procbyte = inb(REG_FLAGS1(iobase)); | ||
1343 | DEBUGP(1, dev, "Read procedure byte 0x%.2x\n", | ||
1344 | dev->procbyte); | ||
1345 | i = 0; /* resettimeout */ | ||
1346 | } | ||
1347 | if (inb(REG_FLAGS0(iobase)) & 0x08) { | ||
1348 | DEBUGP(1, dev, "T0Done flag (read reply)\n"); | ||
1349 | break; | ||
1350 | } | ||
1351 | } | ||
1352 | if (dev->proto) | ||
1353 | infolen = inb(REG_FLAGS1(iobase)); | ||
1354 | } | ||
1355 | if (i == 600) { | ||
1356 | DEBUGP(1, dev, "timeout waiting for numRecBytes\n"); | ||
1357 | rc = -EIO; | ||
1358 | goto release_io; | ||
1359 | } else { | ||
1360 | if (dev->proto == 0) { | ||
1361 | DEBUGP(1, dev, "Wait for T0Done bit to be set\n"); | ||
1362 | for (i = 0; i < 1000; i++) { | ||
1363 | if (inb(REG_FLAGS0(iobase)) & 0x08) | ||
1364 | break; | ||
1365 | msleep_interruptible(10); | ||
1366 | } | ||
1367 | if (i == 1000) { | ||
1368 | DEBUGP(1, dev, "timeout waiting for T0Done\n"); | ||
1369 | rc = -EIO; | ||
1370 | goto release_io; | ||
1371 | } | ||
1372 | |||
1373 | dev->procbyte = inb(REG_FLAGS1(iobase)); | ||
1374 | DEBUGP(4, dev, "Read procedure byte 0x%.2x\n", | ||
1375 | dev->procbyte); | ||
1376 | |||
1377 | io_read_num_rec_bytes(iobase, &dev->rlen); | ||
1378 | DEBUGP(4, dev, "Read NumRecBytes = %i\n", dev->rlen); | ||
1379 | |||
1380 | } | ||
1381 | } | ||
1382 | /* T=1: read offset=zero, T=0: read offset=after challenge */ | ||
1383 | dev->rpos = dev->proto ? 0 : nr == 4 ? 5 : nr > dev->rlen ? 5 : nr; | ||
1384 | DEBUGP(4, dev, "dev->rlen = %i, dev->rpos = %i, nr = %i\n", | ||
1385 | dev->rlen, dev->rpos, nr); | ||
1386 | |||
1387 | release_io: | ||
1388 | DEBUGP(4, dev, "Reset SM\n"); | ||
1389 | xoutb(0x80, REG_FLAGS0(iobase)); /* reset SM */ | ||
1390 | |||
1391 | if (rc < 0) { | ||
1392 | DEBUGP(4, dev, "Write failed but clear T_Active\n"); | ||
1393 | dev->flags1 &= 0xdf; | ||
1394 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1395 | } | ||
1396 | |||
1397 | clear_bit(LOCK_IO, &dev->flags); | ||
1398 | wake_up_interruptible(&dev->ioq); | ||
1399 | wake_up_interruptible(&dev->readq); /* tell read we have data */ | ||
1400 | |||
1401 | /* ITSEC E2: clear write buffer */ | ||
1402 | memset((char *)dev->sbuf, 0, 512); | ||
1403 | |||
1404 | /* return error or actually written bytes */ | ||
1405 | DEBUGP(2, dev, "<- cmm_write\n"); | ||
1406 | return rc < 0 ? rc : nr; | ||
1407 | } | ||
1408 | |||
1409 | static void start_monitor(struct cm4000_dev *dev) | ||
1410 | { | ||
1411 | DEBUGP(3, dev, "-> start_monitor\n"); | ||
1412 | if (!dev->monitor_running) { | ||
1413 | DEBUGP(5, dev, "create, init and add timer\n"); | ||
1414 | init_timer(&dev->timer); | ||
1415 | dev->monitor_running = 1; | ||
1416 | dev->timer.expires = jiffies; | ||
1417 | dev->timer.data = (unsigned long) dev; | ||
1418 | dev->timer.function = monitor_card; | ||
1419 | add_timer(&dev->timer); | ||
1420 | } else | ||
1421 | DEBUGP(5, dev, "monitor already running\n"); | ||
1422 | DEBUGP(3, dev, "<- start_monitor\n"); | ||
1423 | } | ||
1424 | |||
1425 | static void stop_monitor(struct cm4000_dev *dev) | ||
1426 | { | ||
1427 | DEBUGP(3, dev, "-> stop_monitor\n"); | ||
1428 | if (dev->monitor_running) { | ||
1429 | DEBUGP(5, dev, "stopping monitor\n"); | ||
1430 | terminate_monitor(dev); | ||
1431 | /* reset monitor SM */ | ||
1432 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1433 | clear_bit(IS_ATR_PRESENT, &dev->flags); | ||
1434 | } else | ||
1435 | DEBUGP(5, dev, "monitor already stopped\n"); | ||
1436 | DEBUGP(3, dev, "<- stop_monitor\n"); | ||
1437 | } | ||
1438 | |||
1439 | static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | ||
1440 | unsigned long arg) | ||
1441 | { | ||
1442 | struct cm4000_dev *dev = filp->private_data; | ||
1443 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
1444 | dev_link_t *link; | ||
1445 | int size; | ||
1446 | int rc; | ||
1447 | #ifdef PCMCIA_DEBUG | ||
1448 | char *ioctl_names[CM_IOC_MAXNR + 1] = { | ||
1449 | [_IOC_NR(CM_IOCGSTATUS)] "CM_IOCGSTATUS", | ||
1450 | [_IOC_NR(CM_IOCGATR)] "CM_IOCGATR", | ||
1451 | [_IOC_NR(CM_IOCARDOFF)] "CM_IOCARDOFF", | ||
1452 | [_IOC_NR(CM_IOCSPTS)] "CM_IOCSPTS", | ||
1453 | [_IOC_NR(CM_IOSDBGLVL)] "CM4000_DBGLVL", | ||
1454 | }; | ||
1455 | #endif | ||
1456 | DEBUGP(3, dev, "cmm_ioctl(device=%d.%d) %s\n", imajor(inode), | ||
1457 | iminor(inode), ioctl_names[_IOC_NR(cmd)]); | ||
1458 | |||
1459 | link = dev_table[iminor(inode)]; | ||
1460 | if (!(DEV_OK(link))) { | ||
1461 | DEBUGP(4, dev, "DEV_OK false\n"); | ||
1462 | return -ENODEV; | ||
1463 | } | ||
1464 | |||
1465 | if (test_bit(IS_CMM_ABSENT, &dev->flags)) { | ||
1466 | DEBUGP(4, dev, "CMM_ABSENT flag set\n"); | ||
1467 | return -ENODEV; | ||
1468 | } | ||
1469 | |||
1470 | if (_IOC_TYPE(cmd) != CM_IOC_MAGIC) { | ||
1471 | DEBUGP(4, dev, "ioctype mismatch\n"); | ||
1472 | return -EINVAL; | ||
1473 | } | ||
1474 | if (_IOC_NR(cmd) > CM_IOC_MAXNR) { | ||
1475 | DEBUGP(4, dev, "iocnr mismatch\n"); | ||
1476 | return -EINVAL; | ||
1477 | } | ||
1478 | size = _IOC_SIZE(cmd); | ||
1479 | rc = 0; | ||
1480 | DEBUGP(4, dev, "iocdir=%.4x iocr=%.4x iocw=%.4x iocsize=%d cmd=%.4x\n", | ||
1481 | _IOC_DIR(cmd), _IOC_READ, _IOC_WRITE, size, cmd); | ||
1482 | |||
1483 | if (_IOC_DIR(cmd) & _IOC_READ) { | ||
1484 | if (!access_ok(VERIFY_WRITE, (void *)arg, size)) | ||
1485 | return -EFAULT; | ||
1486 | } | ||
1487 | if (_IOC_DIR(cmd) & _IOC_WRITE) { | ||
1488 | if (!access_ok(VERIFY_READ, (void *)arg, size)) | ||
1489 | return -EFAULT; | ||
1490 | } | ||
1491 | |||
1492 | switch (cmd) { | ||
1493 | case CM_IOCGSTATUS: | ||
1494 | DEBUGP(4, dev, " ... in CM_IOCGSTATUS\n"); | ||
1495 | { | ||
1496 | int status; | ||
1497 | |||
1498 | /* clear other bits, but leave inserted & powered as | ||
1499 | * they are */ | ||
1500 | status = dev->flags0 & 3; | ||
1501 | if (test_bit(IS_ATR_PRESENT, &dev->flags)) | ||
1502 | status |= CM_ATR_PRESENT; | ||
1503 | if (test_bit(IS_ATR_VALID, &dev->flags)) | ||
1504 | status |= CM_ATR_VALID; | ||
1505 | if (test_bit(IS_CMM_ABSENT, &dev->flags)) | ||
1506 | status |= CM_NO_READER; | ||
1507 | if (test_bit(IS_BAD_CARD, &dev->flags)) | ||
1508 | status |= CM_BAD_CARD; | ||
1509 | if (copy_to_user((int *)arg, &status, sizeof(int))) | ||
1510 | return -EFAULT; | ||
1511 | } | ||
1512 | return 0; | ||
1513 | case CM_IOCGATR: | ||
1514 | DEBUGP(4, dev, "... in CM_IOCGATR\n"); | ||
1515 | { | ||
1516 | struct atreq *atreq = (struct atreq *) arg; | ||
1517 | int tmp; | ||
1518 | /* allow nonblocking io and being interrupted */ | ||
1519 | if (wait_event_interruptible | ||
1520 | (dev->atrq, | ||
1521 | ((filp->f_flags & O_NONBLOCK) | ||
1522 | || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) | ||
1523 | != 0)))) { | ||
1524 | if (filp->f_flags & O_NONBLOCK) | ||
1525 | return -EAGAIN; | ||
1526 | return -ERESTARTSYS; | ||
1527 | } | ||
1528 | |||
1529 | if (test_bit(IS_ATR_VALID, &dev->flags) == 0) { | ||
1530 | tmp = -1; | ||
1531 | if (copy_to_user(&(atreq->atr_len), &tmp, | ||
1532 | sizeof(int))) | ||
1533 | return -EFAULT; | ||
1534 | } else { | ||
1535 | if (copy_to_user(atreq->atr, dev->atr, | ||
1536 | dev->atr_len)) | ||
1537 | return -EFAULT; | ||
1538 | |||
1539 | tmp = dev->atr_len; | ||
1540 | if (copy_to_user(&(atreq->atr_len), &tmp, sizeof(int))) | ||
1541 | return -EFAULT; | ||
1542 | } | ||
1543 | return 0; | ||
1544 | } | ||
1545 | case CM_IOCARDOFF: | ||
1546 | |||
1547 | #ifdef PCMCIA_DEBUG | ||
1548 | DEBUGP(4, dev, "... in CM_IOCARDOFF\n"); | ||
1549 | if (dev->flags0 & 0x01) { | ||
1550 | DEBUGP(4, dev, " Card inserted\n"); | ||
1551 | } else { | ||
1552 | DEBUGP(2, dev, " No card inserted\n"); | ||
1553 | } | ||
1554 | if (dev->flags0 & 0x02) { | ||
1555 | DEBUGP(4, dev, " Card powered\n"); | ||
1556 | } else { | ||
1557 | DEBUGP(2, dev, " Card not powered\n"); | ||
1558 | } | ||
1559 | #endif | ||
1560 | |||
1561 | /* is a card inserted and powered? */ | ||
1562 | if ((dev->flags0 & 0x01) && (dev->flags0 & 0x02)) { | ||
1563 | |||
1564 | /* get IO lock */ | ||
1565 | if (wait_event_interruptible | ||
1566 | (dev->ioq, | ||
1567 | ((filp->f_flags & O_NONBLOCK) | ||
1568 | || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) | ||
1569 | == 0)))) { | ||
1570 | if (filp->f_flags & O_NONBLOCK) | ||
1571 | return -EAGAIN; | ||
1572 | return -ERESTARTSYS; | ||
1573 | } | ||
1574 | /* Set Flags0 = 0x42 */ | ||
1575 | DEBUGP(4, dev, "Set Flags0=0x42 \n"); | ||
1576 | xoutb(0x42, REG_FLAGS0(iobase)); | ||
1577 | clear_bit(IS_ATR_PRESENT, &dev->flags); | ||
1578 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1579 | dev->mstate = M_CARDOFF; | ||
1580 | clear_bit(LOCK_IO, &dev->flags); | ||
1581 | if (wait_event_interruptible | ||
1582 | (dev->atrq, | ||
1583 | ((filp->f_flags & O_NONBLOCK) | ||
1584 | || (test_bit(IS_ATR_VALID, (void *)&dev->flags) != | ||
1585 | 0)))) { | ||
1586 | if (filp->f_flags & O_NONBLOCK) | ||
1587 | return -EAGAIN; | ||
1588 | return -ERESTARTSYS; | ||
1589 | } | ||
1590 | } | ||
1591 | /* release lock */ | ||
1592 | clear_bit(LOCK_IO, &dev->flags); | ||
1593 | wake_up_interruptible(&dev->ioq); | ||
1594 | |||
1595 | return 0; | ||
1596 | case CM_IOCSPTS: | ||
1597 | { | ||
1598 | struct ptsreq krnptsreq; | ||
1599 | |||
1600 | if (copy_from_user(&krnptsreq, (struct ptsreq *) arg, | ||
1601 | sizeof(struct ptsreq))) | ||
1602 | return -EFAULT; | ||
1603 | |||
1604 | rc = 0; | ||
1605 | DEBUGP(4, dev, "... in CM_IOCSPTS\n"); | ||
1606 | /* wait for ATR to get valid */ | ||
1607 | if (wait_event_interruptible | ||
1608 | (dev->atrq, | ||
1609 | ((filp->f_flags & O_NONBLOCK) | ||
1610 | || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) | ||
1611 | != 0)))) { | ||
1612 | if (filp->f_flags & O_NONBLOCK) | ||
1613 | return -EAGAIN; | ||
1614 | return -ERESTARTSYS; | ||
1615 | } | ||
1616 | /* get IO lock */ | ||
1617 | if (wait_event_interruptible | ||
1618 | (dev->ioq, | ||
1619 | ((filp->f_flags & O_NONBLOCK) | ||
1620 | || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) | ||
1621 | == 0)))) { | ||
1622 | if (filp->f_flags & O_NONBLOCK) | ||
1623 | return -EAGAIN; | ||
1624 | return -ERESTARTSYS; | ||
1625 | } | ||
1626 | |||
1627 | if ((rc = set_protocol(dev, &krnptsreq)) != 0) { | ||
1628 | /* auto power_on again */ | ||
1629 | dev->mstate = M_FETCH_ATR; | ||
1630 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1631 | } | ||
1632 | /* release lock */ | ||
1633 | clear_bit(LOCK_IO, &dev->flags); | ||
1634 | wake_up_interruptible(&dev->ioq); | ||
1635 | |||
1636 | } | ||
1637 | return rc; | ||
1638 | #ifdef PCMCIA_DEBUG | ||
1639 | case CM_IOSDBGLVL: /* set debug log level */ | ||
1640 | { | ||
1641 | int old_pc_debug = 0; | ||
1642 | |||
1643 | old_pc_debug = pc_debug; | ||
1644 | if (copy_from_user(&pc_debug, (int *)arg, sizeof(int))) | ||
1645 | return -EFAULT; | ||
1646 | |||
1647 | if (old_pc_debug != pc_debug) | ||
1648 | DEBUGP(0, dev, "Changed debug log level " | ||
1649 | "to %i\n", pc_debug); | ||
1650 | } | ||
1651 | return rc; | ||
1652 | #endif | ||
1653 | default: | ||
1654 | DEBUGP(4, dev, "... in default (unknown IOCTL code)\n"); | ||
1655 | return -EINVAL; | ||
1656 | } | ||
1657 | } | ||
1658 | |||
1659 | static int cmm_open(struct inode *inode, struct file *filp) | ||
1660 | { | ||
1661 | struct cm4000_dev *dev; | ||
1662 | dev_link_t *link; | ||
1663 | int rc, minor = iminor(inode); | ||
1664 | |||
1665 | if (minor >= CM4000_MAX_DEV) | ||
1666 | return -ENODEV; | ||
1667 | |||
1668 | link = dev_table[minor]; | ||
1669 | if (link == NULL || !(DEV_OK(link))) | ||
1670 | return -ENODEV; | ||
1671 | |||
1672 | if (link->open) | ||
1673 | return -EBUSY; | ||
1674 | |||
1675 | dev = link->priv; | ||
1676 | filp->private_data = dev; | ||
1677 | |||
1678 | DEBUGP(2, dev, "-> cmm_open(device=%d.%d process=%s,%d)\n", | ||
1679 | imajor(inode), minor, current->comm, current->pid); | ||
1680 | |||
1681 | /* init device variables, they may be "polluted" after close | ||
1682 | * or, the device may never have been closed (i.e. open failed) | ||
1683 | */ | ||
1684 | |||
1685 | ZERO_DEV(dev); | ||
1686 | |||
1687 | /* opening will always block since the | ||
1688 | * monitor will be started by open, which | ||
1689 | * means we have to wait for ATR becoming | ||
1690 | * vaild = block until valid (or card | ||
1691 | * inserted) | ||
1692 | */ | ||
1693 | if (filp->f_flags & O_NONBLOCK) | ||
1694 | return -EAGAIN; | ||
1695 | |||
1696 | dev->mdelay = T_50MSEC; | ||
1697 | |||
1698 | /* start monitoring the cardstatus */ | ||
1699 | start_monitor(dev); | ||
1700 | |||
1701 | link->open = 1; /* only one open per device */ | ||
1702 | rc = 0; | ||
1703 | |||
1704 | DEBUGP(2, dev, "<- cmm_open\n"); | ||
1705 | return nonseekable_open(inode, filp); | ||
1706 | } | ||
1707 | |||
1708 | static int cmm_close(struct inode *inode, struct file *filp) | ||
1709 | { | ||
1710 | struct cm4000_dev *dev; | ||
1711 | dev_link_t *link; | ||
1712 | int minor = iminor(inode); | ||
1713 | |||
1714 | if (minor >= CM4000_MAX_DEV) | ||
1715 | return -ENODEV; | ||
1716 | |||
1717 | link = dev_table[minor]; | ||
1718 | if (link == NULL) | ||
1719 | return -ENODEV; | ||
1720 | |||
1721 | dev = link->priv; | ||
1722 | |||
1723 | DEBUGP(2, dev, "-> cmm_close(maj/min=%d.%d)\n", | ||
1724 | imajor(inode), minor); | ||
1725 | |||
1726 | stop_monitor(dev); | ||
1727 | |||
1728 | ZERO_DEV(dev); | ||
1729 | |||
1730 | link->open = 0; /* only one open per device */ | ||
1731 | wake_up(&dev->devq); /* socket removed? */ | ||
1732 | |||
1733 | DEBUGP(2, dev, "cmm_close\n"); | ||
1734 | return 0; | ||
1735 | } | ||
1736 | |||
1737 | static void cmm_cm4000_release(dev_link_t * link) | ||
1738 | { | ||
1739 | struct cm4000_dev *dev = link->priv; | ||
1740 | |||
1741 | /* dont terminate the monitor, rather rely on | ||
1742 | * close doing that for us. | ||
1743 | */ | ||
1744 | DEBUGP(3, dev, "-> cmm_cm4000_release\n"); | ||
1745 | while (link->open) { | ||
1746 | printk(KERN_INFO MODULE_NAME ": delaying release until " | ||
1747 | "process has terminated\n"); | ||
1748 | /* note: don't interrupt us: | ||
1749 | * close the applications which own | ||
1750 | * the devices _first_ ! | ||
1751 | */ | ||
1752 | wait_event(dev->devq, (link->open == 0)); | ||
1753 | } | ||
1754 | /* dev->devq=NULL; this cannot be zeroed earlier */ | ||
1755 | DEBUGP(3, dev, "<- cmm_cm4000_release\n"); | ||
1756 | return; | ||
1757 | } | ||
1758 | |||
1759 | /*==== Interface to PCMCIA Layer =======================================*/ | ||
1760 | |||
1761 | static void cm4000_config(dev_link_t * link, int devno) | ||
1762 | { | ||
1763 | client_handle_t handle = link->handle; | ||
1764 | struct cm4000_dev *dev; | ||
1765 | tuple_t tuple; | ||
1766 | cisparse_t parse; | ||
1767 | config_info_t conf; | ||
1768 | u_char buf[64]; | ||
1769 | int fail_fn, fail_rc; | ||
1770 | int rc; | ||
1771 | |||
1772 | /* read the config-tuples */ | ||
1773 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
1774 | tuple.Attributes = 0; | ||
1775 | tuple.TupleData = buf; | ||
1776 | tuple.TupleDataMax = sizeof(buf); | ||
1777 | tuple.TupleOffset = 0; | ||
1778 | |||
1779 | if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) { | ||
1780 | fail_fn = GetFirstTuple; | ||
1781 | goto cs_failed; | ||
1782 | } | ||
1783 | if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) { | ||
1784 | fail_fn = GetTupleData; | ||
1785 | goto cs_failed; | ||
1786 | } | ||
1787 | if ((fail_rc = | ||
1788 | pcmcia_parse_tuple(handle, &tuple, &parse)) != CS_SUCCESS) { | ||
1789 | fail_fn = ParseTuple; | ||
1790 | goto cs_failed; | ||
1791 | } | ||
1792 | if ((fail_rc = | ||
1793 | pcmcia_get_configuration_info(handle, &conf)) != CS_SUCCESS) { | ||
1794 | fail_fn = GetConfigurationInfo; | ||
1795 | goto cs_failed; | ||
1796 | } | ||
1797 | |||
1798 | link->state |= DEV_CONFIG; | ||
1799 | link->conf.ConfigBase = parse.config.base; | ||
1800 | link->conf.Present = parse.config.rmask[0]; | ||
1801 | link->conf.Vcc = conf.Vcc; | ||
1802 | |||
1803 | link->io.BasePort2 = 0; | ||
1804 | link->io.NumPorts2 = 0; | ||
1805 | link->io.Attributes2 = 0; | ||
1806 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
1807 | for (rc = pcmcia_get_first_tuple(handle, &tuple); | ||
1808 | rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(handle, &tuple)) { | ||
1809 | |||
1810 | rc = pcmcia_get_tuple_data(handle, &tuple); | ||
1811 | if (rc != CS_SUCCESS) | ||
1812 | continue; | ||
1813 | rc = pcmcia_parse_tuple(handle, &tuple, &parse); | ||
1814 | if (rc != CS_SUCCESS) | ||
1815 | continue; | ||
1816 | |||
1817 | link->conf.ConfigIndex = parse.cftable_entry.index; | ||
1818 | |||
1819 | if (!parse.cftable_entry.io.nwin) | ||
1820 | continue; | ||
1821 | |||
1822 | /* Get the IOaddr */ | ||
1823 | link->io.BasePort1 = parse.cftable_entry.io.win[0].base; | ||
1824 | link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; | ||
1825 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
1826 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT)) | ||
1827 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
1828 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT)) | ||
1829 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
1830 | link->io.IOAddrLines = parse.cftable_entry.io.flags | ||
1831 | & CISTPL_IO_LINES_MASK; | ||
1832 | |||
1833 | rc = pcmcia_request_io(handle, &link->io); | ||
1834 | if (rc == CS_SUCCESS) | ||
1835 | break; /* we are done */ | ||
1836 | } | ||
1837 | if (rc != CS_SUCCESS) | ||
1838 | goto cs_release; | ||
1839 | |||
1840 | link->conf.IntType = 00000002; | ||
1841 | |||
1842 | if ((fail_rc = | ||
1843 | pcmcia_request_configuration(handle, &link->conf)) != CS_SUCCESS) { | ||
1844 | fail_fn = RequestConfiguration; | ||
1845 | goto cs_release; | ||
1846 | } | ||
1847 | |||
1848 | dev = link->priv; | ||
1849 | sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); | ||
1850 | dev->node.major = major; | ||
1851 | dev->node.minor = devno; | ||
1852 | dev->node.next = NULL; | ||
1853 | link->dev = &dev->node; | ||
1854 | link->state &= ~DEV_CONFIG_PENDING; | ||
1855 | |||
1856 | return; | ||
1857 | |||
1858 | cs_failed: | ||
1859 | cs_error(handle, fail_fn, fail_rc); | ||
1860 | cs_release: | ||
1861 | cm4000_release(link); | ||
1862 | |||
1863 | link->state &= ~DEV_CONFIG_PENDING; | ||
1864 | } | ||
1865 | |||
1866 | static int cm4000_event(event_t event, int priority, | ||
1867 | event_callback_args_t *args) | ||
1868 | { | ||
1869 | dev_link_t *link; | ||
1870 | struct cm4000_dev *dev; | ||
1871 | int devno; | ||
1872 | |||
1873 | link = args->client_data; | ||
1874 | dev = link->priv; | ||
1875 | |||
1876 | DEBUGP(3, dev, "-> cm4000_event\n"); | ||
1877 | for (devno = 0; devno < CM4000_MAX_DEV; devno++) | ||
1878 | if (dev_table[devno] == link) | ||
1879 | break; | ||
1880 | |||
1881 | if (devno == CM4000_MAX_DEV) | ||
1882 | return CS_BAD_ADAPTER; | ||
1883 | |||
1884 | switch (event) { | ||
1885 | case CS_EVENT_CARD_INSERTION: | ||
1886 | DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n"); | ||
1887 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
1888 | cm4000_config(link, devno); | ||
1889 | break; | ||
1890 | case CS_EVENT_CARD_REMOVAL: | ||
1891 | DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); | ||
1892 | link->state &= ~DEV_PRESENT; | ||
1893 | stop_monitor(dev); | ||
1894 | break; | ||
1895 | case CS_EVENT_PM_SUSPEND: | ||
1896 | DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " | ||
1897 | "(fall-through to CS_EVENT_RESET_PHYSICAL)\n"); | ||
1898 | link->state |= DEV_SUSPEND; | ||
1899 | /* fall-through */ | ||
1900 | case CS_EVENT_RESET_PHYSICAL: | ||
1901 | DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n"); | ||
1902 | if (link->state & DEV_CONFIG) { | ||
1903 | DEBUGP(5, dev, "ReleaseConfiguration\n"); | ||
1904 | pcmcia_release_configuration(link->handle); | ||
1905 | } | ||
1906 | stop_monitor(dev); | ||
1907 | break; | ||
1908 | case CS_EVENT_PM_RESUME: | ||
1909 | DEBUGP(5, dev, "CS_EVENT_PM_RESUME " | ||
1910 | "(fall-through to CS_EVENT_CARD_RESET)\n"); | ||
1911 | link->state &= ~DEV_SUSPEND; | ||
1912 | /* fall-through */ | ||
1913 | case CS_EVENT_CARD_RESET: | ||
1914 | DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n"); | ||
1915 | if ((link->state & DEV_CONFIG)) { | ||
1916 | DEBUGP(5, dev, "RequestConfiguration\n"); | ||
1917 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1918 | } | ||
1919 | if (link->open) | ||
1920 | start_monitor(dev); | ||
1921 | break; | ||
1922 | default: | ||
1923 | DEBUGP(5, dev, "unknown event %.2x\n", event); | ||
1924 | break; | ||
1925 | } | ||
1926 | DEBUGP(3, dev, "<- cm4000_event\n"); | ||
1927 | return CS_SUCCESS; | ||
1928 | } | ||
1929 | |||
1930 | static void cm4000_release(dev_link_t *link) | ||
1931 | { | ||
1932 | cmm_cm4000_release(link->priv); /* delay release until device closed */ | ||
1933 | pcmcia_release_configuration(link->handle); | ||
1934 | pcmcia_release_io(link->handle, &link->io); | ||
1935 | } | ||
1936 | |||
1937 | static dev_link_t *cm4000_attach(void) | ||
1938 | { | ||
1939 | struct cm4000_dev *dev; | ||
1940 | dev_link_t *link; | ||
1941 | client_reg_t client_reg; | ||
1942 | int i; | ||
1943 | |||
1944 | for (i = 0; i < CM4000_MAX_DEV; i++) | ||
1945 | if (dev_table[i] == NULL) | ||
1946 | break; | ||
1947 | |||
1948 | if (i == CM4000_MAX_DEV) { | ||
1949 | printk(KERN_NOTICE MODULE_NAME ": all devices in use\n"); | ||
1950 | return NULL; | ||
1951 | } | ||
1952 | |||
1953 | /* create a new cm4000_cs device */ | ||
1954 | dev = kzalloc(sizeof(struct cm4000_dev), GFP_KERNEL); | ||
1955 | if (dev == NULL) | ||
1956 | return NULL; | ||
1957 | |||
1958 | link = &dev->link; | ||
1959 | link->priv = dev; | ||
1960 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
1961 | dev_table[i] = link; | ||
1962 | |||
1963 | /* register with card services */ | ||
1964 | client_reg.dev_info = &dev_info; | ||
1965 | client_reg.EventMask = | ||
1966 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
1967 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
1968 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
1969 | client_reg.Version = 0x0210; | ||
1970 | client_reg.event_callback_args.client_data = link; | ||
1971 | |||
1972 | i = pcmcia_register_client(&link->handle, &client_reg); | ||
1973 | if (i) { | ||
1974 | cs_error(link->handle, RegisterClient, i); | ||
1975 | cm4000_detach(link); | ||
1976 | return NULL; | ||
1977 | } | ||
1978 | |||
1979 | init_waitqueue_head(&dev->devq); | ||
1980 | init_waitqueue_head(&dev->ioq); | ||
1981 | init_waitqueue_head(&dev->atrq); | ||
1982 | init_waitqueue_head(&dev->readq); | ||
1983 | |||
1984 | return link; | ||
1985 | } | ||
1986 | |||
1987 | static void cm4000_detach_by_devno(int devno, dev_link_t * link) | ||
1988 | { | ||
1989 | struct cm4000_dev *dev = link->priv; | ||
1990 | |||
1991 | DEBUGP(3, dev, "-> detach_by_devno(devno=%d)\n", devno); | ||
1992 | |||
1993 | if (link->state & DEV_CONFIG) { | ||
1994 | DEBUGP(5, dev, "device still configured (try to release it)\n"); | ||
1995 | cm4000_release(link); | ||
1996 | } | ||
1997 | |||
1998 | if (link->handle) { | ||
1999 | pcmcia_deregister_client(link->handle); | ||
2000 | } | ||
2001 | |||
2002 | dev_table[devno] = NULL; | ||
2003 | kfree(dev); | ||
2004 | return; | ||
2005 | } | ||
2006 | |||
2007 | static void cm4000_detach(dev_link_t * link) | ||
2008 | { | ||
2009 | int i; | ||
2010 | |||
2011 | /* find device */ | ||
2012 | for (i = 0; i < CM4000_MAX_DEV; i++) | ||
2013 | if (dev_table[i] == link) | ||
2014 | break; | ||
2015 | |||
2016 | if (i == CM4000_MAX_DEV) | ||
2017 | return; | ||
2018 | |||
2019 | cm4000_detach_by_devno(i, link); | ||
2020 | return; | ||
2021 | } | ||
2022 | |||
2023 | static struct file_operations cm4000_fops = { | ||
2024 | .owner = THIS_MODULE, | ||
2025 | .read = cmm_read, | ||
2026 | .write = cmm_write, | ||
2027 | .ioctl = cmm_ioctl, | ||
2028 | .open = cmm_open, | ||
2029 | .release= cmm_close, | ||
2030 | }; | ||
2031 | |||
2032 | static struct pcmcia_device_id cm4000_ids[] = { | ||
2033 | PCMCIA_DEVICE_MANF_CARD(0x0223, 0x0002), | ||
2034 | PCMCIA_DEVICE_PROD_ID12("CardMan", "4000", 0x2FB368CA, 0xA2BD8C39), | ||
2035 | PCMCIA_DEVICE_NULL, | ||
2036 | }; | ||
2037 | MODULE_DEVICE_TABLE(pcmcia, cm4000_ids); | ||
2038 | |||
2039 | static struct pcmcia_driver cm4000_driver = { | ||
2040 | .owner = THIS_MODULE, | ||
2041 | .drv = { | ||
2042 | .name = "cm4000_cs", | ||
2043 | }, | ||
2044 | .attach = cm4000_attach, | ||
2045 | .detach = cm4000_detach, | ||
2046 | .event = cm4000_event, | ||
2047 | .id_table = cm4000_ids, | ||
2048 | }; | ||
2049 | |||
2050 | static int __init cmm_init(void) | ||
2051 | { | ||
2052 | printk(KERN_INFO "%s\n", version); | ||
2053 | pcmcia_register_driver(&cm4000_driver); | ||
2054 | major = register_chrdev(0, DEVICE_NAME, &cm4000_fops); | ||
2055 | if (major < 0) { | ||
2056 | printk(KERN_WARNING MODULE_NAME | ||
2057 | ": could not get major number\n"); | ||
2058 | return -1; | ||
2059 | } | ||
2060 | |||
2061 | return 0; | ||
2062 | } | ||
2063 | |||
2064 | static void __exit cmm_exit(void) | ||
2065 | { | ||
2066 | int i; | ||
2067 | |||
2068 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | ||
2069 | pcmcia_unregister_driver(&cm4000_driver); | ||
2070 | for (i = 0; i < CM4000_MAX_DEV; i++) | ||
2071 | if (dev_table[i]) | ||
2072 | cm4000_detach_by_devno(i, dev_table[i]); | ||
2073 | unregister_chrdev(major, DEVICE_NAME); | ||
2074 | }; | ||
2075 | |||
2076 | module_init(cmm_init); | ||
2077 | module_exit(cmm_exit); | ||
2078 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c new file mode 100644 index 000000000000..4c698d908ffa --- /dev/null +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -0,0 +1,841 @@ | |||
1 | /* | ||
2 | * A driver for the Omnikey PCMCIA smartcard reader CardMan 4040 | ||
3 | * | ||
4 | * (c) 2000-2004 Omnikey AG (http://www.omnikey.com/) | ||
5 | * | ||
6 | * (C) 2005 Harald Welte <laforge@gnumonks.org> | ||
7 | * - add support for poll() | ||
8 | * - driver cleanup | ||
9 | * - add waitqueues | ||
10 | * - adhere to linux kernel coding style and policies | ||
11 | * - support 2.6.13 "new style" pcmcia interface | ||
12 | * | ||
13 | * The device basically is a USB CCID compliant device that has been | ||
14 | * attached to an I/O-Mapped FIFO. | ||
15 | * | ||
16 | * All rights reserved, Dual BSD/GPL Licensed. | ||
17 | */ | ||
18 | |||
19 | /* #define PCMCIA_DEBUG 6 */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/poll.h> | ||
28 | #include <linux/wait.h> | ||
29 | #include <asm/uaccess.h> | ||
30 | #include <asm/io.h> | ||
31 | |||
32 | #include <pcmcia/cs_types.h> | ||
33 | #include <pcmcia/cs.h> | ||
34 | #include <pcmcia/cistpl.h> | ||
35 | #include <pcmcia/cisreg.h> | ||
36 | #include <pcmcia/ciscode.h> | ||
37 | #include <pcmcia/ds.h> | ||
38 | |||
39 | #include "cm4040_cs.h" | ||
40 | |||
41 | |||
42 | #ifdef PCMCIA_DEBUG | ||
43 | #define reader_to_dev(x) (&handle_to_dev(x->link.handle)) | ||
44 | static int pc_debug = PCMCIA_DEBUG; | ||
45 | module_param(pc_debug, int, 0600); | ||
46 | #define DEBUGP(n, rdr, x, args...) do { \ | ||
47 | if (pc_debug >= (n)) \ | ||
48 | dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x, \ | ||
49 | __FUNCTION__ , ##args); \ | ||
50 | } while (0) | ||
51 | #else | ||
52 | #define DEBUGP(n, rdr, x, args...) | ||
53 | #endif | ||
54 | |||
55 | static char *version = | ||
56 | "OMNIKEY CardMan 4040 v1.1.0gm4 - All bugs added by Harald Welte"; | ||
57 | |||
58 | #define CCID_DRIVER_BULK_DEFAULT_TIMEOUT (150*HZ) | ||
59 | #define CCID_DRIVER_ASYNC_POWERUP_TIMEOUT (35*HZ) | ||
60 | #define CCID_DRIVER_MINIMUM_TIMEOUT (3*HZ) | ||
61 | #define READ_WRITE_BUFFER_SIZE 512 | ||
62 | #define POLL_LOOP_COUNT 1000 | ||
63 | |||
64 | /* how often to poll for fifo status change */ | ||
65 | #define POLL_PERIOD msecs_to_jiffies(10) | ||
66 | |||
67 | static void reader_release(dev_link_t *link); | ||
68 | static void reader_detach(dev_link_t *link); | ||
69 | |||
70 | static int major; | ||
71 | |||
72 | #define BS_READABLE 0x01 | ||
73 | #define BS_WRITABLE 0x02 | ||
74 | |||
75 | struct reader_dev { | ||
76 | dev_link_t link; | ||
77 | dev_node_t node; | ||
78 | wait_queue_head_t devq; | ||
79 | wait_queue_head_t poll_wait; | ||
80 | wait_queue_head_t read_wait; | ||
81 | wait_queue_head_t write_wait; | ||
82 | unsigned long buffer_status; | ||
83 | unsigned long timeout; | ||
84 | unsigned char s_buf[READ_WRITE_BUFFER_SIZE]; | ||
85 | unsigned char r_buf[READ_WRITE_BUFFER_SIZE]; | ||
86 | struct timer_list poll_timer; | ||
87 | }; | ||
88 | |||
89 | static dev_info_t dev_info = MODULE_NAME; | ||
90 | static dev_link_t *dev_table[CM_MAX_DEV]; | ||
91 | |||
92 | #ifndef PCMCIA_DEBUG | ||
93 | #define xoutb outb | ||
94 | #define xinb inb | ||
95 | #else | ||
96 | static inline void xoutb(unsigned char val, unsigned short port) | ||
97 | { | ||
98 | if (pc_debug >= 7) | ||
99 | printk(KERN_DEBUG "outb(val=%.2x,port=%.4x)\n", val, port); | ||
100 | outb(val, port); | ||
101 | } | ||
102 | |||
103 | static inline unsigned char xinb(unsigned short port) | ||
104 | { | ||
105 | unsigned char val; | ||
106 | |||
107 | val = inb(port); | ||
108 | if (pc_debug >= 7) | ||
109 | printk(KERN_DEBUG "%.2x=inb(%.4x)\n", val, port); | ||
110 | return val; | ||
111 | } | ||
112 | #endif | ||
113 | |||
114 | /* poll the device fifo status register. not to be confused with | ||
115 | * the poll syscall. */ | ||
116 | static void cm4040_do_poll(unsigned long dummy) | ||
117 | { | ||
118 | struct reader_dev *dev = (struct reader_dev *) dummy; | ||
119 | unsigned int obs = xinb(dev->link.io.BasePort1 | ||
120 | + REG_OFFSET_BUFFER_STATUS); | ||
121 | |||
122 | if ((obs & BSR_BULK_IN_FULL)) { | ||
123 | set_bit(BS_READABLE, &dev->buffer_status); | ||
124 | DEBUGP(4, dev, "waking up read_wait\n"); | ||
125 | wake_up_interruptible(&dev->read_wait); | ||
126 | } else | ||
127 | clear_bit(BS_READABLE, &dev->buffer_status); | ||
128 | |||
129 | if (!(obs & BSR_BULK_OUT_FULL)) { | ||
130 | set_bit(BS_WRITABLE, &dev->buffer_status); | ||
131 | DEBUGP(4, dev, "waking up write_wait\n"); | ||
132 | wake_up_interruptible(&dev->write_wait); | ||
133 | } else | ||
134 | clear_bit(BS_WRITABLE, &dev->buffer_status); | ||
135 | |||
136 | if (dev->buffer_status) | ||
137 | wake_up_interruptible(&dev->poll_wait); | ||
138 | |||
139 | mod_timer(&dev->poll_timer, jiffies + POLL_PERIOD); | ||
140 | } | ||
141 | |||
142 | static void cm4040_stop_poll(struct reader_dev *dev) | ||
143 | { | ||
144 | del_timer_sync(&dev->poll_timer); | ||
145 | } | ||
146 | |||
147 | static int wait_for_bulk_out_ready(struct reader_dev *dev) | ||
148 | { | ||
149 | int i, rc; | ||
150 | int iobase = dev->link.io.BasePort1; | ||
151 | |||
152 | for (i = 0; i < POLL_LOOP_COUNT; i++) { | ||
153 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) | ||
154 | & BSR_BULK_OUT_FULL) == 0) { | ||
155 | DEBUGP(4, dev, "BulkOut empty (i=%d)\n", i); | ||
156 | return 1; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | DEBUGP(4, dev, "wait_event_interruptible_timeout(timeout=%ld\n", | ||
161 | dev->timeout); | ||
162 | rc = wait_event_interruptible_timeout(dev->write_wait, | ||
163 | test_and_clear_bit(BS_WRITABLE, | ||
164 | &dev->buffer_status), | ||
165 | dev->timeout); | ||
166 | |||
167 | if (rc > 0) | ||
168 | DEBUGP(4, dev, "woke up: BulkOut empty\n"); | ||
169 | else if (rc == 0) | ||
170 | DEBUGP(4, dev, "woke up: BulkOut full, returning 0 :(\n"); | ||
171 | else if (rc < 0) | ||
172 | DEBUGP(4, dev, "woke up: signal arrived\n"); | ||
173 | |||
174 | return rc; | ||
175 | } | ||
176 | |||
177 | /* Write to Sync Control Register */ | ||
178 | static int write_sync_reg(unsigned char val, struct reader_dev *dev) | ||
179 | { | ||
180 | int iobase = dev->link.io.BasePort1; | ||
181 | int rc; | ||
182 | |||
183 | rc = wait_for_bulk_out_ready(dev); | ||
184 | if (rc <= 0) | ||
185 | return rc; | ||
186 | |||
187 | xoutb(val, iobase + REG_OFFSET_SYNC_CONTROL); | ||
188 | rc = wait_for_bulk_out_ready(dev); | ||
189 | if (rc <= 0) | ||
190 | return rc; | ||
191 | |||
192 | return 1; | ||
193 | } | ||
194 | |||
195 | static int wait_for_bulk_in_ready(struct reader_dev *dev) | ||
196 | { | ||
197 | int i, rc; | ||
198 | int iobase = dev->link.io.BasePort1; | ||
199 | |||
200 | for (i = 0; i < POLL_LOOP_COUNT; i++) { | ||
201 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) | ||
202 | & BSR_BULK_IN_FULL) == BSR_BULK_IN_FULL) { | ||
203 | DEBUGP(3, dev, "BulkIn full (i=%d)\n", i); | ||
204 | return 1; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | DEBUGP(4, dev, "wait_event_interruptible_timeout(timeout=%ld\n", | ||
209 | dev->timeout); | ||
210 | rc = wait_event_interruptible_timeout(dev->read_wait, | ||
211 | test_and_clear_bit(BS_READABLE, | ||
212 | &dev->buffer_status), | ||
213 | dev->timeout); | ||
214 | if (rc > 0) | ||
215 | DEBUGP(4, dev, "woke up: BulkIn full\n"); | ||
216 | else if (rc == 0) | ||
217 | DEBUGP(4, dev, "woke up: BulkIn not full, returning 0 :(\n"); | ||
218 | else if (rc < 0) | ||
219 | DEBUGP(4, dev, "woke up: signal arrived\n"); | ||
220 | |||
221 | return rc; | ||
222 | } | ||
223 | |||
224 | static ssize_t cm4040_read(struct file *filp, char __user *buf, | ||
225 | size_t count, loff_t *ppos) | ||
226 | { | ||
227 | struct reader_dev *dev = filp->private_data; | ||
228 | int iobase = dev->link.io.BasePort1; | ||
229 | size_t bytes_to_read; | ||
230 | unsigned long i; | ||
231 | size_t min_bytes_to_read; | ||
232 | int rc; | ||
233 | unsigned char uc; | ||
234 | |||
235 | DEBUGP(2, dev, "-> cm4040_read(%s,%d)\n", current->comm, current->pid); | ||
236 | |||
237 | if (count == 0) | ||
238 | return 0; | ||
239 | |||
240 | if (count < 10) | ||
241 | return -EFAULT; | ||
242 | |||
243 | if (filp->f_flags & O_NONBLOCK) { | ||
244 | DEBUGP(4, dev, "filep->f_flags O_NONBLOCK set\n"); | ||
245 | DEBUGP(2, dev, "<- cm4040_read (failure)\n"); | ||
246 | return -EAGAIN; | ||
247 | } | ||
248 | |||
249 | if ((dev->link.state & DEV_PRESENT)==0) | ||
250 | return -ENODEV; | ||
251 | |||
252 | for (i = 0; i < 5; i++) { | ||
253 | rc = wait_for_bulk_in_ready(dev); | ||
254 | if (rc <= 0) { | ||
255 | DEBUGP(5, dev, "wait_for_bulk_in_ready rc=%.2x\n", rc); | ||
256 | DEBUGP(2, dev, "<- cm4040_read (failed)\n"); | ||
257 | if (rc == -ERESTARTSYS) | ||
258 | return rc; | ||
259 | return -EIO; | ||
260 | } | ||
261 | dev->r_buf[i] = xinb(iobase + REG_OFFSET_BULK_IN); | ||
262 | #ifdef PCMCIA_DEBUG | ||
263 | if (pc_debug >= 6) | ||
264 | printk(KERN_DEBUG "%lu:%2x ", i, dev->r_buf[i]); | ||
265 | } | ||
266 | printk("\n"); | ||
267 | #else | ||
268 | } | ||
269 | #endif | ||
270 | |||
271 | bytes_to_read = 5 + le32_to_cpu(*(__le32 *)&dev->r_buf[1]); | ||
272 | |||
273 | DEBUGP(6, dev, "BytesToRead=%lu\n", bytes_to_read); | ||
274 | |||
275 | min_bytes_to_read = min(count, bytes_to_read + 5); | ||
276 | |||
277 | DEBUGP(6, dev, "Min=%lu\n", min_bytes_to_read); | ||
278 | |||
279 | for (i = 0; i < (min_bytes_to_read-5); i++) { | ||
280 | rc = wait_for_bulk_in_ready(dev); | ||
281 | if (rc <= 0) { | ||
282 | DEBUGP(5, dev, "wait_for_bulk_in_ready rc=%.2x\n", rc); | ||
283 | DEBUGP(2, dev, "<- cm4040_read (failed)\n"); | ||
284 | if (rc == -ERESTARTSYS) | ||
285 | return rc; | ||
286 | return -EIO; | ||
287 | } | ||
288 | dev->r_buf[i+5] = xinb(iobase + REG_OFFSET_BULK_IN); | ||
289 | #ifdef PCMCIA_DEBUG | ||
290 | if (pc_debug >= 6) | ||
291 | printk(KERN_DEBUG "%lu:%2x ", i, dev->r_buf[i]); | ||
292 | } | ||
293 | printk("\n"); | ||
294 | #else | ||
295 | } | ||
296 | #endif | ||
297 | |||
298 | *ppos = min_bytes_to_read; | ||
299 | if (copy_to_user(buf, dev->r_buf, min_bytes_to_read)) | ||
300 | return -EFAULT; | ||
301 | |||
302 | rc = wait_for_bulk_in_ready(dev); | ||
303 | if (rc <= 0) { | ||
304 | DEBUGP(5, dev, "wait_for_bulk_in_ready rc=%.2x\n", rc); | ||
305 | DEBUGP(2, dev, "<- cm4040_read (failed)\n"); | ||
306 | if (rc == -ERESTARTSYS) | ||
307 | return rc; | ||
308 | return -EIO; | ||
309 | } | ||
310 | |||
311 | rc = write_sync_reg(SCR_READER_TO_HOST_DONE, dev); | ||
312 | if (rc <= 0) { | ||
313 | DEBUGP(5, dev, "write_sync_reg c=%.2x\n", rc); | ||
314 | DEBUGP(2, dev, "<- cm4040_read (failed)\n"); | ||
315 | if (rc == -ERESTARTSYS) | ||
316 | return rc; | ||
317 | else | ||
318 | return -EIO; | ||
319 | } | ||
320 | |||
321 | uc = xinb(iobase + REG_OFFSET_BULK_IN); | ||
322 | |||
323 | DEBUGP(2, dev, "<- cm4040_read (successfully)\n"); | ||
324 | return min_bytes_to_read; | ||
325 | } | ||
326 | |||
327 | static ssize_t cm4040_write(struct file *filp, const char __user *buf, | ||
328 | size_t count, loff_t *ppos) | ||
329 | { | ||
330 | struct reader_dev *dev = filp->private_data; | ||
331 | int iobase = dev->link.io.BasePort1; | ||
332 | ssize_t rc; | ||
333 | int i; | ||
334 | unsigned int bytes_to_write; | ||
335 | |||
336 | DEBUGP(2, dev, "-> cm4040_write(%s,%d)\n", current->comm, current->pid); | ||
337 | |||
338 | if (count == 0) { | ||
339 | DEBUGP(2, dev, "<- cm4040_write empty read (successfully)\n"); | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | if (count < 5) { | ||
344 | DEBUGP(2, dev, "<- cm4040_write buffersize=%Zd < 5\n", count); | ||
345 | return -EIO; | ||
346 | } | ||
347 | |||
348 | if (filp->f_flags & O_NONBLOCK) { | ||
349 | DEBUGP(4, dev, "filep->f_flags O_NONBLOCK set\n"); | ||
350 | DEBUGP(4, dev, "<- cm4040_write (failure)\n"); | ||
351 | return -EAGAIN; | ||
352 | } | ||
353 | |||
354 | if ((dev->link.state & DEV_PRESENT) == 0) | ||
355 | return -ENODEV; | ||
356 | |||
357 | bytes_to_write = count; | ||
358 | if (copy_from_user(dev->s_buf, buf, bytes_to_write)) | ||
359 | return -EFAULT; | ||
360 | |||
361 | switch (dev->s_buf[0]) { | ||
362 | case CMD_PC_TO_RDR_XFRBLOCK: | ||
363 | case CMD_PC_TO_RDR_SECURE: | ||
364 | case CMD_PC_TO_RDR_TEST_SECURE: | ||
365 | case CMD_PC_TO_RDR_OK_SECURE: | ||
366 | dev->timeout = CCID_DRIVER_BULK_DEFAULT_TIMEOUT; | ||
367 | break; | ||
368 | |||
369 | case CMD_PC_TO_RDR_ICCPOWERON: | ||
370 | dev->timeout = CCID_DRIVER_ASYNC_POWERUP_TIMEOUT; | ||
371 | break; | ||
372 | |||
373 | case CMD_PC_TO_RDR_GETSLOTSTATUS: | ||
374 | case CMD_PC_TO_RDR_ICCPOWEROFF: | ||
375 | case CMD_PC_TO_RDR_GETPARAMETERS: | ||
376 | case CMD_PC_TO_RDR_RESETPARAMETERS: | ||
377 | case CMD_PC_TO_RDR_SETPARAMETERS: | ||
378 | case CMD_PC_TO_RDR_ESCAPE: | ||
379 | case CMD_PC_TO_RDR_ICCCLOCK: | ||
380 | default: | ||
381 | dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; | ||
382 | break; | ||
383 | } | ||
384 | |||
385 | rc = write_sync_reg(SCR_HOST_TO_READER_START, dev); | ||
386 | if (rc <= 0) { | ||
387 | DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc); | ||
388 | DEBUGP(2, dev, "<- cm4040_write (failed)\n"); | ||
389 | if (rc == -ERESTARTSYS) | ||
390 | return rc; | ||
391 | else | ||
392 | return -EIO; | ||
393 | } | ||
394 | |||
395 | DEBUGP(4, dev, "start \n"); | ||
396 | |||
397 | for (i = 0; i < bytes_to_write; i++) { | ||
398 | rc = wait_for_bulk_out_ready(dev); | ||
399 | if (rc <= 0) { | ||
400 | DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2Zx\n", | ||
401 | rc); | ||
402 | DEBUGP(2, dev, "<- cm4040_write (failed)\n"); | ||
403 | if (rc == -ERESTARTSYS) | ||
404 | return rc; | ||
405 | else | ||
406 | return -EIO; | ||
407 | } | ||
408 | |||
409 | xoutb(dev->s_buf[i],iobase + REG_OFFSET_BULK_OUT); | ||
410 | } | ||
411 | DEBUGP(4, dev, "end\n"); | ||
412 | |||
413 | rc = write_sync_reg(SCR_HOST_TO_READER_DONE, dev); | ||
414 | |||
415 | if (rc <= 0) { | ||
416 | DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc); | ||
417 | DEBUGP(2, dev, "<- cm4040_write (failed)\n"); | ||
418 | if (rc == -ERESTARTSYS) | ||
419 | return rc; | ||
420 | else | ||
421 | return -EIO; | ||
422 | } | ||
423 | |||
424 | DEBUGP(2, dev, "<- cm4040_write (successfully)\n"); | ||
425 | return count; | ||
426 | } | ||
427 | |||
428 | static unsigned int cm4040_poll(struct file *filp, poll_table *wait) | ||
429 | { | ||
430 | struct reader_dev *dev = filp->private_data; | ||
431 | unsigned int mask = 0; | ||
432 | |||
433 | poll_wait(filp, &dev->poll_wait, wait); | ||
434 | |||
435 | if (test_and_clear_bit(BS_READABLE, &dev->buffer_status)) | ||
436 | mask |= POLLIN | POLLRDNORM; | ||
437 | if (test_and_clear_bit(BS_WRITABLE, &dev->buffer_status)) | ||
438 | mask |= POLLOUT | POLLWRNORM; | ||
439 | |||
440 | DEBUGP(2, dev, "<- cm4040_poll(%u)\n", mask); | ||
441 | |||
442 | return mask; | ||
443 | } | ||
444 | |||
445 | static int cm4040_open(struct inode *inode, struct file *filp) | ||
446 | { | ||
447 | struct reader_dev *dev; | ||
448 | dev_link_t *link; | ||
449 | int minor = iminor(inode); | ||
450 | |||
451 | if (minor >= CM_MAX_DEV) | ||
452 | return -ENODEV; | ||
453 | |||
454 | link = dev_table[minor]; | ||
455 | if (link == NULL || !(DEV_OK(link))) | ||
456 | return -ENODEV; | ||
457 | |||
458 | if (link->open) | ||
459 | return -EBUSY; | ||
460 | |||
461 | dev = link->priv; | ||
462 | filp->private_data = dev; | ||
463 | |||
464 | if (filp->f_flags & O_NONBLOCK) { | ||
465 | DEBUGP(4, dev, "filep->f_flags O_NONBLOCK set\n"); | ||
466 | return -EAGAIN; | ||
467 | } | ||
468 | |||
469 | link->open = 1; | ||
470 | |||
471 | dev->poll_timer.data = (unsigned long) dev; | ||
472 | mod_timer(&dev->poll_timer, jiffies + POLL_PERIOD); | ||
473 | |||
474 | DEBUGP(2, dev, "<- cm4040_open (successfully)\n"); | ||
475 | return nonseekable_open(inode, filp); | ||
476 | } | ||
477 | |||
478 | static int cm4040_close(struct inode *inode, struct file *filp) | ||
479 | { | ||
480 | struct reader_dev *dev = filp->private_data; | ||
481 | dev_link_t *link; | ||
482 | int minor = iminor(inode); | ||
483 | |||
484 | DEBUGP(2, dev, "-> cm4040_close(maj/min=%d.%d)\n", imajor(inode), | ||
485 | iminor(inode)); | ||
486 | |||
487 | if (minor >= CM_MAX_DEV) | ||
488 | return -ENODEV; | ||
489 | |||
490 | link = dev_table[minor]; | ||
491 | if (link == NULL) | ||
492 | return -ENODEV; | ||
493 | |||
494 | cm4040_stop_poll(dev); | ||
495 | |||
496 | link->open = 0; | ||
497 | wake_up(&dev->devq); | ||
498 | |||
499 | DEBUGP(2, dev, "<- cm4040_close\n"); | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | static void cm4040_reader_release(dev_link_t *link) | ||
504 | { | ||
505 | struct reader_dev *dev = link->priv; | ||
506 | |||
507 | DEBUGP(3, dev, "-> cm4040_reader_release\n"); | ||
508 | while (link->open) { | ||
509 | DEBUGP(3, dev, KERN_INFO MODULE_NAME ": delaying release " | ||
510 | "until process has terminated\n"); | ||
511 | wait_event(dev->devq, (link->open == 0)); | ||
512 | } | ||
513 | DEBUGP(3, dev, "<- cm4040_reader_release\n"); | ||
514 | return; | ||
515 | } | ||
516 | |||
517 | static void reader_config(dev_link_t *link, int devno) | ||
518 | { | ||
519 | client_handle_t handle; | ||
520 | struct reader_dev *dev; | ||
521 | tuple_t tuple; | ||
522 | cisparse_t parse; | ||
523 | config_info_t conf; | ||
524 | u_char buf[64]; | ||
525 | int fail_fn, fail_rc; | ||
526 | int rc; | ||
527 | |||
528 | handle = link->handle; | ||
529 | |||
530 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
531 | tuple.Attributes = 0; | ||
532 | tuple.TupleData = buf; | ||
533 | tuple.TupleDataMax = sizeof(buf); | ||
534 | tuple.TupleOffset = 0; | ||
535 | |||
536 | if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) { | ||
537 | fail_fn = GetFirstTuple; | ||
538 | goto cs_failed; | ||
539 | } | ||
540 | if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) { | ||
541 | fail_fn = GetTupleData; | ||
542 | goto cs_failed; | ||
543 | } | ||
544 | if ((fail_rc = pcmcia_parse_tuple(handle, &tuple, &parse)) | ||
545 | != CS_SUCCESS) { | ||
546 | fail_fn = ParseTuple; | ||
547 | goto cs_failed; | ||
548 | } | ||
549 | if ((fail_rc = pcmcia_get_configuration_info(handle, &conf)) | ||
550 | != CS_SUCCESS) { | ||
551 | fail_fn = GetConfigurationInfo; | ||
552 | goto cs_failed; | ||
553 | } | ||
554 | |||
555 | link->state |= DEV_CONFIG; | ||
556 | link->conf.ConfigBase = parse.config.base; | ||
557 | link->conf.Present = parse.config.rmask[0]; | ||
558 | link->conf.Vcc = conf.Vcc; | ||
559 | |||
560 | link->io.BasePort2 = 0; | ||
561 | link->io.NumPorts2 = 0; | ||
562 | link->io.Attributes2 = 0; | ||
563 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
564 | for (rc = pcmcia_get_first_tuple(handle, &tuple); | ||
565 | rc == CS_SUCCESS; | ||
566 | rc = pcmcia_get_next_tuple(handle, &tuple)) { | ||
567 | rc = pcmcia_get_tuple_data(handle, &tuple); | ||
568 | if (rc != CS_SUCCESS) | ||
569 | continue; | ||
570 | rc = pcmcia_parse_tuple(handle, &tuple, &parse); | ||
571 | if (rc != CS_SUCCESS) | ||
572 | continue; | ||
573 | |||
574 | link->conf.ConfigIndex = parse.cftable_entry.index; | ||
575 | |||
576 | if (!parse.cftable_entry.io.nwin) | ||
577 | continue; | ||
578 | |||
579 | link->io.BasePort1 = parse.cftable_entry.io.win[0].base; | ||
580 | link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; | ||
581 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
582 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT)) | ||
583 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
584 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT)) | ||
585 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
586 | link->io.IOAddrLines = parse.cftable_entry.io.flags | ||
587 | & CISTPL_IO_LINES_MASK; | ||
588 | rc = pcmcia_request_io(handle, &link->io); | ||
589 | |||
590 | dev_printk(KERN_INFO, &handle_to_dev(handle), "foo"); | ||
591 | if (rc == CS_SUCCESS) | ||
592 | break; | ||
593 | else | ||
594 | dev_printk(KERN_INFO, &handle_to_dev(handle), | ||
595 | "pcmcia_request_io failed 0x%x\n", rc); | ||
596 | } | ||
597 | if (rc != CS_SUCCESS) | ||
598 | goto cs_release; | ||
599 | |||
600 | link->conf.IntType = 00000002; | ||
601 | |||
602 | if ((fail_rc = pcmcia_request_configuration(handle,&link->conf)) | ||
603 | !=CS_SUCCESS) { | ||
604 | fail_fn = RequestConfiguration; | ||
605 | dev_printk(KERN_INFO, &handle_to_dev(handle), | ||
606 | "pcmcia_request_configuration failed 0x%x\n", | ||
607 | fail_rc); | ||
608 | goto cs_release; | ||
609 | } | ||
610 | |||
611 | dev = link->priv; | ||
612 | sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); | ||
613 | dev->node.major = major; | ||
614 | dev->node.minor = devno; | ||
615 | dev->node.next = NULL; | ||
616 | link->dev = &dev->node; | ||
617 | link->state &= ~DEV_CONFIG_PENDING; | ||
618 | |||
619 | DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno, | ||
620 | link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1); | ||
621 | DEBUGP(2, dev, "<- reader_config (succ)\n"); | ||
622 | |||
623 | return; | ||
624 | |||
625 | cs_failed: | ||
626 | cs_error(handle, fail_fn, fail_rc); | ||
627 | cs_release: | ||
628 | reader_release(link); | ||
629 | link->state &= ~DEV_CONFIG_PENDING; | ||
630 | } | ||
631 | |||
632 | static int reader_event(event_t event, int priority, | ||
633 | event_callback_args_t *args) | ||
634 | { | ||
635 | dev_link_t *link; | ||
636 | struct reader_dev *dev; | ||
637 | int devno; | ||
638 | |||
639 | link = args->client_data; | ||
640 | dev = link->priv; | ||
641 | DEBUGP(3, dev, "-> reader_event\n"); | ||
642 | for (devno = 0; devno < CM_MAX_DEV; devno++) { | ||
643 | if (dev_table[devno] == link) | ||
644 | break; | ||
645 | } | ||
646 | if (devno == CM_MAX_DEV) | ||
647 | return CS_BAD_ADAPTER; | ||
648 | |||
649 | switch (event) { | ||
650 | case CS_EVENT_CARD_INSERTION: | ||
651 | DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n"); | ||
652 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
653 | reader_config(link, devno); | ||
654 | break; | ||
655 | case CS_EVENT_CARD_REMOVAL: | ||
656 | DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); | ||
657 | link->state &= ~DEV_PRESENT; | ||
658 | break; | ||
659 | case CS_EVENT_PM_SUSPEND: | ||
660 | DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " | ||
661 | "(fall-through to CS_EVENT_RESET_PHYSICAL)\n"); | ||
662 | link->state |= DEV_SUSPEND; | ||
663 | |||
664 | case CS_EVENT_RESET_PHYSICAL: | ||
665 | DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n"); | ||
666 | if (link->state & DEV_CONFIG) { | ||
667 | DEBUGP(5, dev, "ReleaseConfiguration\n"); | ||
668 | pcmcia_release_configuration(link->handle); | ||
669 | } | ||
670 | break; | ||
671 | case CS_EVENT_PM_RESUME: | ||
672 | DEBUGP(5, dev, "CS_EVENT_PM_RESUME " | ||
673 | "(fall-through to CS_EVENT_CARD_RESET)\n"); | ||
674 | link->state &= ~DEV_SUSPEND; | ||
675 | |||
676 | case CS_EVENT_CARD_RESET: | ||
677 | DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n"); | ||
678 | if ((link->state & DEV_CONFIG)) { | ||
679 | DEBUGP(5, dev, "RequestConfiguration\n"); | ||
680 | pcmcia_request_configuration(link->handle, | ||
681 | &link->conf); | ||
682 | } | ||
683 | break; | ||
684 | default: | ||
685 | DEBUGP(5, dev, "reader_event: unknown event %.2x\n", | ||
686 | event); | ||
687 | break; | ||
688 | } | ||
689 | DEBUGP(3, dev, "<- reader_event\n"); | ||
690 | return CS_SUCCESS; | ||
691 | } | ||
692 | |||
693 | static void reader_release(dev_link_t *link) | ||
694 | { | ||
695 | cm4040_reader_release(link->priv); | ||
696 | pcmcia_release_configuration(link->handle); | ||
697 | pcmcia_release_io(link->handle, &link->io); | ||
698 | } | ||
699 | |||
700 | static dev_link_t *reader_attach(void) | ||
701 | { | ||
702 | struct reader_dev *dev; | ||
703 | dev_link_t *link; | ||
704 | client_reg_t client_reg; | ||
705 | int i; | ||
706 | |||
707 | for (i = 0; i < CM_MAX_DEV; i++) { | ||
708 | if (dev_table[i] == NULL) | ||
709 | break; | ||
710 | } | ||
711 | |||
712 | if (i == CM_MAX_DEV) | ||
713 | return NULL; | ||
714 | |||
715 | dev = kzalloc(sizeof(struct reader_dev), GFP_KERNEL); | ||
716 | if (dev == NULL) | ||
717 | return NULL; | ||
718 | |||
719 | dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; | ||
720 | dev->buffer_status = 0; | ||
721 | |||
722 | link = &dev->link; | ||
723 | link->priv = dev; | ||
724 | |||
725 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
726 | dev_table[i] = link; | ||
727 | |||
728 | client_reg.dev_info = &dev_info; | ||
729 | client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; | ||
730 | client_reg.EventMask= | ||
731 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
732 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
733 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
734 | client_reg.Version = 0x0210; | ||
735 | client_reg.event_callback_args.client_data = link; | ||
736 | i = pcmcia_register_client(&link->handle, &client_reg); | ||
737 | if (i) { | ||
738 | cs_error(link->handle, RegisterClient, i); | ||
739 | reader_detach(link); | ||
740 | return NULL; | ||
741 | } | ||
742 | init_waitqueue_head(&dev->devq); | ||
743 | init_waitqueue_head(&dev->poll_wait); | ||
744 | init_waitqueue_head(&dev->read_wait); | ||
745 | init_waitqueue_head(&dev->write_wait); | ||
746 | init_timer(&dev->poll_timer); | ||
747 | dev->poll_timer.function = &cm4040_do_poll; | ||
748 | |||
749 | return link; | ||
750 | } | ||
751 | |||
752 | static void reader_detach_by_devno(int devno, dev_link_t *link) | ||
753 | { | ||
754 | struct reader_dev *dev = link->priv; | ||
755 | |||
756 | if (link->state & DEV_CONFIG) { | ||
757 | DEBUGP(5, dev, "device still configured (try to release it)\n"); | ||
758 | reader_release(link); | ||
759 | } | ||
760 | |||
761 | pcmcia_deregister_client(link->handle); | ||
762 | dev_table[devno] = NULL; | ||
763 | DEBUGP(5, dev, "freeing dev=%p\n", dev); | ||
764 | cm4040_stop_poll(dev); | ||
765 | kfree(dev); | ||
766 | return; | ||
767 | } | ||
768 | |||
769 | static void reader_detach(dev_link_t *link) | ||
770 | { | ||
771 | int i; | ||
772 | |||
773 | /* find device */ | ||
774 | for (i = 0; i < CM_MAX_DEV; i++) { | ||
775 | if (dev_table[i] == link) | ||
776 | break; | ||
777 | } | ||
778 | if (i == CM_MAX_DEV) | ||
779 | return; | ||
780 | |||
781 | reader_detach_by_devno(i, link); | ||
782 | return; | ||
783 | } | ||
784 | |||
785 | static struct file_operations reader_fops = { | ||
786 | .owner = THIS_MODULE, | ||
787 | .read = cm4040_read, | ||
788 | .write = cm4040_write, | ||
789 | .open = cm4040_open, | ||
790 | .release = cm4040_close, | ||
791 | .poll = cm4040_poll, | ||
792 | }; | ||
793 | |||
794 | static struct pcmcia_device_id cm4040_ids[] = { | ||
795 | PCMCIA_DEVICE_MANF_CARD(0x0223, 0x0200), | ||
796 | PCMCIA_DEVICE_PROD_ID12("OMNIKEY", "CardMan 4040", | ||
797 | 0xE32CDD8C, 0x8F23318B), | ||
798 | PCMCIA_DEVICE_NULL, | ||
799 | }; | ||
800 | MODULE_DEVICE_TABLE(pcmcia, cm4040_ids); | ||
801 | |||
802 | static struct pcmcia_driver reader_driver = { | ||
803 | .owner = THIS_MODULE, | ||
804 | .drv = { | ||
805 | .name = "cm4040_cs", | ||
806 | }, | ||
807 | .attach = reader_attach, | ||
808 | .detach = reader_detach, | ||
809 | .event = reader_event, | ||
810 | .id_table = cm4040_ids, | ||
811 | }; | ||
812 | |||
813 | static int __init cm4040_init(void) | ||
814 | { | ||
815 | printk(KERN_INFO "%s\n", version); | ||
816 | pcmcia_register_driver(&reader_driver); | ||
817 | major = register_chrdev(0, DEVICE_NAME, &reader_fops); | ||
818 | if (major < 0) { | ||
819 | printk(KERN_WARNING MODULE_NAME | ||
820 | ": could not get major number\n"); | ||
821 | return -1; | ||
822 | } | ||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | static void __exit cm4040_exit(void) | ||
827 | { | ||
828 | int i; | ||
829 | |||
830 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | ||
831 | pcmcia_unregister_driver(&reader_driver); | ||
832 | for (i = 0; i < CM_MAX_DEV; i++) { | ||
833 | if (dev_table[i]) | ||
834 | reader_detach_by_devno(i, dev_table[i]); | ||
835 | } | ||
836 | unregister_chrdev(major, DEVICE_NAME); | ||
837 | } | ||
838 | |||
839 | module_init(cm4040_init); | ||
840 | module_exit(cm4040_exit); | ||
841 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/drivers/char/pcmcia/cm4040_cs.h b/drivers/char/pcmcia/cm4040_cs.h new file mode 100644 index 000000000000..9a8b805c5095 --- /dev/null +++ b/drivers/char/pcmcia/cm4040_cs.h | |||
@@ -0,0 +1,47 @@ | |||
1 | #ifndef _CM4040_H_ | ||
2 | #define _CM4040_H_ | ||
3 | |||
4 | #define CM_MAX_DEV 4 | ||
5 | |||
6 | #define DEVICE_NAME "cmx" | ||
7 | #define MODULE_NAME "cm4040_cs" | ||
8 | |||
9 | #define REG_OFFSET_BULK_OUT 0 | ||
10 | #define REG_OFFSET_BULK_IN 0 | ||
11 | #define REG_OFFSET_BUFFER_STATUS 1 | ||
12 | #define REG_OFFSET_SYNC_CONTROL 2 | ||
13 | |||
14 | #define BSR_BULK_IN_FULL 0x02 | ||
15 | #define BSR_BULK_OUT_FULL 0x01 | ||
16 | |||
17 | #define SCR_HOST_TO_READER_START 0x80 | ||
18 | #define SCR_ABORT 0x40 | ||
19 | #define SCR_EN_NOTIFY 0x20 | ||
20 | #define SCR_ACK_NOTIFY 0x10 | ||
21 | #define SCR_READER_TO_HOST_DONE 0x08 | ||
22 | #define SCR_HOST_TO_READER_DONE 0x04 | ||
23 | #define SCR_PULSE_INTERRUPT 0x02 | ||
24 | #define SCR_POWER_DOWN 0x01 | ||
25 | |||
26 | |||
27 | #define CMD_PC_TO_RDR_ICCPOWERON 0x62 | ||
28 | #define CMD_PC_TO_RDR_GETSLOTSTATUS 0x65 | ||
29 | #define CMD_PC_TO_RDR_ICCPOWEROFF 0x63 | ||
30 | #define CMD_PC_TO_RDR_SECURE 0x69 | ||
31 | #define CMD_PC_TO_RDR_GETPARAMETERS 0x6C | ||
32 | #define CMD_PC_TO_RDR_RESETPARAMETERS 0x6D | ||
33 | #define CMD_PC_TO_RDR_SETPARAMETERS 0x61 | ||
34 | #define CMD_PC_TO_RDR_XFRBLOCK 0x6F | ||
35 | #define CMD_PC_TO_RDR_ESCAPE 0x6B | ||
36 | #define CMD_PC_TO_RDR_ICCCLOCK 0x6E | ||
37 | #define CMD_PC_TO_RDR_TEST_SECURE 0x74 | ||
38 | #define CMD_PC_TO_RDR_OK_SECURE 0x89 | ||
39 | |||
40 | |||
41 | #define CMD_RDR_TO_PC_SLOTSTATUS 0x81 | ||
42 | #define CMD_RDR_TO_PC_DATABLOCK 0x80 | ||
43 | #define CMD_RDR_TO_PC_PARAMETERS 0x82 | ||
44 | #define CMD_RDR_TO_PC_ESCAPE 0x83 | ||
45 | #define CMD_RDR_TO_PC_OK_SECURE 0x89 | ||
46 | |||
47 | #endif /* _CM4040_H_ */ | ||
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 82c6abde68df..62aa0e534a6d 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/synclink.c | 2 | * linux/drivers/char/synclink.c |
3 | * | 3 | * |
4 | * $Id: synclink.c,v 4.37 2005/09/07 13:13:19 paulkf Exp $ | 4 | * $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $ |
5 | * | 5 | * |
6 | * Device driver for Microgate SyncLink ISA and PCI | 6 | * Device driver for Microgate SyncLink ISA and PCI |
7 | * high speed multiprotocol serial adapters. | 7 | * high speed multiprotocol serial adapters. |
@@ -101,6 +101,7 @@ | |||
101 | #include <linux/termios.h> | 101 | #include <linux/termios.h> |
102 | #include <linux/workqueue.h> | 102 | #include <linux/workqueue.h> |
103 | #include <linux/hdlc.h> | 103 | #include <linux/hdlc.h> |
104 | #include <linux/dma-mapping.h> | ||
104 | 105 | ||
105 | #ifdef CONFIG_HDLC_MODULE | 106 | #ifdef CONFIG_HDLC_MODULE |
106 | #define CONFIG_HDLC 1 | 107 | #define CONFIG_HDLC 1 |
@@ -148,6 +149,7 @@ typedef struct _DMABUFFERENTRY | |||
148 | u32 link; /* 32-bit flat link to next buffer entry */ | 149 | u32 link; /* 32-bit flat link to next buffer entry */ |
149 | char *virt_addr; /* virtual address of data buffer */ | 150 | char *virt_addr; /* virtual address of data buffer */ |
150 | u32 phys_entry; /* physical address of this buffer entry */ | 151 | u32 phys_entry; /* physical address of this buffer entry */ |
152 | dma_addr_t dma_addr; | ||
151 | } DMABUFFERENTRY, *DMAPBUFFERENTRY; | 153 | } DMABUFFERENTRY, *DMAPBUFFERENTRY; |
152 | 154 | ||
153 | /* The queue of BH actions to be performed */ | 155 | /* The queue of BH actions to be performed */ |
@@ -233,7 +235,8 @@ struct mgsl_struct { | |||
233 | int ri_chkcount; | 235 | int ri_chkcount; |
234 | 236 | ||
235 | char *buffer_list; /* virtual address of Rx & Tx buffer lists */ | 237 | char *buffer_list; /* virtual address of Rx & Tx buffer lists */ |
236 | unsigned long buffer_list_phys; | 238 | u32 buffer_list_phys; |
239 | dma_addr_t buffer_list_dma_addr; | ||
237 | 240 | ||
238 | unsigned int rx_buffer_count; /* count of total allocated Rx buffers */ | 241 | unsigned int rx_buffer_count; /* count of total allocated Rx buffers */ |
239 | DMABUFFERENTRY *rx_buffer_list; /* list of receive buffer entries */ | 242 | DMABUFFERENTRY *rx_buffer_list; /* list of receive buffer entries */ |
@@ -896,7 +899,7 @@ module_param_array(txdmabufs, int, NULL, 0); | |||
896 | module_param_array(txholdbufs, int, NULL, 0); | 899 | module_param_array(txholdbufs, int, NULL, 0); |
897 | 900 | ||
898 | static char *driver_name = "SyncLink serial driver"; | 901 | static char *driver_name = "SyncLink serial driver"; |
899 | static char *driver_version = "$Revision: 4.37 $"; | 902 | static char *driver_version = "$Revision: 4.38 $"; |
900 | 903 | ||
901 | static int synclink_init_one (struct pci_dev *dev, | 904 | static int synclink_init_one (struct pci_dev *dev, |
902 | const struct pci_device_id *ent); | 905 | const struct pci_device_id *ent); |
@@ -3811,11 +3814,10 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) | |||
3811 | /* inspect portions of the buffer while other portions are being */ | 3814 | /* inspect portions of the buffer while other portions are being */ |
3812 | /* updated by the adapter using Bus Master DMA. */ | 3815 | /* updated by the adapter using Bus Master DMA. */ |
3813 | 3816 | ||
3814 | info->buffer_list = kmalloc(BUFFERLISTSIZE, GFP_KERNEL | GFP_DMA); | 3817 | info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL); |
3815 | if ( info->buffer_list == NULL ) | 3818 | if (info->buffer_list == NULL) |
3816 | return -ENOMEM; | 3819 | return -ENOMEM; |
3817 | 3820 | info->buffer_list_phys = (u32)(info->buffer_list_dma_addr); | |
3818 | info->buffer_list_phys = isa_virt_to_bus(info->buffer_list); | ||
3819 | } | 3821 | } |
3820 | 3822 | ||
3821 | /* We got the memory for the buffer entry lists. */ | 3823 | /* We got the memory for the buffer entry lists. */ |
@@ -3882,8 +3884,8 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) | |||
3882 | */ | 3884 | */ |
3883 | static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) | 3885 | static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) |
3884 | { | 3886 | { |
3885 | if ( info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI ) | 3887 | if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI) |
3886 | kfree(info->buffer_list); | 3888 | dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr); |
3887 | 3889 | ||
3888 | info->buffer_list = NULL; | 3890 | info->buffer_list = NULL; |
3889 | info->rx_buffer_list = NULL; | 3891 | info->rx_buffer_list = NULL; |
@@ -3910,7 +3912,7 @@ static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) | |||
3910 | static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount) | 3912 | static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount) |
3911 | { | 3913 | { |
3912 | int i; | 3914 | int i; |
3913 | unsigned long phys_addr; | 3915 | u32 phys_addr; |
3914 | 3916 | ||
3915 | /* Allocate page sized buffers for the receive buffer list */ | 3917 | /* Allocate page sized buffers for the receive buffer list */ |
3916 | 3918 | ||
@@ -3922,11 +3924,10 @@ static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *Buff | |||
3922 | info->last_mem_alloc += DMABUFFERSIZE; | 3924 | info->last_mem_alloc += DMABUFFERSIZE; |
3923 | } else { | 3925 | } else { |
3924 | /* ISA adapter uses system memory. */ | 3926 | /* ISA adapter uses system memory. */ |
3925 | BufferList[i].virt_addr = | 3927 | BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL); |
3926 | kmalloc(DMABUFFERSIZE, GFP_KERNEL | GFP_DMA); | 3928 | if (BufferList[i].virt_addr == NULL) |
3927 | if ( BufferList[i].virt_addr == NULL ) | ||
3928 | return -ENOMEM; | 3929 | return -ENOMEM; |
3929 | phys_addr = isa_virt_to_bus(BufferList[i].virt_addr); | 3930 | phys_addr = (u32)(BufferList[i].dma_addr); |
3930 | } | 3931 | } |
3931 | BufferList[i].phys_addr = phys_addr; | 3932 | BufferList[i].phys_addr = phys_addr; |
3932 | } | 3933 | } |
@@ -3957,7 +3958,7 @@ static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *Buf | |||
3957 | for ( i = 0 ; i < Buffercount ; i++ ) { | 3958 | for ( i = 0 ; i < Buffercount ; i++ ) { |
3958 | if ( BufferList[i].virt_addr ) { | 3959 | if ( BufferList[i].virt_addr ) { |
3959 | if ( info->bus_type != MGSL_BUS_TYPE_PCI ) | 3960 | if ( info->bus_type != MGSL_BUS_TYPE_PCI ) |
3960 | kfree(BufferList[i].virt_addr); | 3961 | dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr); |
3961 | BufferList[i].virt_addr = NULL; | 3962 | BufferList[i].virt_addr = NULL; |
3962 | } | 3963 | } |
3963 | } | 3964 | } |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 303f15880466..0b283d246730 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -43,6 +43,13 @@ static void user_reader_timeout(unsigned long ptr) | |||
43 | { | 43 | { |
44 | struct tpm_chip *chip = (struct tpm_chip *) ptr; | 44 | struct tpm_chip *chip = (struct tpm_chip *) ptr; |
45 | 45 | ||
46 | schedule_work(&chip->work); | ||
47 | } | ||
48 | |||
49 | static void timeout_work(void * ptr) | ||
50 | { | ||
51 | struct tpm_chip *chip = ptr; | ||
52 | |||
46 | down(&chip->buffer_mutex); | 53 | down(&chip->buffer_mutex); |
47 | atomic_set(&chip->data_pending, 0); | 54 | atomic_set(&chip->data_pending, 0); |
48 | memset(chip->data_buffer, 0, TPM_BUFSIZE); | 55 | memset(chip->data_buffer, 0, TPM_BUFSIZE); |
@@ -428,8 +435,7 @@ ssize_t tpm_read(struct file * file, char __user *buf, | |||
428 | ret_size = size; | 435 | ret_size = size; |
429 | 436 | ||
430 | down(&chip->buffer_mutex); | 437 | down(&chip->buffer_mutex); |
431 | if (copy_to_user | 438 | if (copy_to_user(buf, chip->data_buffer, ret_size)) |
432 | ((void __user *) buf, chip->data_buffer, ret_size)) | ||
433 | ret_size = -EFAULT; | 439 | ret_size = -EFAULT; |
434 | up(&chip->buffer_mutex); | 440 | up(&chip->buffer_mutex); |
435 | } | 441 | } |
@@ -460,7 +466,7 @@ void tpm_remove_hardware(struct device *dev) | |||
460 | sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); | 466 | sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); |
461 | 467 | ||
462 | dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= | 468 | dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= |
463 | !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); | 469 | ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); |
464 | 470 | ||
465 | kfree(chip); | 471 | kfree(chip); |
466 | 472 | ||
@@ -528,6 +534,8 @@ int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry) | |||
528 | init_MUTEX(&chip->tpm_mutex); | 534 | init_MUTEX(&chip->tpm_mutex); |
529 | INIT_LIST_HEAD(&chip->list); | 535 | INIT_LIST_HEAD(&chip->list); |
530 | 536 | ||
537 | INIT_WORK(&chip->work, timeout_work, chip); | ||
538 | |||
531 | init_timer(&chip->user_read_timer); | 539 | init_timer(&chip->user_read_timer); |
532 | chip->user_read_timer.function = user_reader_timeout; | 540 | chip->user_read_timer.function = user_reader_timeout; |
533 | chip->user_read_timer.data = (unsigned long) chip; | 541 | chip->user_read_timer.data = (unsigned long) chip; |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 9293bcc4dc62..159882ca69dd 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -50,7 +50,11 @@ struct tpm_vendor_specific { | |||
50 | u8 req_complete_mask; | 50 | u8 req_complete_mask; |
51 | u8 req_complete_val; | 51 | u8 req_complete_val; |
52 | u8 req_canceled; | 52 | u8 req_canceled; |
53 | u16 base; /* TPM base address */ | 53 | void __iomem *iobase; /* ioremapped address */ |
54 | unsigned long base; /* TPM base address */ | ||
55 | |||
56 | int region_size; | ||
57 | int have_region; | ||
54 | 58 | ||
55 | int (*recv) (struct tpm_chip *, u8 *, size_t); | 59 | int (*recv) (struct tpm_chip *, u8 *, size_t); |
56 | int (*send) (struct tpm_chip *, u8 *, size_t); | 60 | int (*send) (struct tpm_chip *, u8 *, size_t); |
@@ -73,6 +77,7 @@ struct tpm_chip { | |||
73 | struct semaphore buffer_mutex; | 77 | struct semaphore buffer_mutex; |
74 | 78 | ||
75 | struct timer_list user_read_timer; /* user needs to claim result */ | 79 | struct timer_list user_read_timer; /* user needs to claim result */ |
80 | struct work_struct work; | ||
76 | struct semaphore tpm_mutex; /* tpm is processing */ | 81 | struct semaphore tpm_mutex; /* tpm is processing */ |
77 | 82 | ||
78 | struct tpm_vendor_specific *vendor; | 83 | struct tpm_vendor_specific *vendor; |
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index 32e01450c425..deb4b5c80914 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -19,14 +19,8 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/platform_device.h> | ||
23 | #include "tpm.h" | 22 | #include "tpm.h" |
24 | 23 | #include "tpm_atmel.h" | |
25 | /* Atmel definitions */ | ||
26 | enum tpm_atmel_addr { | ||
27 | TPM_ATMEL_BASE_ADDR_LO = 0x08, | ||
28 | TPM_ATMEL_BASE_ADDR_HI = 0x09 | ||
29 | }; | ||
30 | 24 | ||
31 | /* write status bits */ | 25 | /* write status bits */ |
32 | enum tpm_atmel_write_status { | 26 | enum tpm_atmel_write_status { |
@@ -53,13 +47,13 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
53 | return -EIO; | 47 | return -EIO; |
54 | 48 | ||
55 | for (i = 0; i < 6; i++) { | 49 | for (i = 0; i < 6; i++) { |
56 | status = inb(chip->vendor->base + 1); | 50 | status = atmel_getb(chip, 1); |
57 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 51 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
58 | dev_err(chip->dev, | 52 | dev_err(chip->dev, |
59 | "error reading header\n"); | 53 | "error reading header\n"); |
60 | return -EIO; | 54 | return -EIO; |
61 | } | 55 | } |
62 | *buf++ = inb(chip->vendor->base); | 56 | *buf++ = atmel_getb(chip, 0); |
63 | } | 57 | } |
64 | 58 | ||
65 | /* size of the data received */ | 59 | /* size of the data received */ |
@@ -70,7 +64,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
70 | dev_err(chip->dev, | 64 | dev_err(chip->dev, |
71 | "Recv size(%d) less than available space\n", size); | 65 | "Recv size(%d) less than available space\n", size); |
72 | for (; i < size; i++) { /* clear the waiting data anyway */ | 66 | for (; i < size; i++) { /* clear the waiting data anyway */ |
73 | status = inb(chip->vendor->base + 1); | 67 | status = atmel_getb(chip, 1); |
74 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 68 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
75 | dev_err(chip->dev, | 69 | dev_err(chip->dev, |
76 | "error reading data\n"); | 70 | "error reading data\n"); |
@@ -82,17 +76,17 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
82 | 76 | ||
83 | /* read all the data available */ | 77 | /* read all the data available */ |
84 | for (; i < size; i++) { | 78 | for (; i < size; i++) { |
85 | status = inb(chip->vendor->base + 1); | 79 | status = atmel_getb(chip, 1); |
86 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 80 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
87 | dev_err(chip->dev, | 81 | dev_err(chip->dev, |
88 | "error reading data\n"); | 82 | "error reading data\n"); |
89 | return -EIO; | 83 | return -EIO; |
90 | } | 84 | } |
91 | *buf++ = inb(chip->vendor->base); | 85 | *buf++ = atmel_getb(chip, 0); |
92 | } | 86 | } |
93 | 87 | ||
94 | /* make sure data available is gone */ | 88 | /* make sure data available is gone */ |
95 | status = inb(chip->vendor->base + 1); | 89 | status = atmel_getb(chip, 1); |
96 | if (status & ATML_STATUS_DATA_AVAIL) { | 90 | if (status & ATML_STATUS_DATA_AVAIL) { |
97 | dev_err(chip->dev, "data available is stuck\n"); | 91 | dev_err(chip->dev, "data available is stuck\n"); |
98 | return -EIO; | 92 | return -EIO; |
@@ -108,7 +102,7 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
108 | dev_dbg(chip->dev, "tpm_atml_send:\n"); | 102 | dev_dbg(chip->dev, "tpm_atml_send:\n"); |
109 | for (i = 0; i < count; i++) { | 103 | for (i = 0; i < count; i++) { |
110 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); | 104 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); |
111 | outb(buf[i], chip->vendor->base); | 105 | atmel_putb(buf[i], chip, 0); |
112 | } | 106 | } |
113 | 107 | ||
114 | return count; | 108 | return count; |
@@ -116,12 +110,12 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
116 | 110 | ||
117 | static void tpm_atml_cancel(struct tpm_chip *chip) | 111 | static void tpm_atml_cancel(struct tpm_chip *chip) |
118 | { | 112 | { |
119 | outb(ATML_STATUS_ABORT, chip->vendor->base + 1); | 113 | atmel_putb(ATML_STATUS_ABORT, chip, 1); |
120 | } | 114 | } |
121 | 115 | ||
122 | static u8 tpm_atml_status(struct tpm_chip *chip) | 116 | static u8 tpm_atml_status(struct tpm_chip *chip) |
123 | { | 117 | { |
124 | return inb(chip->vendor->base + 1); | 118 | return atmel_getb(chip, 1); |
125 | } | 119 | } |
126 | 120 | ||
127 | static struct file_operations atmel_ops = { | 121 | static struct file_operations atmel_ops = { |
@@ -162,12 +156,16 @@ static struct tpm_vendor_specific tpm_atmel = { | |||
162 | 156 | ||
163 | static struct platform_device *pdev; | 157 | static struct platform_device *pdev; |
164 | 158 | ||
165 | static void __devexit tpm_atml_remove(struct device *dev) | 159 | static void atml_plat_remove(void) |
166 | { | 160 | { |
167 | struct tpm_chip *chip = dev_get_drvdata(dev); | 161 | struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); |
162 | |||
168 | if (chip) { | 163 | if (chip) { |
169 | release_region(chip->vendor->base, 2); | 164 | if (chip->vendor->have_region) |
165 | atmel_release_region(chip->vendor->base, chip->vendor->region_size); | ||
166 | atmel_put_base_addr(chip->vendor); | ||
170 | tpm_remove_hardware(chip->dev); | 167 | tpm_remove_hardware(chip->dev); |
168 | platform_device_unregister(pdev); | ||
171 | } | 169 | } |
172 | } | 170 | } |
173 | 171 | ||
@@ -182,72 +180,40 @@ static struct device_driver atml_drv = { | |||
182 | static int __init init_atmel(void) | 180 | static int __init init_atmel(void) |
183 | { | 181 | { |
184 | int rc = 0; | 182 | int rc = 0; |
185 | int lo, hi; | ||
186 | 183 | ||
187 | driver_register(&atml_drv); | 184 | driver_register(&atml_drv); |
188 | 185 | ||
189 | lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); | 186 | if (atmel_get_base_addr(&tpm_atmel) != 0) { |
190 | hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); | 187 | rc = -ENODEV; |
191 | 188 | goto err_unreg_drv; | |
192 | tpm_atmel.base = (hi<<8)|lo; | ||
193 | |||
194 | /* verify that it is an Atmel part */ | ||
195 | if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T' | ||
196 | || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') { | ||
197 | return -ENODEV; | ||
198 | } | ||
199 | |||
200 | /* verify chip version number is 1.1 */ | ||
201 | if ( (tpm_read_index(TPM_ADDR, 0x00) != 0x01) || | ||
202 | (tpm_read_index(TPM_ADDR, 0x01) != 0x01 )) | ||
203 | return -ENODEV; | ||
204 | |||
205 | pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL); | ||
206 | if ( !pdev ) | ||
207 | return -ENOMEM; | ||
208 | |||
209 | pdev->name = "tpm_atmel0"; | ||
210 | pdev->id = -1; | ||
211 | pdev->num_resources = 0; | ||
212 | pdev->dev.release = tpm_atml_remove; | ||
213 | pdev->dev.driver = &atml_drv; | ||
214 | |||
215 | if ((rc = platform_device_register(pdev)) < 0) { | ||
216 | kfree(pdev); | ||
217 | pdev = NULL; | ||
218 | return rc; | ||
219 | } | 189 | } |
220 | 190 | ||
221 | if (request_region(tpm_atmel.base, 2, "tpm_atmel0") == NULL ) { | 191 | tpm_atmel.have_region = (atmel_request_region( tpm_atmel.base, tpm_atmel.region_size, "tpm_atmel0") == NULL) ? 0 : 1; |
222 | platform_device_unregister(pdev); | ||
223 | kfree(pdev); | ||
224 | pdev = NULL; | ||
225 | return -EBUSY; | ||
226 | } | ||
227 | 192 | ||
228 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) { | 193 | if (IS_ERR(pdev = platform_device_register_simple("tpm_atmel", -1, NULL, 0 ))) { |
229 | release_region(tpm_atmel.base, 2); | 194 | rc = PTR_ERR(pdev); |
230 | platform_device_unregister(pdev); | 195 | goto err_rel_reg; |
231 | kfree(pdev); | ||
232 | pdev = NULL; | ||
233 | return rc; | ||
234 | } | 196 | } |
235 | 197 | ||
236 | dev_info(&pdev->dev, "Atmel TPM 1.1, Base Address: 0x%x\n", | 198 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) |
237 | tpm_atmel.base); | 199 | goto err_unreg_dev; |
238 | return 0; | 200 | return 0; |
201 | |||
202 | err_unreg_dev: | ||
203 | platform_device_unregister(pdev); | ||
204 | err_rel_reg: | ||
205 | if (tpm_atmel.have_region) | ||
206 | atmel_release_region(tpm_atmel.base, tpm_atmel.region_size); | ||
207 | atmel_put_base_addr(&tpm_atmel); | ||
208 | err_unreg_drv: | ||
209 | driver_unregister(&atml_drv); | ||
210 | return rc; | ||
239 | } | 211 | } |
240 | 212 | ||
241 | static void __exit cleanup_atmel(void) | 213 | static void __exit cleanup_atmel(void) |
242 | { | 214 | { |
243 | if (pdev) { | ||
244 | tpm_atml_remove(&pdev->dev); | ||
245 | platform_device_unregister(pdev); | ||
246 | kfree(pdev); | ||
247 | pdev = NULL; | ||
248 | } | ||
249 | |||
250 | driver_unregister(&atml_drv); | 215 | driver_unregister(&atml_drv); |
216 | atml_plat_remove(); | ||
251 | } | 217 | } |
252 | 218 | ||
253 | module_init(init_atmel); | 219 | module_init(init_atmel); |
diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h new file mode 100644 index 000000000000..3c5b9a8d1c49 --- /dev/null +++ b/drivers/char/tpm/tpm_atmel.h | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 IBM Corporation | ||
3 | * | ||
4 | * Authors: | ||
5 | * Kylene Hall <kjhall@us.ibm.com> | ||
6 | * | ||
7 | * Maintained by: <tpmdd_devel@lists.sourceforge.net> | ||
8 | * | ||
9 | * Device driver for TCG/TCPA TPM (trusted platform module). | ||
10 | * Specifications at www.trustedcomputinggroup.org | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License as | ||
14 | * published by the Free Software Foundation, version 2 of the | ||
15 | * License. | ||
16 | * | ||
17 | * These difference are required on power because the device must be | ||
18 | * discovered through the device tree and iomap must be used to get | ||
19 | * around the need for holes in the io_page_mask. This does not happen | ||
20 | * automatically because the tpm is not a normal pci device and lives | ||
21 | * under the root node. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifdef CONFIG_PPC64 | ||
26 | #define atmel_getb(chip, offset) readb(chip->vendor->iobase + offset); | ||
27 | #define atmel_putb(val, chip, offset) writeb(val, chip->vendor->iobase + offset) | ||
28 | #define atmel_request_region request_mem_region | ||
29 | #define atmel_release_region release_mem_region | ||
30 | static inline void atmel_put_base_addr(struct tpm_vendor_specific *vendor) | ||
31 | { | ||
32 | iounmap(vendor->iobase); | ||
33 | } | ||
34 | |||
35 | static int atmel_get_base_addr(struct tpm_vendor_specific *vendor) | ||
36 | { | ||
37 | struct device_node *dn; | ||
38 | unsigned long address, size; | ||
39 | unsigned int *reg; | ||
40 | int reglen; | ||
41 | int naddrc; | ||
42 | int nsizec; | ||
43 | |||
44 | dn = of_find_node_by_name(NULL, "tpm"); | ||
45 | |||
46 | if (!dn) | ||
47 | return 1; | ||
48 | |||
49 | if (!device_is_compatible(dn, "AT97SC3201")) { | ||
50 | of_node_put(dn); | ||
51 | return 1; | ||
52 | } | ||
53 | |||
54 | reg = (unsigned int *) get_property(dn, "reg", ®len); | ||
55 | naddrc = prom_n_addr_cells(dn); | ||
56 | nsizec = prom_n_size_cells(dn); | ||
57 | |||
58 | of_node_put(dn); | ||
59 | |||
60 | |||
61 | if (naddrc == 2) | ||
62 | address = ((unsigned long) reg[0] << 32) | reg[1]; | ||
63 | else | ||
64 | address = reg[0]; | ||
65 | |||
66 | if (nsizec == 2) | ||
67 | size = | ||
68 | ((unsigned long) reg[naddrc] << 32) | reg[naddrc + 1]; | ||
69 | else | ||
70 | size = reg[naddrc]; | ||
71 | |||
72 | vendor->base = address; | ||
73 | vendor->region_size = size; | ||
74 | vendor->iobase = ioremap(address, size); | ||
75 | return 0; | ||
76 | } | ||
77 | #else | ||
78 | #define atmel_getb(chip, offset) inb(chip->vendor->base + offset) | ||
79 | #define atmel_putb(val, chip, offset) outb(val, chip->vendor->base + offset) | ||
80 | #define atmel_request_region request_region | ||
81 | #define atmel_release_region release_region | ||
82 | /* Atmel definitions */ | ||
83 | enum tpm_atmel_addr { | ||
84 | TPM_ATMEL_BASE_ADDR_LO = 0x08, | ||
85 | TPM_ATMEL_BASE_ADDR_HI = 0x09 | ||
86 | }; | ||
87 | |||
88 | /* Verify this is a 1.1 Atmel TPM */ | ||
89 | static int atmel_verify_tpm11(void) | ||
90 | { | ||
91 | |||
92 | /* verify that it is an Atmel part */ | ||
93 | if (tpm_read_index(TPM_ADDR, 4) != 'A' || | ||
94 | tpm_read_index(TPM_ADDR, 5) != 'T' || | ||
95 | tpm_read_index(TPM_ADDR, 6) != 'M' || | ||
96 | tpm_read_index(TPM_ADDR, 7) != 'L') | ||
97 | return 1; | ||
98 | |||
99 | /* query chip for its version number */ | ||
100 | if (tpm_read_index(TPM_ADDR, 0x00) != 1 || | ||
101 | tpm_read_index(TPM_ADDR, 0x01) != 1) | ||
102 | return 1; | ||
103 | |||
104 | /* This is an atmel supported part */ | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static inline void atmel_put_base_addr(struct tpm_vendor_specific *vendor) | ||
109 | { | ||
110 | } | ||
111 | |||
112 | /* Determine where to talk to device */ | ||
113 | static unsigned long atmel_get_base_addr(struct tpm_vendor_specific | ||
114 | *vendor) | ||
115 | { | ||
116 | int lo, hi; | ||
117 | |||
118 | if (atmel_verify_tpm11() != 0) | ||
119 | return 1; | ||
120 | |||
121 | lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); | ||
122 | hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); | ||
123 | |||
124 | vendor->base = (hi << 8) | lo; | ||
125 | vendor->region_size = 2; | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | #endif | ||
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c index abc30cca6645..65830ec71042 100644 --- a/drivers/char/watchdog/booke_wdt.c +++ b/drivers/char/watchdog/booke_wdt.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Watchdog timer for PowerPC Book-E systems | 4 | * Watchdog timer for PowerPC Book-E systems |
5 | * | 5 | * |
6 | * Author: Matthew McClintock | 6 | * Author: Matthew McClintock |
7 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 7 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
8 | * | 8 | * |
9 | * Copyright 2005 Freescale Semiconductor Inc. | 9 | * Copyright 2005 Freescale Semiconductor Inc. |
10 | * | 10 | * |
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index ea0806c82be0..8a5c7b286b2b 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c | |||
@@ -399,34 +399,6 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c | |||
399 | return dev->irq; | 399 | return dev->irq; |
400 | } | 400 | } |
401 | 401 | ||
402 | static void __devinit init_dma_sl82c105(ide_hwif_t *hwif, unsigned long dma_base) | ||
403 | { | ||
404 | unsigned int rev; | ||
405 | u8 dma_state; | ||
406 | |||
407 | DBG(("init_dma_sl82c105(hwif: ide%d, dma_base: 0x%08x)\n", hwif->index, dma_base)); | ||
408 | |||
409 | hwif->autodma = 0; | ||
410 | |||
411 | if (!dma_base) | ||
412 | return; | ||
413 | |||
414 | dma_state = hwif->INB(dma_base + 2); | ||
415 | rev = sl82c105_bridge_revision(hwif->pci_dev); | ||
416 | if (rev <= 5) { | ||
417 | printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", | ||
418 | hwif->name, rev); | ||
419 | dma_state &= ~0x60; | ||
420 | } else { | ||
421 | dma_state |= 0x60; | ||
422 | if (!noautodma) | ||
423 | hwif->autodma = 1; | ||
424 | } | ||
425 | hwif->OUTB(dma_state, dma_base + 2); | ||
426 | |||
427 | ide_setup_dma(hwif, dma_base, 8); | ||
428 | } | ||
429 | |||
430 | /* | 402 | /* |
431 | * Initialise the chip | 403 | * Initialise the chip |
432 | */ | 404 | */ |
@@ -434,6 +406,8 @@ static void __devinit init_dma_sl82c105(ide_hwif_t *hwif, unsigned long dma_base | |||
434 | static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) | 406 | static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) |
435 | { | 407 | { |
436 | struct pci_dev *dev = hwif->pci_dev; | 408 | struct pci_dev *dev = hwif->pci_dev; |
409 | unsigned int rev; | ||
410 | u8 dma_state; | ||
437 | u32 val; | 411 | u32 val; |
438 | 412 | ||
439 | DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); | 413 | DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); |
@@ -455,33 +429,54 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) | |||
455 | pci_read_config_dword(dev, 0x40, &val); | 429 | pci_read_config_dword(dev, 0x40, &val); |
456 | *((u32 *)&hwif->hwif_data) = val; | 430 | *((u32 *)&hwif->hwif_data) = val; |
457 | 431 | ||
432 | hwif->atapi_dma = 0; | ||
433 | hwif->mwdma_mask = 0; | ||
434 | hwif->swdma_mask = 0; | ||
435 | hwif->autodma = 0; | ||
436 | |||
458 | if (!hwif->dma_base) | 437 | if (!hwif->dma_base) |
459 | return; | 438 | return; |
460 | 439 | ||
461 | hwif->atapi_dma = 1; | 440 | dma_state = hwif->INB(hwif->dma_base + 2) & ~0x60; |
462 | hwif->mwdma_mask = 0x07; | 441 | rev = sl82c105_bridge_revision(hwif->pci_dev); |
463 | hwif->swdma_mask = 0x07; | 442 | if (rev <= 5) { |
464 | 443 | /* | |
444 | * Never ever EVER under any circumstances enable | ||
445 | * DMA when the bridge is this old. | ||
446 | */ | ||
447 | printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", | ||
448 | hwif->name, rev); | ||
449 | } else { | ||
465 | #ifdef CONFIG_BLK_DEV_IDEDMA | 450 | #ifdef CONFIG_BLK_DEV_IDEDMA |
466 | hwif->ide_dma_check = &sl82c105_check_drive; | 451 | dma_state |= 0x60; |
467 | hwif->ide_dma_on = &sl82c105_ide_dma_on; | 452 | |
468 | hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly; | 453 | hwif->atapi_dma = 1; |
469 | hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq; | 454 | hwif->mwdma_mask = 0x07; |
470 | hwif->dma_start = &sl82c105_ide_dma_start; | 455 | hwif->swdma_mask = 0x07; |
471 | hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout; | 456 | |
472 | 457 | hwif->ide_dma_check = &sl82c105_check_drive; | |
473 | if (!noautodma) | 458 | hwif->ide_dma_on = &sl82c105_ide_dma_on; |
474 | hwif->autodma = 1; | 459 | hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly; |
475 | hwif->drives[0].autodma = hwif->autodma; | 460 | hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq; |
476 | hwif->drives[1].autodma = hwif->autodma; | 461 | hwif->dma_start = &sl82c105_ide_dma_start; |
462 | hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout; | ||
463 | |||
464 | if (!noautodma) | ||
465 | hwif->autodma = 1; | ||
466 | hwif->drives[0].autodma = hwif->autodma; | ||
467 | hwif->drives[1].autodma = hwif->autodma; | ||
468 | |||
469 | if (hwif->mate) | ||
470 | hwif->serialized = hwif->mate->serialized = 1; | ||
477 | #endif /* CONFIG_BLK_DEV_IDEDMA */ | 471 | #endif /* CONFIG_BLK_DEV_IDEDMA */ |
472 | } | ||
473 | hwif->OUTB(dma_state, hwif->dma_base + 2); | ||
478 | } | 474 | } |
479 | 475 | ||
480 | static ide_pci_device_t sl82c105_chipset __devinitdata = { | 476 | static ide_pci_device_t sl82c105_chipset __devinitdata = { |
481 | .name = "W82C105", | 477 | .name = "W82C105", |
482 | .init_chipset = init_chipset_sl82c105, | 478 | .init_chipset = init_chipset_sl82c105, |
483 | .init_hwif = init_hwif_sl82c105, | 479 | .init_hwif = init_hwif_sl82c105, |
484 | .init_dma = init_dma_sl82c105, | ||
485 | .channels = 2, | 480 | .channels = 2, |
486 | .autodma = NOAUTODMA, | 481 | .autodma = NOAUTODMA, |
487 | .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, | 482 | .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, |
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index b3e65a65d202..136911a86e84 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c | |||
@@ -1667,11 +1667,16 @@ static struct macio_driver pmac_ide_macio_driver = | |||
1667 | }; | 1667 | }; |
1668 | 1668 | ||
1669 | static struct pci_device_id pmac_ide_pci_match[] = { | 1669 | static struct pci_device_id pmac_ide_pci_match[] = { |
1670 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1670 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA, |
1671 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1671 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
1672 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1672 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, |
1673 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
1674 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, | ||
1675 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
1673 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA, | 1676 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA, |
1674 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1677 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
1678 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA, | ||
1679 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
1675 | }; | 1680 | }; |
1676 | 1681 | ||
1677 | static struct pci_driver pmac_ide_pci_driver = { | 1682 | static struct pci_driver pmac_ide_pci_driver = { |
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c index 4b71fd6f7aed..7972c73bc14e 100644 --- a/drivers/media/common/ir-common.c +++ b/drivers/media/common/ir-common.c | |||
@@ -126,6 +126,66 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { | |||
126 | }; | 126 | }; |
127 | EXPORT_SYMBOL_GPL(ir_codes_winfast); | 127 | EXPORT_SYMBOL_GPL(ir_codes_winfast); |
128 | 128 | ||
129 | IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { | ||
130 | [ 0x59 ] = KEY_MUTE, | ||
131 | [ 0x4a ] = KEY_POWER, | ||
132 | |||
133 | [ 0x18 ] = KEY_TEXT, | ||
134 | [ 0x26 ] = KEY_TV, | ||
135 | [ 0x3d ] = KEY_PRINT, | ||
136 | |||
137 | [ 0x48 ] = KEY_RED, | ||
138 | [ 0x04 ] = KEY_GREEN, | ||
139 | [ 0x11 ] = KEY_YELLOW, | ||
140 | [ 0x00 ] = KEY_BLUE, | ||
141 | |||
142 | [ 0x2d ] = KEY_VOLUMEUP, | ||
143 | [ 0x1e ] = KEY_VOLUMEDOWN, | ||
144 | |||
145 | [ 0x49 ] = KEY_MENU, | ||
146 | |||
147 | [ 0x16 ] = KEY_CHANNELUP, | ||
148 | [ 0x17 ] = KEY_CHANNELDOWN, | ||
149 | |||
150 | [ 0x20 ] = KEY_UP, | ||
151 | [ 0x21 ] = KEY_DOWN, | ||
152 | [ 0x22 ] = KEY_LEFT, | ||
153 | [ 0x23 ] = KEY_RIGHT, | ||
154 | [ 0x0d ] = KEY_SELECT, | ||
155 | |||
156 | |||
157 | |||
158 | [ 0x08 ] = KEY_BACK, | ||
159 | [ 0x07 ] = KEY_REFRESH, | ||
160 | |||
161 | [ 0x2f ] = KEY_ZOOM, | ||
162 | [ 0x29 ] = KEY_RECORD, | ||
163 | |||
164 | [ 0x4b ] = KEY_PAUSE, | ||
165 | [ 0x4d ] = KEY_REWIND, | ||
166 | [ 0x2e ] = KEY_PLAY, | ||
167 | [ 0x4e ] = KEY_FORWARD, | ||
168 | [ 0x53 ] = KEY_PREVIOUS, | ||
169 | [ 0x4c ] = KEY_STOP, | ||
170 | [ 0x54 ] = KEY_NEXT, | ||
171 | |||
172 | [ 0x69 ] = KEY_KP0, | ||
173 | [ 0x6a ] = KEY_KP1, | ||
174 | [ 0x6b ] = KEY_KP2, | ||
175 | [ 0x6c ] = KEY_KP3, | ||
176 | [ 0x6d ] = KEY_KP4, | ||
177 | [ 0x6e ] = KEY_KP5, | ||
178 | [ 0x6f ] = KEY_KP6, | ||
179 | [ 0x70 ] = KEY_KP7, | ||
180 | [ 0x71 ] = KEY_KP8, | ||
181 | [ 0x72 ] = KEY_KP9, | ||
182 | |||
183 | [ 0x74 ] = KEY_CHANNEL, | ||
184 | [ 0x0a ] = KEY_BACKSPACE, | ||
185 | }; | ||
186 | |||
187 | EXPORT_SYMBOL_GPL(ir_codes_pinnacle); | ||
188 | |||
129 | /* empty keytable, can be used as placeholder for not-yet created keytables */ | 189 | /* empty keytable, can be used as placeholder for not-yet created keytables */ |
130 | IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { | 190 | IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { |
131 | [ 42 ] = KEY_COFFEE, | 191 | [ 42 ] = KEY_COFFEE, |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 199b01188858..1a3b3c7e5e99 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -333,4 +333,18 @@ config VIDEO_M32R_AR_M64278 | |||
333 | Say Y here to use the Renesas M64278E-800 camera module, | 333 | Say Y here to use the Renesas M64278E-800 camera module, |
334 | which supports VGA(640x480 pixcels) size of images. | 334 | which supports VGA(640x480 pixcels) size of images. |
335 | 335 | ||
336 | config VIDEO_AUDIO_DECODER | ||
337 | tristate "Add support for additional audio chipsets" | ||
338 | depends on VIDEO_DEV && I2C && EXPERIMENTAL | ||
339 | ---help--- | ||
340 | Say Y here to compile drivers for WM8775 and CS53L32A audio | ||
341 | decoders. | ||
342 | |||
343 | config VIDEO_DECODER | ||
344 | tristate "Add support for additional video chipsets" | ||
345 | depends on VIDEO_DEV && I2C && EXPERIMENTAL | ||
346 | ---help--- | ||
347 | Say Y here to compile drivers for SAA7115, SAA7127 and CX25840 | ||
348 | video decoders. | ||
349 | |||
336 | endmenu | 350 | endmenu |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 3ac465992400..82060f9909d8 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -36,10 +36,11 @@ obj-$(CONFIG_VIDEO_CPIA) += cpia.o | |||
36 | obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o | 36 | obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o |
37 | obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o | 37 | obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o |
38 | obj-$(CONFIG_VIDEO_MEYE) += meye.o | 38 | obj-$(CONFIG_VIDEO_MEYE) += meye.o |
39 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ | 39 | obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ |
40 | obj-$(CONFIG_VIDEO_CX88) += cx88/ | 40 | obj-$(CONFIG_VIDEO_CX88) += cx88/ |
41 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ | 41 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ |
42 | obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o | 42 | obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o |
43 | obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o | ||
43 | obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ | 44 | obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ |
44 | obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o | 45 | obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o |
45 | obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o | 46 | obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o |
@@ -55,4 +56,6 @@ obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o | |||
55 | 56 | ||
56 | obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o | 57 | obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o |
57 | 58 | ||
59 | obj-$(CONFIG_VIDEO_DECODER) += saa7115.o cx25840/ saa7127.o | ||
60 | |||
58 | EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core | 61 | EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core |
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 3413bace443a..e31ebb11c468 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c | |||
@@ -2133,7 +2133,10 @@ struct tvcard bttv_tvcards[] = { | |||
2133 | .tuner_addr = ADDR_UNSET, | 2133 | .tuner_addr = ADDR_UNSET, |
2134 | .radio_addr = ADDR_UNSET, | 2134 | .radio_addr = ADDR_UNSET, |
2135 | .has_dvb = 1, | 2135 | .has_dvb = 1, |
2136 | .has_remote = 1, | ||
2137 | .gpiomask = 0x1b, | ||
2136 | .no_gpioirq = 1, | 2138 | .no_gpioirq = 1, |
2139 | .any_irq = 1, | ||
2137 | }, | 2140 | }, |
2138 | [BTTV_BOARD_PV143] = { | 2141 | [BTTV_BOARD_PV143] = { |
2139 | /* Jorge Boncompte - DTI2 <jorge@dti2.net> */ | 2142 | /* Jorge Boncompte - DTI2 <jorge@dti2.net> */ |
@@ -2796,7 +2799,24 @@ struct tvcard bttv_tvcards[] = { | |||
2796 | .tuner_addr = ADDR_UNSET, | 2799 | .tuner_addr = ADDR_UNSET, |
2797 | .radio_addr = ADDR_UNSET, | 2800 | .radio_addr = ADDR_UNSET, |
2798 | }, | 2801 | }, |
2799 | 2802 | /* ---- card 0x8e ---------------------------------- */ | |
2803 | [BTTV_BOARD_SABRENT_TVFM] = { | ||
2804 | .name = "Sabrent TV-FM (bttv version)", | ||
2805 | .video_inputs = 3, | ||
2806 | .audio_inputs = 1, | ||
2807 | .tuner = 0, | ||
2808 | .svhs = 2, | ||
2809 | .gpiomask = 0x108007, | ||
2810 | .muxsel = { 2, 3, 1, 1}, | ||
2811 | .audiomux = { 100000, 100002, 100002, 100000}, | ||
2812 | .no_msp34xx = 1, | ||
2813 | .no_tda9875 = 1, | ||
2814 | .no_tda7432 = 1, | ||
2815 | .pll = PLL_28, | ||
2816 | .tuner_type = TUNER_TNF_5335MF, | ||
2817 | .tuner_addr = ADDR_UNSET, | ||
2818 | .has_radio = 1, | ||
2819 | }, | ||
2800 | }; | 2820 | }; |
2801 | 2821 | ||
2802 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); | 2822 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); |
@@ -3367,6 +3387,8 @@ void __devinit bttv_init_card2(struct bttv *btv) | |||
3367 | btv->has_remote=1; | 3387 | btv->has_remote=1; |
3368 | if (!bttv_tvcards[btv->c.type].no_gpioirq) | 3388 | if (!bttv_tvcards[btv->c.type].no_gpioirq) |
3369 | btv->gpioirq=1; | 3389 | btv->gpioirq=1; |
3390 | if (bttv_tvcards[btv->c.type].any_irq) | ||
3391 | btv->any_irq = 1; | ||
3370 | if (bttv_tvcards[btv->c.type].audio_hook) | 3392 | if (bttv_tvcards[btv->c.type].audio_hook) |
3371 | btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook; | 3393 | btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook; |
3372 | 3394 | ||
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 0005741d5514..709099f03bd2 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c | |||
@@ -3667,6 +3667,10 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) | |||
3667 | int handled = 0; | 3667 | int handled = 0; |
3668 | 3668 | ||
3669 | btv=(struct bttv *)dev_id; | 3669 | btv=(struct bttv *)dev_id; |
3670 | |||
3671 | if (btv->any_irq) | ||
3672 | handled = bttv_any_irq(&btv->c); | ||
3673 | |||
3670 | count=0; | 3674 | count=0; |
3671 | while (1) { | 3675 | while (1) { |
3672 | /* get/clear interrupt status bits */ | 3676 | /* get/clear interrupt status bits */ |
diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c index 575ce8b8e714..616a5b7e510c 100644 --- a/drivers/media/video/bttv-gpio.c +++ b/drivers/media/video/bttv-gpio.c | |||
@@ -113,6 +113,24 @@ void bttv_gpio_irq(struct bttv_core *core) | |||
113 | } | 113 | } |
114 | } | 114 | } |
115 | 115 | ||
116 | int bttv_any_irq(struct bttv_core *core) | ||
117 | { | ||
118 | struct bttv_sub_driver *drv; | ||
119 | struct bttv_sub_device *dev; | ||
120 | struct list_head *item; | ||
121 | int handled = 0; | ||
122 | |||
123 | list_for_each(item,&core->subs) { | ||
124 | dev = list_entry(item,struct bttv_sub_device,list); | ||
125 | drv = to_bttv_sub_drv(dev->dev.driver); | ||
126 | if (drv && drv->any_irq) { | ||
127 | if (drv->any_irq(dev)) | ||
128 | handled = 1; | ||
129 | } | ||
130 | } | ||
131 | return handled; | ||
132 | } | ||
133 | |||
116 | /* ----------------------------------------------------------------------- */ | 134 | /* ----------------------------------------------------------------------- */ |
117 | /* external: sub-driver register/unregister */ | 135 | /* external: sub-driver register/unregister */ |
118 | 136 | ||
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 124ea41dada4..93298f06e019 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h | |||
@@ -162,6 +162,7 @@ | |||
162 | #define BTTV_BOARD_PV_M4900 0x8b | 162 | #define BTTV_BOARD_PV_M4900 0x8b |
163 | #define BTTV_BOARD_OSPREY440 0x8c | 163 | #define BTTV_BOARD_OSPREY440 0x8c |
164 | #define BTTV_BOARD_ASOUND_SKYEYE 0x8d | 164 | #define BTTV_BOARD_ASOUND_SKYEYE 0x8d |
165 | #define BTTV_BOARD_SABRENT_TVFM 0x8e | ||
165 | 166 | ||
166 | /* i2c address list */ | 167 | /* i2c address list */ |
167 | #define I2C_TSA5522 0xc2 | 168 | #define I2C_TSA5522 0xc2 |
@@ -234,6 +235,7 @@ struct tvcard | |||
234 | unsigned int has_dvb:1; | 235 | unsigned int has_dvb:1; |
235 | unsigned int has_remote:1; | 236 | unsigned int has_remote:1; |
236 | unsigned int no_gpioirq:1; | 237 | unsigned int no_gpioirq:1; |
238 | unsigned int any_irq:1; | ||
237 | 239 | ||
238 | /* other settings */ | 240 | /* other settings */ |
239 | unsigned int pll; | 241 | unsigned int pll; |
@@ -333,6 +335,7 @@ struct bttv_sub_driver { | |||
333 | struct device_driver drv; | 335 | struct device_driver drv; |
334 | char wanted[BUS_ID_SIZE]; | 336 | char wanted[BUS_ID_SIZE]; |
335 | void (*gpio_irq)(struct bttv_sub_device *sub); | 337 | void (*gpio_irq)(struct bttv_sub_device *sub); |
338 | int (*any_irq)(struct bttv_sub_device *sub); | ||
336 | }; | 339 | }; |
337 | #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) | 340 | #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) |
338 | 341 | ||
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index 386f546f7d11..3aa9c6e4fc33 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h | |||
@@ -208,6 +208,7 @@ extern struct bus_type bttv_sub_bus_type; | |||
208 | int bttv_sub_add_device(struct bttv_core *core, char *name); | 208 | int bttv_sub_add_device(struct bttv_core *core, char *name); |
209 | int bttv_sub_del_devices(struct bttv_core *core); | 209 | int bttv_sub_del_devices(struct bttv_core *core); |
210 | void bttv_gpio_irq(struct bttv_core *core); | 210 | void bttv_gpio_irq(struct bttv_core *core); |
211 | int bttv_any_irq(struct bttv_core *core); | ||
211 | 212 | ||
212 | 213 | ||
213 | /* ---------------------------------------------------------- */ | 214 | /* ---------------------------------------------------------- */ |
@@ -273,6 +274,7 @@ struct bttv { | |||
273 | struct bttv_pll_info pll; | 274 | struct bttv_pll_info pll; |
274 | int triton1; | 275 | int triton1; |
275 | int gpioirq; | 276 | int gpioirq; |
277 | int any_irq; | ||
276 | int use_i2c_hw; | 278 | int use_i2c_hw; |
277 | 279 | ||
278 | /* old gpio interface */ | 280 | /* old gpio interface */ |
diff --git a/drivers/media/video/cx25840/Makefile b/drivers/media/video/cx25840/Makefile new file mode 100644 index 000000000000..543ebacdc9d7 --- /dev/null +++ b/drivers/media/video/cx25840/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \ | ||
2 | cx25840-vbi.o | ||
3 | |||
4 | obj-$(CONFIG_VIDEO_DECODER) += cx25840.o | ||
5 | |||
6 | EXTRA_CFLAGS += -I$(src)/.. | ||
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c new file mode 100644 index 000000000000..740908f8027d --- /dev/null +++ b/drivers/media/video/cx25840/cx25840-audio.c | |||
@@ -0,0 +1,368 @@ | |||
1 | /* cx25840 audio functions | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version 2 | ||
6 | * of the License, or (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #include <linux/videodev2.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <media/audiochip.h> | ||
22 | #include <media/v4l2-common.h> | ||
23 | |||
24 | #include "cx25840.h" | ||
25 | |||
26 | inline static int set_audclk_freq(struct i2c_client *client, | ||
27 | enum v4l2_audio_clock_freq freq) | ||
28 | { | ||
29 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
30 | |||
31 | /* assert soft reset */ | ||
32 | cx25840_and_or(client, 0x810, ~0x1, 0x01); | ||
33 | |||
34 | /* common for all inputs and rates */ | ||
35 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ | ||
36 | cx25840_write(client, 0x127, 0x50); | ||
37 | |||
38 | switch (state->audio_input) { | ||
39 | case AUDIO_TUNER: | ||
40 | switch (freq) { | ||
41 | case V4L2_AUDCLK_32_KHZ: | ||
42 | /* VID_PLL and AUX_PLL */ | ||
43 | cx25840_write4(client, 0x108, 0x0f040610); | ||
44 | |||
45 | /* AUX_PLL_FRAC */ | ||
46 | cx25840_write4(client, 0x110, 0xee39bb01); | ||
47 | |||
48 | /* src3/4/6_ctl = 0x0801f77f */ | ||
49 | cx25840_write4(client, 0x900, 0x7ff70108); | ||
50 | cx25840_write4(client, 0x904, 0x7ff70108); | ||
51 | cx25840_write4(client, 0x90c, 0x7ff70108); | ||
52 | break; | ||
53 | |||
54 | case V4L2_AUDCLK_441_KHZ: | ||
55 | /* VID_PLL and AUX_PLL */ | ||
56 | cx25840_write4(client, 0x108, 0x0f040910); | ||
57 | |||
58 | /* AUX_PLL_FRAC */ | ||
59 | cx25840_write4(client, 0x110, 0xd66bec00); | ||
60 | |||
61 | /* src3/4/6_ctl = 0x08016d59 */ | ||
62 | cx25840_write4(client, 0x900, 0x596d0108); | ||
63 | cx25840_write4(client, 0x904, 0x596d0108); | ||
64 | cx25840_write4(client, 0x90c, 0x596d0108); | ||
65 | break; | ||
66 | |||
67 | case V4L2_AUDCLK_48_KHZ: | ||
68 | /* VID_PLL and AUX_PLL */ | ||
69 | cx25840_write4(client, 0x108, 0x0f040a10); | ||
70 | |||
71 | /* AUX_PLL_FRAC */ | ||
72 | cx25840_write4(client, 0x110, 0xe5d69800); | ||
73 | |||
74 | /* src3/4/6_ctl = 0x08014faa */ | ||
75 | cx25840_write4(client, 0x900, 0xaa4f0108); | ||
76 | cx25840_write4(client, 0x904, 0xaa4f0108); | ||
77 | cx25840_write4(client, 0x90c, 0xaa4f0108); | ||
78 | break; | ||
79 | } | ||
80 | break; | ||
81 | |||
82 | case AUDIO_EXTERN_1: | ||
83 | case AUDIO_EXTERN_2: | ||
84 | case AUDIO_INTERN: | ||
85 | case AUDIO_RADIO: | ||
86 | switch (freq) { | ||
87 | case V4L2_AUDCLK_32_KHZ: | ||
88 | /* VID_PLL and AUX_PLL */ | ||
89 | cx25840_write4(client, 0x108, 0x0f04081e); | ||
90 | |||
91 | /* AUX_PLL_FRAC */ | ||
92 | cx25840_write4(client, 0x110, 0x69082a01); | ||
93 | |||
94 | /* src1_ctl = 0x08010000 */ | ||
95 | cx25840_write4(client, 0x8f8, 0x00000108); | ||
96 | |||
97 | /* src3/4/6_ctl = 0x08020000 */ | ||
98 | cx25840_write4(client, 0x900, 0x00000208); | ||
99 | cx25840_write4(client, 0x904, 0x00000208); | ||
100 | cx25840_write4(client, 0x90c, 0x00000208); | ||
101 | |||
102 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */ | ||
103 | cx25840_write(client, 0x127, 0x54); | ||
104 | break; | ||
105 | |||
106 | case V4L2_AUDCLK_441_KHZ: | ||
107 | /* VID_PLL and AUX_PLL */ | ||
108 | cx25840_write4(client, 0x108, 0x0f040918); | ||
109 | |||
110 | /* AUX_PLL_FRAC */ | ||
111 | cx25840_write4(client, 0x110, 0xd66bec00); | ||
112 | |||
113 | /* src1_ctl = 0x08010000 */ | ||
114 | cx25840_write4(client, 0x8f8, 0xcd600108); | ||
115 | |||
116 | /* src3/4/6_ctl = 0x08020000 */ | ||
117 | cx25840_write4(client, 0x900, 0x85730108); | ||
118 | cx25840_write4(client, 0x904, 0x85730108); | ||
119 | cx25840_write4(client, 0x90c, 0x85730108); | ||
120 | break; | ||
121 | |||
122 | case V4L2_AUDCLK_48_KHZ: | ||
123 | /* VID_PLL and AUX_PLL */ | ||
124 | cx25840_write4(client, 0x108, 0x0f040a18); | ||
125 | |||
126 | /* AUX_PLL_FRAC */ | ||
127 | cx25840_write4(client, 0x110, 0xe5d69800); | ||
128 | |||
129 | /* src1_ctl = 0x08010000 */ | ||
130 | cx25840_write4(client, 0x8f8, 0x00800108); | ||
131 | |||
132 | /* src3/4/6_ctl = 0x08020000 */ | ||
133 | cx25840_write4(client, 0x900, 0x55550108); | ||
134 | cx25840_write4(client, 0x904, 0x55550108); | ||
135 | cx25840_write4(client, 0x90c, 0x55550108); | ||
136 | break; | ||
137 | } | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | /* deassert soft reset */ | ||
142 | cx25840_and_or(client, 0x810, ~0x1, 0x00); | ||
143 | |||
144 | state->audclk_freq = freq; | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int set_input(struct i2c_client *client, int audio_input) | ||
150 | { | ||
151 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
152 | |||
153 | cx25840_dbg("set audio input (%d)\n", audio_input); | ||
154 | |||
155 | /* stop microcontroller */ | ||
156 | cx25840_and_or(client, 0x803, ~0x10, 0); | ||
157 | |||
158 | /* Mute everything to prevent the PFFT! */ | ||
159 | cx25840_write(client, 0x8d3, 0x1f); | ||
160 | |||
161 | switch (audio_input) { | ||
162 | case AUDIO_TUNER: | ||
163 | /* Set Path1 to Analog Demod Main Channel */ | ||
164 | cx25840_write4(client, 0x8d0, 0x7038061f); | ||
165 | |||
166 | /* When the microcontroller detects the | ||
167 | * audio format, it will unmute the lines */ | ||
168 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
169 | break; | ||
170 | |||
171 | case AUDIO_EXTERN_1: | ||
172 | case AUDIO_EXTERN_2: | ||
173 | case AUDIO_INTERN: | ||
174 | case AUDIO_RADIO: | ||
175 | /* Set Path1 to Serial Audio Input */ | ||
176 | cx25840_write4(client, 0x8d0, 0x12100101); | ||
177 | |||
178 | /* The microcontroller should not be started for the | ||
179 | * non-tuner inputs: autodetection is specific for | ||
180 | * TV audio. */ | ||
181 | break; | ||
182 | |||
183 | default: | ||
184 | cx25840_dbg("Invalid audio input selection %d\n", audio_input); | ||
185 | return -EINVAL; | ||
186 | } | ||
187 | |||
188 | state->audio_input = audio_input; | ||
189 | |||
190 | return set_audclk_freq(client, state->audclk_freq); | ||
191 | } | ||
192 | |||
193 | inline static int get_volume(struct i2c_client *client) | ||
194 | { | ||
195 | /* Volume runs +18dB to -96dB in 1/2dB steps | ||
196 | * change to fit the msp3400 -114dB to +12dB range */ | ||
197 | |||
198 | /* check PATH1_VOLUME */ | ||
199 | int vol = 228 - cx25840_read(client, 0x8d4); | ||
200 | vol = (vol / 2) + 23; | ||
201 | return vol << 9; | ||
202 | } | ||
203 | |||
204 | inline static void set_volume(struct i2c_client *client, int volume) | ||
205 | { | ||
206 | /* First convert the volume to msp3400 values (0-127) */ | ||
207 | int vol = volume >> 9; | ||
208 | /* now scale it up to cx25840 values | ||
209 | * -114dB to -96dB maps to 0 | ||
210 | * this should be 19, but in my testing that was 4dB too loud */ | ||
211 | if (vol <= 23) { | ||
212 | vol = 0; | ||
213 | } else { | ||
214 | vol -= 23; | ||
215 | } | ||
216 | |||
217 | /* PATH1_VOLUME */ | ||
218 | cx25840_write(client, 0x8d4, 228 - (vol * 2)); | ||
219 | } | ||
220 | |||
221 | inline static int get_bass(struct i2c_client *client) | ||
222 | { | ||
223 | /* bass is 49 steps +12dB to -12dB */ | ||
224 | |||
225 | /* check PATH1_EQ_BASS_VOL */ | ||
226 | int bass = cx25840_read(client, 0x8d9) & 0x3f; | ||
227 | bass = (((48 - bass) * 0xffff) + 47) / 48; | ||
228 | return bass; | ||
229 | } | ||
230 | |||
231 | inline static void set_bass(struct i2c_client *client, int bass) | ||
232 | { | ||
233 | /* PATH1_EQ_BASS_VOL */ | ||
234 | cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff)); | ||
235 | } | ||
236 | |||
237 | inline static int get_treble(struct i2c_client *client) | ||
238 | { | ||
239 | /* treble is 49 steps +12dB to -12dB */ | ||
240 | |||
241 | /* check PATH1_EQ_TREBLE_VOL */ | ||
242 | int treble = cx25840_read(client, 0x8db) & 0x3f; | ||
243 | treble = (((48 - treble) * 0xffff) + 47) / 48; | ||
244 | return treble; | ||
245 | } | ||
246 | |||
247 | inline static void set_treble(struct i2c_client *client, int treble) | ||
248 | { | ||
249 | /* PATH1_EQ_TREBLE_VOL */ | ||
250 | cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff)); | ||
251 | } | ||
252 | |||
253 | inline static int get_balance(struct i2c_client *client) | ||
254 | { | ||
255 | /* balance is 7 bit, 0 to -96dB */ | ||
256 | |||
257 | /* check PATH1_BAL_LEVEL */ | ||
258 | int balance = cx25840_read(client, 0x8d5) & 0x7f; | ||
259 | /* check PATH1_BAL_LEFT */ | ||
260 | if ((cx25840_read(client, 0x8d5) & 0x80) == 0) | ||
261 | balance = 0x80 - balance; | ||
262 | else | ||
263 | balance = 0x80 + balance; | ||
264 | return balance << 8; | ||
265 | } | ||
266 | |||
267 | inline static void set_balance(struct i2c_client *client, int balance) | ||
268 | { | ||
269 | int bal = balance >> 8; | ||
270 | if (bal > 0x80) { | ||
271 | /* PATH1_BAL_LEFT */ | ||
272 | cx25840_and_or(client, 0x8d5, 0x7f, 0x80); | ||
273 | /* PATH1_BAL_LEVEL */ | ||
274 | cx25840_and_or(client, 0x8d5, ~0x7f, bal & 0x7f); | ||
275 | } else { | ||
276 | /* PATH1_BAL_LEFT */ | ||
277 | cx25840_and_or(client, 0x8d5, 0x7f, 0x00); | ||
278 | /* PATH1_BAL_LEVEL */ | ||
279 | cx25840_and_or(client, 0x8d5, ~0x7f, 0x80 - bal); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | inline static int get_mute(struct i2c_client *client) | ||
284 | { | ||
285 | /* check SRC1_MUTE_EN */ | ||
286 | return cx25840_read(client, 0x8d3) & 0x2 ? 1 : 0; | ||
287 | } | ||
288 | |||
289 | inline static void set_mute(struct i2c_client *client, int mute) | ||
290 | { | ||
291 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
292 | |||
293 | if (state->audio_input == AUDIO_TUNER) { | ||
294 | /* Must turn off microcontroller in order to mute sound. | ||
295 | * Not sure if this is the best method, but it does work. | ||
296 | * If the microcontroller is running, then it will undo any | ||
297 | * changes to the mute register. */ | ||
298 | if (mute) { | ||
299 | /* disable microcontroller */ | ||
300 | cx25840_and_or(client, 0x803, ~0x10, 0x00); | ||
301 | cx25840_write(client, 0x8d3, 0x1f); | ||
302 | } else { | ||
303 | /* enable microcontroller */ | ||
304 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
305 | } | ||
306 | } else { | ||
307 | /* SRC1_MUTE_EN */ | ||
308 | cx25840_and_or(client, 0x8d3, ~0x2, mute ? 0x02 : 0x00); | ||
309 | } | ||
310 | } | ||
311 | |||
312 | int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) | ||
313 | { | ||
314 | struct v4l2_control *ctrl = arg; | ||
315 | |||
316 | switch (cmd) { | ||
317 | case AUDC_SET_INPUT: | ||
318 | return set_input(client, *(int *)arg); | ||
319 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | ||
320 | return set_audclk_freq(client, *(enum v4l2_audio_clock_freq *)arg); | ||
321 | case VIDIOC_G_CTRL: | ||
322 | switch (ctrl->id) { | ||
323 | case V4L2_CID_AUDIO_VOLUME: | ||
324 | ctrl->value = get_volume(client); | ||
325 | break; | ||
326 | case V4L2_CID_AUDIO_BASS: | ||
327 | ctrl->value = get_bass(client); | ||
328 | break; | ||
329 | case V4L2_CID_AUDIO_TREBLE: | ||
330 | ctrl->value = get_treble(client); | ||
331 | break; | ||
332 | case V4L2_CID_AUDIO_BALANCE: | ||
333 | ctrl->value = get_balance(client); | ||
334 | break; | ||
335 | case V4L2_CID_AUDIO_MUTE: | ||
336 | ctrl->value = get_mute(client); | ||
337 | break; | ||
338 | default: | ||
339 | return -EINVAL; | ||
340 | } | ||
341 | break; | ||
342 | case VIDIOC_S_CTRL: | ||
343 | switch (ctrl->id) { | ||
344 | case V4L2_CID_AUDIO_VOLUME: | ||
345 | set_volume(client, ctrl->value); | ||
346 | break; | ||
347 | case V4L2_CID_AUDIO_BASS: | ||
348 | set_bass(client, ctrl->value); | ||
349 | break; | ||
350 | case V4L2_CID_AUDIO_TREBLE: | ||
351 | set_treble(client, ctrl->value); | ||
352 | break; | ||
353 | case V4L2_CID_AUDIO_BALANCE: | ||
354 | set_balance(client, ctrl->value); | ||
355 | break; | ||
356 | case V4L2_CID_AUDIO_MUTE: | ||
357 | set_mute(client, ctrl->value); | ||
358 | break; | ||
359 | default: | ||
360 | return -EINVAL; | ||
361 | } | ||
362 | break; | ||
363 | default: | ||
364 | return -EINVAL; | ||
365 | } | ||
366 | |||
367 | return 0; | ||
368 | } | ||
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c new file mode 100644 index 000000000000..f6afeec499c5 --- /dev/null +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -0,0 +1,1020 @@ | |||
1 | /* cx25840 - Conexant CX25840 audio/video decoder driver | ||
2 | * | ||
3 | * Copyright (C) 2004 Ulf Eklund | ||
4 | * | ||
5 | * Based on the saa7115 driver and on the first verison of Chris Kennedy's | ||
6 | * cx25840 driver. | ||
7 | * | ||
8 | * Changes by Tyler Trafford <tatrafford@comcast.net> | ||
9 | * - cleanup/rewrite for V4L2 API (2005) | ||
10 | * | ||
11 | * VBI support by Hans Verkuil <hverkuil@xs4all.nl>. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
26 | */ | ||
27 | |||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/videodev2.h> | ||
33 | #include <linux/i2c.h> | ||
34 | #include <media/audiochip.h> | ||
35 | #include <media/v4l2-common.h> | ||
36 | |||
37 | #include "cx25840.h" | ||
38 | |||
39 | MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver"); | ||
40 | MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford"); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | |||
43 | static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; | ||
44 | |||
45 | |||
46 | int cx25840_debug = 0; | ||
47 | |||
48 | module_param(cx25840_debug, bool, 0644); | ||
49 | |||
50 | MODULE_PARM_DESC(cx25840_debug, "Debugging messages [0=Off (default) 1=On]"); | ||
51 | |||
52 | I2C_CLIENT_INSMOD; | ||
53 | |||
54 | /* ----------------------------------------------------------------------- */ | ||
55 | |||
56 | int cx25840_write(struct i2c_client *client, u16 addr, u8 value) | ||
57 | { | ||
58 | u8 buffer[3]; | ||
59 | buffer[0] = addr >> 8; | ||
60 | buffer[1] = addr & 0xff; | ||
61 | buffer[2] = value; | ||
62 | return i2c_master_send(client, buffer, 3); | ||
63 | } | ||
64 | |||
65 | int cx25840_write4(struct i2c_client *client, u16 addr, u32 value) | ||
66 | { | ||
67 | u8 buffer[6]; | ||
68 | buffer[0] = addr >> 8; | ||
69 | buffer[1] = addr & 0xff; | ||
70 | buffer[2] = value >> 24; | ||
71 | buffer[3] = (value >> 16) & 0xff; | ||
72 | buffer[4] = (value >> 8) & 0xff; | ||
73 | buffer[5] = value & 0xff; | ||
74 | return i2c_master_send(client, buffer, 6); | ||
75 | } | ||
76 | |||
77 | u8 cx25840_read(struct i2c_client * client, u16 addr) | ||
78 | { | ||
79 | u8 buffer[2]; | ||
80 | buffer[0] = addr >> 8; | ||
81 | buffer[1] = addr & 0xff; | ||
82 | |||
83 | if (i2c_master_send(client, buffer, 2) < 2) | ||
84 | return 0; | ||
85 | |||
86 | if (i2c_master_recv(client, buffer, 1) < 1) | ||
87 | return 0; | ||
88 | |||
89 | return buffer[0]; | ||
90 | } | ||
91 | |||
92 | u32 cx25840_read4(struct i2c_client * client, u16 addr) | ||
93 | { | ||
94 | u8 buffer[4]; | ||
95 | buffer[0] = addr >> 8; | ||
96 | buffer[1] = addr & 0xff; | ||
97 | |||
98 | if (i2c_master_send(client, buffer, 2) < 2) | ||
99 | return 0; | ||
100 | |||
101 | if (i2c_master_recv(client, buffer, 4) < 4) | ||
102 | return 0; | ||
103 | |||
104 | return (buffer[0] << 24) | (buffer[1] << 16) | | ||
105 | (buffer[2] << 8) | buffer[3]; | ||
106 | } | ||
107 | |||
108 | int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask, | ||
109 | u8 or_value) | ||
110 | { | ||
111 | return cx25840_write(client, addr, | ||
112 | (cx25840_read(client, addr) & and_mask) | | ||
113 | or_value); | ||
114 | } | ||
115 | |||
116 | /* ----------------------------------------------------------------------- */ | ||
117 | |||
118 | static int set_input(struct i2c_client *, enum cx25840_input); | ||
119 | static void input_change(struct i2c_client *); | ||
120 | static void log_status(struct i2c_client *client); | ||
121 | |||
122 | /* ----------------------------------------------------------------------- */ | ||
123 | |||
124 | static inline void init_dll1(struct i2c_client *client) | ||
125 | { | ||
126 | /* This is the Hauppauge sequence used to | ||
127 | * initialize the Delay Lock Loop 1 (ADC DLL). */ | ||
128 | cx25840_write(client, 0x159, 0x23); | ||
129 | cx25840_write(client, 0x15a, 0x87); | ||
130 | cx25840_write(client, 0x15b, 0x06); | ||
131 | cx25840_write(client, 0x159, 0xe1); | ||
132 | cx25840_write(client, 0x15a, 0x86); | ||
133 | cx25840_write(client, 0x159, 0xe0); | ||
134 | cx25840_write(client, 0x159, 0xe1); | ||
135 | cx25840_write(client, 0x15b, 0x10); | ||
136 | } | ||
137 | |||
138 | static inline void init_dll2(struct i2c_client *client) | ||
139 | { | ||
140 | /* This is the Hauppauge sequence used to | ||
141 | * initialize the Delay Lock Loop 2 (ADC DLL). */ | ||
142 | cx25840_write(client, 0x15d, 0xe3); | ||
143 | cx25840_write(client, 0x15e, 0x86); | ||
144 | cx25840_write(client, 0x15f, 0x06); | ||
145 | cx25840_write(client, 0x15d, 0xe1); | ||
146 | cx25840_write(client, 0x15d, 0xe0); | ||
147 | cx25840_write(client, 0x15d, 0xe1); | ||
148 | } | ||
149 | |||
150 | static void cx25840_initialize(struct i2c_client *client, int loadfw) | ||
151 | { | ||
152 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
153 | |||
154 | /* datasheet startup in numbered steps, refer to page 3-77 */ | ||
155 | /* 2. */ | ||
156 | cx25840_and_or(client, 0x803, ~0x10, 0x00); | ||
157 | /* The default of this register should be 4, but I get 0 instead. | ||
158 | * Set this register to 4 manually. */ | ||
159 | cx25840_write(client, 0x000, 0x04); | ||
160 | /* 3. */ | ||
161 | init_dll1(client); | ||
162 | init_dll2(client); | ||
163 | cx25840_write(client, 0x136, 0x0a); | ||
164 | /* 4. */ | ||
165 | cx25840_write(client, 0x13c, 0x01); | ||
166 | cx25840_write(client, 0x13c, 0x00); | ||
167 | /* 5. */ | ||
168 | if (loadfw) | ||
169 | cx25840_loadfw(client); | ||
170 | /* 6. */ | ||
171 | cx25840_write(client, 0x115, 0x8c); | ||
172 | cx25840_write(client, 0x116, 0x07); | ||
173 | cx25840_write(client, 0x118, 0x02); | ||
174 | /* 7. */ | ||
175 | cx25840_write(client, 0x4a5, 0x80); | ||
176 | cx25840_write(client, 0x4a5, 0x00); | ||
177 | cx25840_write(client, 0x402, 0x00); | ||
178 | /* 8. */ | ||
179 | cx25840_write(client, 0x401, 0x18); | ||
180 | cx25840_write(client, 0x4a2, 0x10); | ||
181 | cx25840_write(client, 0x402, 0x04); | ||
182 | /* 10. */ | ||
183 | cx25840_write(client, 0x8d3, 0x1f); | ||
184 | cx25840_write(client, 0x8e3, 0x03); | ||
185 | |||
186 | cx25840_vbi_setup(client); | ||
187 | |||
188 | /* trial and error says these are needed to get audio */ | ||
189 | cx25840_write(client, 0x914, 0xa0); | ||
190 | cx25840_write(client, 0x918, 0xa0); | ||
191 | cx25840_write(client, 0x919, 0x01); | ||
192 | |||
193 | /* stereo prefered */ | ||
194 | cx25840_write(client, 0x809, 0x04); | ||
195 | /* AC97 shift */ | ||
196 | cx25840_write(client, 0x8cf, 0x0f); | ||
197 | |||
198 | /* (re)set video input */ | ||
199 | set_input(client, state->input); | ||
200 | /* (re)set audio input */ | ||
201 | cx25840_audio(client, AUDC_SET_INPUT, &state->audio_input); | ||
202 | |||
203 | /* start microcontroller */ | ||
204 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
205 | } | ||
206 | |||
207 | /* ----------------------------------------------------------------------- */ | ||
208 | |||
209 | static void input_change(struct i2c_client *client) | ||
210 | { | ||
211 | v4l2_std_id std = cx25840_get_v4lstd(client); | ||
212 | |||
213 | if (std & V4L2_STD_PAL) { | ||
214 | /* Follow tuner change procedure for PAL */ | ||
215 | cx25840_write(client, 0x808, 0xff); | ||
216 | cx25840_write(client, 0x80b, 0x10); | ||
217 | } else if (std & V4L2_STD_SECAM) { | ||
218 | /* Select autodetect for SECAM */ | ||
219 | cx25840_write(client, 0x808, 0xff); | ||
220 | cx25840_write(client, 0x80b, 0x10); | ||
221 | } else if (std & V4L2_STD_NTSC) { | ||
222 | /* NTSC */ | ||
223 | cx25840_write(client, 0x808, 0xf6); | ||
224 | cx25840_write(client, 0x80b, 0x00); | ||
225 | } | ||
226 | |||
227 | if (cx25840_read(client, 0x803) & 0x10) { | ||
228 | /* restart audio decoder microcontroller */ | ||
229 | cx25840_and_or(client, 0x803, ~0x10, 0x00); | ||
230 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | static int set_input(struct i2c_client *client, enum cx25840_input input) | ||
235 | { | ||
236 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
237 | |||
238 | cx25840_dbg("decoder set input (%d)\n", input); | ||
239 | |||
240 | switch (input) { | ||
241 | case CX25840_TUNER: | ||
242 | cx25840_dbg("now setting Tuner input\n"); | ||
243 | |||
244 | if (state->cardtype == CARDTYPE_PVR150) { | ||
245 | /* CH_SEL_ADC2=1 */ | ||
246 | cx25840_and_or(client, 0x102, ~0x2, 0x02); | ||
247 | } | ||
248 | |||
249 | /* Video Input Control */ | ||
250 | if (state->cardtype == CARDTYPE_PG600) { | ||
251 | cx25840_write(client, 0x103, 0x11); | ||
252 | } else { | ||
253 | cx25840_write(client, 0x103, 0x46); | ||
254 | } | ||
255 | |||
256 | /* INPUT_MODE=0 */ | ||
257 | cx25840_and_or(client, 0x401, ~0x6, 0x00); | ||
258 | break; | ||
259 | |||
260 | case CX25840_COMPOSITE0: | ||
261 | case CX25840_COMPOSITE1: | ||
262 | cx25840_dbg("now setting Composite input\n"); | ||
263 | |||
264 | /* Video Input Control */ | ||
265 | if (state->cardtype == CARDTYPE_PG600) { | ||
266 | cx25840_write(client, 0x103, 0x00); | ||
267 | } else { | ||
268 | cx25840_write(client, 0x103, 0x02); | ||
269 | } | ||
270 | |||
271 | /* INPUT_MODE=0 */ | ||
272 | cx25840_and_or(client, 0x401, ~0x6, 0x00); | ||
273 | break; | ||
274 | |||
275 | case CX25840_SVIDEO0: | ||
276 | case CX25840_SVIDEO1: | ||
277 | cx25840_dbg("now setting S-Video input\n"); | ||
278 | |||
279 | /* CH_SEL_ADC2=0 */ | ||
280 | cx25840_and_or(client, 0x102, ~0x2, 0x00); | ||
281 | |||
282 | /* Video Input Control */ | ||
283 | if (state->cardtype == CARDTYPE_PG600) { | ||
284 | cx25840_write(client, 0x103, 0x02); | ||
285 | } else { | ||
286 | cx25840_write(client, 0x103, 0x10); | ||
287 | } | ||
288 | |||
289 | /* INPUT_MODE=1 */ | ||
290 | cx25840_and_or(client, 0x401, ~0x6, 0x02); | ||
291 | break; | ||
292 | |||
293 | default: | ||
294 | cx25840_err("%d is not a valid input!\n", input); | ||
295 | return -EINVAL; | ||
296 | } | ||
297 | |||
298 | state->input = input; | ||
299 | input_change(client); | ||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | /* ----------------------------------------------------------------------- */ | ||
304 | |||
305 | static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) | ||
306 | { | ||
307 | u8 fmt; | ||
308 | |||
309 | switch (std) { | ||
310 | /* zero is autodetect */ | ||
311 | case 0: fmt = 0x0; break; | ||
312 | /* default ntsc to ntsc-m */ | ||
313 | case V4L2_STD_NTSC: | ||
314 | case V4L2_STD_NTSC_M: fmt = 0x1; break; | ||
315 | case V4L2_STD_NTSC_M_JP: fmt = 0x2; break; | ||
316 | case V4L2_STD_NTSC_443: fmt = 0x3; break; | ||
317 | case V4L2_STD_PAL: fmt = 0x4; break; | ||
318 | case V4L2_STD_PAL_M: fmt = 0x5; break; | ||
319 | case V4L2_STD_PAL_N: fmt = 0x6; break; | ||
320 | case V4L2_STD_PAL_Nc: fmt = 0x7; break; | ||
321 | case V4L2_STD_PAL_60: fmt = 0x8; break; | ||
322 | case V4L2_STD_SECAM: fmt = 0xc; break; | ||
323 | default: | ||
324 | return -ERANGE; | ||
325 | } | ||
326 | |||
327 | cx25840_and_or(client, 0x400, ~0xf, fmt); | ||
328 | cx25840_vbi_setup(client); | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) | ||
333 | { | ||
334 | /* check VID_FMT_SEL first */ | ||
335 | u8 fmt = cx25840_read(client, 0x400) & 0xf; | ||
336 | |||
337 | if (!fmt) { | ||
338 | /* check AFD_FMT_STAT if set to autodetect */ | ||
339 | fmt = cx25840_read(client, 0x40d) & 0xf; | ||
340 | } | ||
341 | |||
342 | switch (fmt) { | ||
343 | case 0x1: return V4L2_STD_NTSC_M; | ||
344 | case 0x2: return V4L2_STD_NTSC_M_JP; | ||
345 | case 0x3: return V4L2_STD_NTSC_443; | ||
346 | case 0x4: return V4L2_STD_PAL; | ||
347 | case 0x5: return V4L2_STD_PAL_M; | ||
348 | case 0x6: return V4L2_STD_PAL_N; | ||
349 | case 0x7: return V4L2_STD_PAL_Nc; | ||
350 | case 0x8: return V4L2_STD_PAL_60; | ||
351 | case 0xc: return V4L2_STD_SECAM; | ||
352 | default: return V4L2_STD_UNKNOWN; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | /* ----------------------------------------------------------------------- */ | ||
357 | |||
358 | static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
359 | { | ||
360 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
361 | |||
362 | switch (ctrl->id) { | ||
363 | case CX25840_CID_CARDTYPE: | ||
364 | switch (ctrl->value) { | ||
365 | case CARDTYPE_PVR150: | ||
366 | case CARDTYPE_PG600: | ||
367 | state->cardtype = ctrl->value; | ||
368 | break; | ||
369 | default: | ||
370 | return -ERANGE; | ||
371 | } | ||
372 | |||
373 | set_input(client, state->input); | ||
374 | break; | ||
375 | |||
376 | case V4L2_CID_BRIGHTNESS: | ||
377 | if (ctrl->value < 0 || ctrl->value > 255) { | ||
378 | cx25840_err("invalid brightness setting %d\n", | ||
379 | ctrl->value); | ||
380 | return -ERANGE; | ||
381 | } | ||
382 | |||
383 | cx25840_write(client, 0x414, ctrl->value - 128); | ||
384 | break; | ||
385 | |||
386 | case V4L2_CID_CONTRAST: | ||
387 | if (ctrl->value < 0 || ctrl->value > 127) { | ||
388 | cx25840_err("invalid contrast setting %d\n", | ||
389 | ctrl->value); | ||
390 | return -ERANGE; | ||
391 | } | ||
392 | |||
393 | cx25840_write(client, 0x415, ctrl->value << 1); | ||
394 | break; | ||
395 | |||
396 | case V4L2_CID_SATURATION: | ||
397 | if (ctrl->value < 0 || ctrl->value > 127) { | ||
398 | cx25840_err("invalid saturation setting %d\n", | ||
399 | ctrl->value); | ||
400 | return -ERANGE; | ||
401 | } | ||
402 | |||
403 | cx25840_write(client, 0x420, ctrl->value << 1); | ||
404 | cx25840_write(client, 0x421, ctrl->value << 1); | ||
405 | break; | ||
406 | |||
407 | case V4L2_CID_HUE: | ||
408 | if (ctrl->value < -127 || ctrl->value > 127) { | ||
409 | cx25840_err("invalid hue setting %d\n", ctrl->value); | ||
410 | return -ERANGE; | ||
411 | } | ||
412 | |||
413 | cx25840_write(client, 0x422, ctrl->value); | ||
414 | break; | ||
415 | |||
416 | case V4L2_CID_AUDIO_VOLUME: | ||
417 | case V4L2_CID_AUDIO_BASS: | ||
418 | case V4L2_CID_AUDIO_TREBLE: | ||
419 | case V4L2_CID_AUDIO_BALANCE: | ||
420 | case V4L2_CID_AUDIO_MUTE: | ||
421 | return cx25840_audio(client, VIDIOC_S_CTRL, ctrl); | ||
422 | } | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
428 | { | ||
429 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
430 | |||
431 | switch (ctrl->id) { | ||
432 | case CX25840_CID_CARDTYPE: | ||
433 | ctrl->value = state->cardtype; | ||
434 | break; | ||
435 | case V4L2_CID_BRIGHTNESS: | ||
436 | ctrl->value = cx25840_read(client, 0x414) + 128; | ||
437 | break; | ||
438 | case V4L2_CID_CONTRAST: | ||
439 | ctrl->value = cx25840_read(client, 0x415) >> 1; | ||
440 | break; | ||
441 | case V4L2_CID_SATURATION: | ||
442 | ctrl->value = cx25840_read(client, 0x420) >> 1; | ||
443 | break; | ||
444 | case V4L2_CID_HUE: | ||
445 | ctrl->value = cx25840_read(client, 0x422); | ||
446 | break; | ||
447 | case V4L2_CID_AUDIO_VOLUME: | ||
448 | case V4L2_CID_AUDIO_BASS: | ||
449 | case V4L2_CID_AUDIO_TREBLE: | ||
450 | case V4L2_CID_AUDIO_BALANCE: | ||
451 | case V4L2_CID_AUDIO_MUTE: | ||
452 | return cx25840_audio(client, VIDIOC_G_CTRL, ctrl); | ||
453 | default: | ||
454 | return -EINVAL; | ||
455 | } | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | /* ----------------------------------------------------------------------- */ | ||
461 | |||
462 | static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | ||
463 | { | ||
464 | switch (fmt->type) { | ||
465 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
466 | return cx25840_vbi(client, VIDIOC_G_FMT, fmt); | ||
467 | default: | ||
468 | return -EINVAL; | ||
469 | } | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | ||
475 | { | ||
476 | struct v4l2_pix_format *pix; | ||
477 | int HSC, VSC, Vsrc, Hsrc, filter, Vlines; | ||
478 | int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); | ||
479 | |||
480 | switch (fmt->type) { | ||
481 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
482 | pix = &(fmt->fmt.pix); | ||
483 | |||
484 | Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4; | ||
485 | Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4; | ||
486 | |||
487 | Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4; | ||
488 | Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4; | ||
489 | |||
490 | Vlines = pix->height + (is_pal ? 4 : 7); | ||
491 | |||
492 | if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || | ||
493 | (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { | ||
494 | cx25840_err("%dx%d is not a valid size!\n", | ||
495 | pix->width, pix->height); | ||
496 | return -ERANGE; | ||
497 | } | ||
498 | |||
499 | HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20); | ||
500 | VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); | ||
501 | VSC &= 0x1fff; | ||
502 | |||
503 | if (pix->width >= 385) | ||
504 | filter = 0; | ||
505 | else if (pix->width > 192) | ||
506 | filter = 1; | ||
507 | else if (pix->width > 96) | ||
508 | filter = 2; | ||
509 | else | ||
510 | filter = 3; | ||
511 | |||
512 | cx25840_dbg("decoder set size %dx%d -> scale %ux%u\n", | ||
513 | pix->width, pix->height, HSC, VSC); | ||
514 | |||
515 | /* HSCALE=HSC */ | ||
516 | cx25840_write(client, 0x418, HSC & 0xff); | ||
517 | cx25840_write(client, 0x419, (HSC >> 8) & 0xff); | ||
518 | cx25840_write(client, 0x41a, HSC >> 16); | ||
519 | /* VSCALE=VSC */ | ||
520 | cx25840_write(client, 0x41c, VSC & 0xff); | ||
521 | cx25840_write(client, 0x41d, VSC >> 8); | ||
522 | /* VS_INTRLACE=1 VFILT=filter */ | ||
523 | cx25840_write(client, 0x41e, 0x8 | filter); | ||
524 | break; | ||
525 | |||
526 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
527 | return cx25840_vbi(client, VIDIOC_S_FMT, fmt); | ||
528 | |||
529 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
530 | return cx25840_vbi(client, VIDIOC_S_FMT, fmt); | ||
531 | |||
532 | default: | ||
533 | return -EINVAL; | ||
534 | } | ||
535 | |||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | /* ----------------------------------------------------------------------- */ | ||
540 | |||
541 | static int cx25840_command(struct i2c_client *client, unsigned int cmd, | ||
542 | void *arg) | ||
543 | { | ||
544 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
545 | struct v4l2_tuner *vt = arg; | ||
546 | int result = 0; | ||
547 | |||
548 | switch (cmd) { | ||
549 | case 0: | ||
550 | break; | ||
551 | |||
552 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
553 | /* ioctls to allow direct access to the | ||
554 | * cx25840 registers for testing */ | ||
555 | case VIDIOC_INT_G_REGISTER: | ||
556 | { | ||
557 | struct v4l2_register *reg = arg; | ||
558 | |||
559 | if (reg->i2c_id != I2C_DRIVERID_CX25840) | ||
560 | return -EINVAL; | ||
561 | reg->val = cx25840_read(client, reg->reg & 0x0fff); | ||
562 | break; | ||
563 | } | ||
564 | |||
565 | case VIDIOC_INT_S_REGISTER: | ||
566 | { | ||
567 | struct v4l2_register *reg = arg; | ||
568 | |||
569 | if (reg->i2c_id != I2C_DRIVERID_CX25840) | ||
570 | return -EINVAL; | ||
571 | if (!capable(CAP_SYS_ADMIN)) | ||
572 | return -EPERM; | ||
573 | cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); | ||
574 | break; | ||
575 | } | ||
576 | #endif | ||
577 | |||
578 | case VIDIOC_INT_DECODE_VBI_LINE: | ||
579 | return cx25840_vbi(client, cmd, arg); | ||
580 | |||
581 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | ||
582 | case AUDC_SET_INPUT: | ||
583 | result = cx25840_audio(client, cmd, arg); | ||
584 | break; | ||
585 | |||
586 | case VIDIOC_STREAMON: | ||
587 | cx25840_dbg("enable output\n"); | ||
588 | cx25840_write(client, 0x115, 0x8c); | ||
589 | cx25840_write(client, 0x116, 0x07); | ||
590 | break; | ||
591 | |||
592 | case VIDIOC_STREAMOFF: | ||
593 | cx25840_dbg("disable output\n"); | ||
594 | cx25840_write(client, 0x115, 0x00); | ||
595 | cx25840_write(client, 0x116, 0x00); | ||
596 | break; | ||
597 | |||
598 | case VIDIOC_LOG_STATUS: | ||
599 | log_status(client); | ||
600 | break; | ||
601 | |||
602 | case VIDIOC_G_CTRL: | ||
603 | result = get_v4lctrl(client, (struct v4l2_control *)arg); | ||
604 | break; | ||
605 | |||
606 | case VIDIOC_S_CTRL: | ||
607 | result = set_v4lctrl(client, (struct v4l2_control *)arg); | ||
608 | break; | ||
609 | |||
610 | case VIDIOC_G_STD: | ||
611 | *(v4l2_std_id *)arg = cx25840_get_v4lstd(client); | ||
612 | break; | ||
613 | |||
614 | case VIDIOC_S_STD: | ||
615 | result = set_v4lstd(client, *(v4l2_std_id *)arg); | ||
616 | break; | ||
617 | |||
618 | case VIDIOC_G_INPUT: | ||
619 | *(int *)arg = state->input; | ||
620 | break; | ||
621 | |||
622 | case VIDIOC_S_INPUT: | ||
623 | result = set_input(client, *(int *)arg); | ||
624 | break; | ||
625 | |||
626 | case VIDIOC_S_FREQUENCY: | ||
627 | input_change(client); | ||
628 | break; | ||
629 | |||
630 | case VIDIOC_G_TUNER: | ||
631 | { | ||
632 | u8 mode = cx25840_read(client, 0x804); | ||
633 | u8 pref = cx25840_read(client, 0x809) & 0xf; | ||
634 | u8 vpres = cx25840_read(client, 0x80a) & 0x10; | ||
635 | int val = 0; | ||
636 | |||
637 | vt->capability |= | ||
638 | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | | ||
639 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; | ||
640 | |||
641 | vt->signal = vpres ? 0xffff : 0x0; | ||
642 | |||
643 | /* get rxsubchans and audmode */ | ||
644 | if ((mode & 0xf) == 1) | ||
645 | val |= V4L2_TUNER_SUB_STEREO; | ||
646 | else | ||
647 | val |= V4L2_TUNER_SUB_MONO; | ||
648 | |||
649 | if (mode == 2 || mode == 4) | ||
650 | val |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | ||
651 | |||
652 | if (mode & 0x10) | ||
653 | val |= V4L2_TUNER_SUB_SAP; | ||
654 | |||
655 | vt->rxsubchans = val; | ||
656 | |||
657 | switch (pref) { | ||
658 | case 0: | ||
659 | vt->audmode = V4L2_TUNER_MODE_MONO; | ||
660 | break; | ||
661 | case 1: | ||
662 | case 2: | ||
663 | vt->audmode = V4L2_TUNER_MODE_LANG2; | ||
664 | break; | ||
665 | case 4: | ||
666 | default: | ||
667 | vt->audmode = V4L2_TUNER_MODE_STEREO; | ||
668 | } | ||
669 | break; | ||
670 | } | ||
671 | |||
672 | case VIDIOC_S_TUNER: | ||
673 | switch (vt->audmode) { | ||
674 | case V4L2_TUNER_MODE_MONO: | ||
675 | case V4L2_TUNER_MODE_LANG1: | ||
676 | /* Force PREF_MODE to MONO */ | ||
677 | cx25840_and_or(client, 0x809, ~0xf, 0x00); | ||
678 | break; | ||
679 | case V4L2_TUNER_MODE_STEREO: | ||
680 | /* Force PREF_MODE to STEREO */ | ||
681 | cx25840_and_or(client, 0x809, ~0xf, 0x04); | ||
682 | break; | ||
683 | case V4L2_TUNER_MODE_LANG2: | ||
684 | /* Force PREF_MODE to LANG2 */ | ||
685 | cx25840_and_or(client, 0x809, ~0xf, 0x01); | ||
686 | break; | ||
687 | } | ||
688 | break; | ||
689 | |||
690 | case VIDIOC_G_FMT: | ||
691 | result = get_v4lfmt(client, (struct v4l2_format *)arg); | ||
692 | break; | ||
693 | |||
694 | case VIDIOC_S_FMT: | ||
695 | result = set_v4lfmt(client, (struct v4l2_format *)arg); | ||
696 | break; | ||
697 | |||
698 | case VIDIOC_INT_RESET: | ||
699 | cx25840_initialize(client, 0); | ||
700 | break; | ||
701 | |||
702 | case VIDIOC_INT_G_CHIP_IDENT: | ||
703 | *(enum v4l2_chip_ident *)arg = | ||
704 | V4L2_IDENT_CX25840 + ((cx25840_read(client, 0x100) >> 4) & 0xf); | ||
705 | break; | ||
706 | |||
707 | default: | ||
708 | cx25840_err("invalid ioctl %x\n", cmd); | ||
709 | return -EINVAL; | ||
710 | } | ||
711 | |||
712 | return result; | ||
713 | } | ||
714 | |||
715 | /* ----------------------------------------------------------------------- */ | ||
716 | |||
717 | struct i2c_driver i2c_driver_cx25840; | ||
718 | |||
719 | static int cx25840_detect_client(struct i2c_adapter *adapter, int address, | ||
720 | int kind) | ||
721 | { | ||
722 | struct i2c_client *client; | ||
723 | struct cx25840_state *state; | ||
724 | u16 device_id; | ||
725 | |||
726 | /* Check if the adapter supports the needed features | ||
727 | * Not until kernel version 2.6.11 did the bit-algo | ||
728 | * correctly report that it would do an I2C-level xfer */ | ||
729 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) | ||
730 | return 0; | ||
731 | |||
732 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
733 | if (client == 0) | ||
734 | return -ENOMEM; | ||
735 | |||
736 | memset(client, 0, sizeof(struct i2c_client)); | ||
737 | client->addr = address; | ||
738 | client->adapter = adapter; | ||
739 | client->driver = &i2c_driver_cx25840; | ||
740 | client->flags = I2C_CLIENT_ALLOW_USE; | ||
741 | snprintf(client->name, sizeof(client->name) - 1, "cx25840"); | ||
742 | |||
743 | cx25840_dbg("detecting cx25840 client on address 0x%x\n", address << 1); | ||
744 | |||
745 | device_id = cx25840_read(client, 0x101) << 8; | ||
746 | device_id |= cx25840_read(client, 0x100); | ||
747 | |||
748 | /* The high byte of the device ID should be | ||
749 | * 0x84 if chip is present */ | ||
750 | if ((device_id & 0xff00) != 0x8400) { | ||
751 | cx25840_dbg("cx25840 not found\n"); | ||
752 | kfree(client); | ||
753 | return 0; | ||
754 | } | ||
755 | |||
756 | cx25840_info("cx25%3x-2%x found @ 0x%x (%s)\n", | ||
757 | (device_id & 0xfff0) >> 4, | ||
758 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3, | ||
759 | address << 1, adapter->name); | ||
760 | |||
761 | state = kmalloc(sizeof(struct cx25840_state), GFP_KERNEL); | ||
762 | if (state == NULL) { | ||
763 | kfree(client); | ||
764 | return -ENOMEM; | ||
765 | } | ||
766 | |||
767 | i2c_set_clientdata(client, state); | ||
768 | memset(state, 0, sizeof(struct cx25840_state)); | ||
769 | state->input = CX25840_TUNER; | ||
770 | state->audclk_freq = V4L2_AUDCLK_48_KHZ; | ||
771 | state->audio_input = AUDIO_TUNER; | ||
772 | state->cardtype = CARDTYPE_PVR150; | ||
773 | |||
774 | cx25840_initialize(client, 1); | ||
775 | |||
776 | i2c_attach_client(client); | ||
777 | |||
778 | return 0; | ||
779 | } | ||
780 | |||
781 | static int cx25840_attach_adapter(struct i2c_adapter *adapter) | ||
782 | { | ||
783 | #ifdef I2C_CLASS_TV_ANALOG | ||
784 | if (adapter->class & I2C_CLASS_TV_ANALOG) | ||
785 | #else | ||
786 | if (adapter->id == I2C_HW_B_BT848) | ||
787 | #endif | ||
788 | return i2c_probe(adapter, &addr_data, &cx25840_detect_client); | ||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | static int cx25840_detach_client(struct i2c_client *client) | ||
793 | { | ||
794 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
795 | int err; | ||
796 | |||
797 | err = i2c_detach_client(client); | ||
798 | if (err) { | ||
799 | return err; | ||
800 | } | ||
801 | |||
802 | kfree(state); | ||
803 | kfree(client); | ||
804 | |||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | /* ----------------------------------------------------------------------- */ | ||
809 | |||
810 | struct i2c_driver i2c_driver_cx25840 = { | ||
811 | .name = "cx25840", | ||
812 | |||
813 | .id = I2C_DRIVERID_CX25840, | ||
814 | .flags = I2C_DF_NOTIFY, | ||
815 | |||
816 | .attach_adapter = cx25840_attach_adapter, | ||
817 | .detach_client = cx25840_detach_client, | ||
818 | .command = cx25840_command, | ||
819 | .owner = THIS_MODULE, | ||
820 | }; | ||
821 | |||
822 | |||
823 | static int __init m__init(void) | ||
824 | { | ||
825 | return i2c_add_driver(&i2c_driver_cx25840); | ||
826 | } | ||
827 | |||
828 | static void __exit m__exit(void) | ||
829 | { | ||
830 | i2c_del_driver(&i2c_driver_cx25840); | ||
831 | } | ||
832 | |||
833 | module_init(m__init); | ||
834 | module_exit(m__exit); | ||
835 | |||
836 | /* ----------------------------------------------------------------------- */ | ||
837 | |||
838 | static void log_status(struct i2c_client *client) | ||
839 | { | ||
840 | static const char *const fmt_strs[] = { | ||
841 | "0x0", | ||
842 | "NTSC-M", "NTSC-J", "NTSC-4.43", | ||
843 | "PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60", | ||
844 | "0x9", "0xA", "0xB", | ||
845 | "SECAM", | ||
846 | "0xD", "0xE", "0xF" | ||
847 | }; | ||
848 | |||
849 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
850 | u8 microctrl_vidfmt = cx25840_read(client, 0x80a); | ||
851 | u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf; | ||
852 | u8 gen_stat1 = cx25840_read(client, 0x40d); | ||
853 | u8 download_ctl = cx25840_read(client, 0x803); | ||
854 | u8 mod_det_stat0 = cx25840_read(client, 0x804); | ||
855 | u8 mod_det_stat1 = cx25840_read(client, 0x805); | ||
856 | u8 audio_config = cx25840_read(client, 0x808); | ||
857 | u8 pref_mode = cx25840_read(client, 0x809); | ||
858 | u8 afc0 = cx25840_read(client, 0x80b); | ||
859 | u8 mute_ctl = cx25840_read(client, 0x8d3); | ||
860 | char *p; | ||
861 | |||
862 | cx25840_info("Video signal: %spresent\n", | ||
863 | (microctrl_vidfmt & 0x10) ? "" : "not "); | ||
864 | cx25840_info("Detected format: %s\n", | ||
865 | fmt_strs[gen_stat1 & 0xf]); | ||
866 | |||
867 | switch (mod_det_stat0) { | ||
868 | case 0x00: p = "mono"; break; | ||
869 | case 0x01: p = "stereo"; break; | ||
870 | case 0x02: p = "dual"; break; | ||
871 | case 0x04: p = "tri"; break; | ||
872 | case 0x10: p = "mono with SAP"; break; | ||
873 | case 0x11: p = "stereo with SAP"; break; | ||
874 | case 0x12: p = "dual with SAP"; break; | ||
875 | case 0x14: p = "tri with SAP"; break; | ||
876 | case 0xfe: p = "forced mode"; break; | ||
877 | default: p = "not defined"; | ||
878 | } | ||
879 | cx25840_info("Detected audio mode: %s\n", p); | ||
880 | |||
881 | switch (mod_det_stat1) { | ||
882 | case 0x00: p = "not defined"; break; | ||
883 | case 0x01: p = "EIAJ"; break; | ||
884 | case 0x02: p = "A2-M"; break; | ||
885 | case 0x03: p = "A2-BG"; break; | ||
886 | case 0x04: p = "A2-DK1"; break; | ||
887 | case 0x05: p = "A2-DK2"; break; | ||
888 | case 0x06: p = "A2-DK3"; break; | ||
889 | case 0x07: p = "A1 (6.0 MHz FM Mono)"; break; | ||
890 | case 0x08: p = "AM-L"; break; | ||
891 | case 0x09: p = "NICAM-BG"; break; | ||
892 | case 0x0a: p = "NICAM-DK"; break; | ||
893 | case 0x0b: p = "NICAM-I"; break; | ||
894 | case 0x0c: p = "NICAM-L"; break; | ||
895 | case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break; | ||
896 | case 0x0e: p = "IF FM Radio"; break; | ||
897 | case 0x0f: p = "BTSC"; break; | ||
898 | case 0x10: p = "high-deviation FM"; break; | ||
899 | case 0x11: p = "very high-deviation FM"; break; | ||
900 | case 0xfd: p = "unknown audio standard"; break; | ||
901 | case 0xfe: p = "forced audio standard"; break; | ||
902 | case 0xff: p = "no detected audio standard"; break; | ||
903 | default: p = "not defined"; | ||
904 | } | ||
905 | cx25840_info("Detected audio standard: %s\n", p); | ||
906 | cx25840_info("Audio muted: %s\n", | ||
907 | (mute_ctl & 0x2) ? "yes" : "no"); | ||
908 | cx25840_info("Audio microcontroller: %s\n", | ||
909 | (download_ctl & 0x10) ? "running" : "stopped"); | ||
910 | |||
911 | switch (audio_config >> 4) { | ||
912 | case 0x00: p = "undefined"; break; | ||
913 | case 0x01: p = "BTSC"; break; | ||
914 | case 0x02: p = "EIAJ"; break; | ||
915 | case 0x03: p = "A2-M"; break; | ||
916 | case 0x04: p = "A2-BG"; break; | ||
917 | case 0x05: p = "A2-DK1"; break; | ||
918 | case 0x06: p = "A2-DK2"; break; | ||
919 | case 0x07: p = "A2-DK3"; break; | ||
920 | case 0x08: p = "A1 (6.0 MHz FM Mono)"; break; | ||
921 | case 0x09: p = "AM-L"; break; | ||
922 | case 0x0a: p = "NICAM-BG"; break; | ||
923 | case 0x0b: p = "NICAM-DK"; break; | ||
924 | case 0x0c: p = "NICAM-I"; break; | ||
925 | case 0x0d: p = "NICAM-L"; break; | ||
926 | case 0x0e: p = "FM radio"; break; | ||
927 | case 0x0f: p = "automatic detection"; break; | ||
928 | default: p = "undefined"; | ||
929 | } | ||
930 | cx25840_info("Configured audio standard: %s\n", p); | ||
931 | |||
932 | if ((audio_config >> 4) < 0xF) { | ||
933 | switch (audio_config & 0xF) { | ||
934 | case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break; | ||
935 | case 0x01: p = "MONO2 (LANGUAGE B)"; break; | ||
936 | case 0x02: p = "MONO3 (STEREO forced MONO)"; break; | ||
937 | case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break; | ||
938 | case 0x04: p = "STEREO"; break; | ||
939 | case 0x05: p = "DUAL1 (AB)"; break; | ||
940 | case 0x06: p = "DUAL2 (AC) (FM)"; break; | ||
941 | case 0x07: p = "DUAL3 (BC) (FM)"; break; | ||
942 | case 0x08: p = "DUAL4 (AC) (AM)"; break; | ||
943 | case 0x09: p = "DUAL5 (BC) (AM)"; break; | ||
944 | case 0x0a: p = "SAP"; break; | ||
945 | default: p = "undefined"; | ||
946 | } | ||
947 | cx25840_info("Configured audio mode: %s\n", p); | ||
948 | } else { | ||
949 | switch (audio_config & 0xF) { | ||
950 | case 0x00: p = "BG"; break; | ||
951 | case 0x01: p = "DK1"; break; | ||
952 | case 0x02: p = "DK2"; break; | ||
953 | case 0x03: p = "DK3"; break; | ||
954 | case 0x04: p = "I"; break; | ||
955 | case 0x05: p = "L"; break; | ||
956 | case 0x06: p = "BTSC"; break; | ||
957 | case 0x07: p = "EIAJ"; break; | ||
958 | case 0x08: p = "A2-M"; break; | ||
959 | case 0x09: p = "FM Radio"; break; | ||
960 | case 0x0f: p = "automatic standard and mode detection"; break; | ||
961 | default: p = "undefined"; | ||
962 | } | ||
963 | cx25840_info("Configured audio system: %s\n", p); | ||
964 | } | ||
965 | |||
966 | cx25840_info("Specified standard: %s\n", | ||
967 | vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); | ||
968 | |||
969 | switch (state->input) { | ||
970 | case CX25840_COMPOSITE0: p = "Composite 0"; break; | ||
971 | case CX25840_COMPOSITE1: p = "Composite 1"; break; | ||
972 | case CX25840_SVIDEO0: p = "S-Video 0"; break; | ||
973 | case CX25840_SVIDEO1: p = "S-Video 1"; break; | ||
974 | case CX25840_TUNER: p = "Tuner"; break; | ||
975 | } | ||
976 | cx25840_info("Specified input: %s\n", p); | ||
977 | cx25840_info("Specified audio input: %s\n", | ||
978 | state->audio_input == 0 ? "Tuner" : "External"); | ||
979 | |||
980 | switch (state->audclk_freq) { | ||
981 | case V4L2_AUDCLK_441_KHZ: p = "44.1 kHz"; break; | ||
982 | case V4L2_AUDCLK_48_KHZ: p = "48 kHz"; break; | ||
983 | case V4L2_AUDCLK_32_KHZ: p = "32 kHz"; break; | ||
984 | default: p = "undefined"; | ||
985 | } | ||
986 | cx25840_info("Specified audioclock freq: %s\n", p); | ||
987 | |||
988 | switch (pref_mode & 0xf) { | ||
989 | case 0: p = "mono/language A"; break; | ||
990 | case 1: p = "language B"; break; | ||
991 | case 2: p = "language C"; break; | ||
992 | case 3: p = "analog fallback"; break; | ||
993 | case 4: p = "stereo"; break; | ||
994 | case 5: p = "language AC"; break; | ||
995 | case 6: p = "language BC"; break; | ||
996 | case 7: p = "language AB"; break; | ||
997 | default: p = "undefined"; | ||
998 | } | ||
999 | cx25840_info("Preferred audio mode: %s\n", p); | ||
1000 | |||
1001 | if ((audio_config & 0xf) == 0xf) { | ||
1002 | switch ((afc0 >> 3) & 0x3) { | ||
1003 | case 0: p = "system DK"; break; | ||
1004 | case 1: p = "system L"; break; | ||
1005 | case 2: p = "autodetect"; break; | ||
1006 | default: p = "undefined"; | ||
1007 | } | ||
1008 | cx25840_info("Selected 65 MHz format: %s\n", p); | ||
1009 | |||
1010 | switch (afc0 & 0x7) { | ||
1011 | case 0: p = "chroma"; break; | ||
1012 | case 1: p = "BTSC"; break; | ||
1013 | case 2: p = "EIAJ"; break; | ||
1014 | case 3: p = "A2-M"; break; | ||
1015 | case 4: p = "autodetect"; break; | ||
1016 | default: p = "undefined"; | ||
1017 | } | ||
1018 | cx25840_info("Selected 45 MHz format: %s\n", p); | ||
1019 | } | ||
1020 | } | ||
diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c new file mode 100644 index 000000000000..df9d50a75542 --- /dev/null +++ b/drivers/media/video/cx25840/cx25840-firmware.c | |||
@@ -0,0 +1,167 @@ | |||
1 | /* cx25840 firmware functions | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version 2 | ||
6 | * of the License, or (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/i2c-algo-bit.h> | ||
22 | #include <linux/firmware.h> | ||
23 | #include <media/v4l2-common.h> | ||
24 | |||
25 | #include "cx25840.h" | ||
26 | |||
27 | #define FWFILE "v4l-cx25840.fw" | ||
28 | #define FWSEND 1024 | ||
29 | |||
30 | #define FWDEV(x) &((x)->adapter->dev) | ||
31 | |||
32 | static int fastfw = 1; | ||
33 | static char *firmware = FWFILE; | ||
34 | |||
35 | module_param(fastfw, bool, 0444); | ||
36 | module_param(firmware, charp, 0444); | ||
37 | |||
38 | MODULE_PARM_DESC(fastfw, "Load firmware fast [0=100MHz 1=333MHz (default)]"); | ||
39 | MODULE_PARM_DESC(firmware, "Firmware image [default: " FWFILE "]"); | ||
40 | |||
41 | static inline void set_i2c_delay(struct i2c_client *client, int delay) | ||
42 | { | ||
43 | struct i2c_algo_bit_data *algod = client->adapter->algo_data; | ||
44 | |||
45 | /* We aren't guaranteed to be using algo_bit, | ||
46 | * so avoid the null pointer dereference | ||
47 | * and disable the 'fast firmware load' */ | ||
48 | if (algod) { | ||
49 | algod->udelay = delay; | ||
50 | } else { | ||
51 | fastfw = 0; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | static inline void start_fw_load(struct i2c_client *client) | ||
56 | { | ||
57 | /* DL_ADDR_LB=0 DL_ADDR_HB=0 */ | ||
58 | cx25840_write(client, 0x800, 0x00); | ||
59 | cx25840_write(client, 0x801, 0x00); | ||
60 | // DL_MAP=3 DL_AUTO_INC=0 DL_ENABLE=1 | ||
61 | cx25840_write(client, 0x803, 0x0b); | ||
62 | /* AUTO_INC_DIS=1 */ | ||
63 | cx25840_write(client, 0x000, 0x20); | ||
64 | |||
65 | if (fastfw) | ||
66 | set_i2c_delay(client, 3); | ||
67 | } | ||
68 | |||
69 | static inline void end_fw_load(struct i2c_client *client) | ||
70 | { | ||
71 | if (fastfw) | ||
72 | set_i2c_delay(client, 10); | ||
73 | |||
74 | /* AUTO_INC_DIS=0 */ | ||
75 | cx25840_write(client, 0x000, 0x00); | ||
76 | /* DL_ENABLE=0 */ | ||
77 | cx25840_write(client, 0x803, 0x03); | ||
78 | } | ||
79 | |||
80 | static inline int check_fw_load(struct i2c_client *client, int size) | ||
81 | { | ||
82 | /* DL_ADDR_HB DL_ADDR_LB */ | ||
83 | int s = cx25840_read(client, 0x801) << 8; | ||
84 | s |= cx25840_read(client, 0x800); | ||
85 | |||
86 | if (size != s) { | ||
87 | cx25840_err("firmware %s load failed\n", firmware); | ||
88 | return -EINVAL; | ||
89 | } | ||
90 | |||
91 | cx25840_info("loaded %s firmware (%d bytes)\n", firmware, size); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static inline int fw_write(struct i2c_client *client, u8 * data, int size) | ||
96 | { | ||
97 | if (i2c_master_send(client, data, size) < size) { | ||
98 | |||
99 | if (fastfw) { | ||
100 | cx25840_err("333MHz i2c firmware load failed\n"); | ||
101 | fastfw = 0; | ||
102 | set_i2c_delay(client, 10); | ||
103 | |||
104 | if (i2c_master_send(client, data, size) < size) { | ||
105 | cx25840_err | ||
106 | ("100MHz i2c firmware load failed\n"); | ||
107 | return -ENOSYS; | ||
108 | } | ||
109 | |||
110 | } else { | ||
111 | cx25840_err("firmware load i2c failure\n"); | ||
112 | return -ENOSYS; | ||
113 | } | ||
114 | |||
115 | } | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | int cx25840_loadfw(struct i2c_client *client) | ||
121 | { | ||
122 | const struct firmware *fw = NULL; | ||
123 | u8 buffer[4], *ptr; | ||
124 | int size, send, retval; | ||
125 | |||
126 | if (request_firmware(&fw, firmware, FWDEV(client)) != 0) { | ||
127 | cx25840_err("unable to open firmware %s\n", firmware); | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | |||
131 | start_fw_load(client); | ||
132 | |||
133 | buffer[0] = 0x08; | ||
134 | buffer[1] = 0x02; | ||
135 | buffer[2] = fw->data[0]; | ||
136 | buffer[3] = fw->data[1]; | ||
137 | retval = fw_write(client, buffer, 4); | ||
138 | |||
139 | if (retval < 0) { | ||
140 | release_firmware(fw); | ||
141 | return retval; | ||
142 | } | ||
143 | |||
144 | size = fw->size - 2; | ||
145 | ptr = fw->data; | ||
146 | while (size > 0) { | ||
147 | ptr[0] = 0x08; | ||
148 | ptr[1] = 0x02; | ||
149 | send = size > (FWSEND - 2) ? FWSEND : size + 2; | ||
150 | retval = fw_write(client, ptr, send); | ||
151 | |||
152 | if (retval < 0) { | ||
153 | release_firmware(fw); | ||
154 | return retval; | ||
155 | } | ||
156 | |||
157 | size -= FWSEND - 2; | ||
158 | ptr += FWSEND - 2; | ||
159 | } | ||
160 | |||
161 | end_fw_load(client); | ||
162 | |||
163 | size = fw->size; | ||
164 | release_firmware(fw); | ||
165 | |||
166 | return check_fw_load(client, size); | ||
167 | } | ||
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c new file mode 100644 index 000000000000..13ba4e15ddea --- /dev/null +++ b/drivers/media/video/cx25840/cx25840-vbi.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* cx25840 VBI functions | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version 2 | ||
6 | * of the License, or (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #include <linux/videodev2.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <media/v4l2-common.h> | ||
22 | |||
23 | #include "cx25840.h" | ||
24 | |||
25 | static inline int odd_parity(u8 c) | ||
26 | { | ||
27 | c ^= (c >> 4); | ||
28 | c ^= (c >> 2); | ||
29 | c ^= (c >> 1); | ||
30 | |||
31 | return c & 1; | ||
32 | } | ||
33 | |||
34 | static inline int decode_vps(u8 * dst, u8 * p) | ||
35 | { | ||
36 | static const u8 biphase_tbl[] = { | ||
37 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
38 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
39 | 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96, | ||
40 | 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2, | ||
41 | 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94, | ||
42 | 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0, | ||
43 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
44 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
45 | 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5, | ||
46 | 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1, | ||
47 | 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87, | ||
48 | 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3, | ||
49 | 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85, | ||
50 | 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1, | ||
51 | 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5, | ||
52 | 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1, | ||
53 | 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4, | ||
54 | 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0, | ||
55 | 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86, | ||
56 | 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2, | ||
57 | 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84, | ||
58 | 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0, | ||
59 | 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4, | ||
60 | 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0, | ||
61 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
62 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
63 | 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96, | ||
64 | 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2, | ||
65 | 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94, | ||
66 | 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0, | ||
67 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
68 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
69 | }; | ||
70 | |||
71 | u8 c, err = 0; | ||
72 | int i; | ||
73 | |||
74 | for (i = 0; i < 2 * 13; i += 2) { | ||
75 | err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]]; | ||
76 | c = (biphase_tbl[p[i + 1]] & 0xf) | | ||
77 | ((biphase_tbl[p[i]] & 0xf) << 4); | ||
78 | dst[i / 2] = c; | ||
79 | } | ||
80 | |||
81 | return err & 0xf0; | ||
82 | } | ||
83 | |||
84 | void cx25840_vbi_setup(struct i2c_client *client) | ||
85 | { | ||
86 | v4l2_std_id std = cx25840_get_v4lstd(client); | ||
87 | |||
88 | if (std & ~V4L2_STD_NTSC) { | ||
89 | /* datasheet startup, step 8d */ | ||
90 | cx25840_write(client, 0x49f, 0x11); | ||
91 | |||
92 | cx25840_write(client, 0x470, 0x84); | ||
93 | cx25840_write(client, 0x471, 0x00); | ||
94 | cx25840_write(client, 0x472, 0x2d); | ||
95 | cx25840_write(client, 0x473, 0x5d); | ||
96 | |||
97 | cx25840_write(client, 0x474, 0x24); | ||
98 | cx25840_write(client, 0x475, 0x40); | ||
99 | cx25840_write(client, 0x476, 0x24); | ||
100 | cx25840_write(client, 0x477, 0x28); | ||
101 | |||
102 | cx25840_write(client, 0x478, 0x1f); | ||
103 | cx25840_write(client, 0x479, 0x02); | ||
104 | |||
105 | if (std & V4L2_STD_SECAM) { | ||
106 | cx25840_write(client, 0x47a, 0x80); | ||
107 | cx25840_write(client, 0x47b, 0x00); | ||
108 | cx25840_write(client, 0x47c, 0x5f); | ||
109 | cx25840_write(client, 0x47d, 0x42); | ||
110 | } else { | ||
111 | cx25840_write(client, 0x47a, 0x90); | ||
112 | cx25840_write(client, 0x47b, 0x20); | ||
113 | cx25840_write(client, 0x47c, 0x63); | ||
114 | cx25840_write(client, 0x47d, 0x82); | ||
115 | } | ||
116 | |||
117 | cx25840_write(client, 0x47e, 0x0a); | ||
118 | cx25840_write(client, 0x47f, 0x01); | ||
119 | } else { | ||
120 | /* datasheet startup, step 8d */ | ||
121 | cx25840_write(client, 0x49f, 0x14); | ||
122 | |||
123 | cx25840_write(client, 0x470, 0x7a); | ||
124 | cx25840_write(client, 0x471, 0x00); | ||
125 | cx25840_write(client, 0x472, 0x2d); | ||
126 | cx25840_write(client, 0x473, 0x5b); | ||
127 | |||
128 | cx25840_write(client, 0x474, 0x1a); | ||
129 | cx25840_write(client, 0x475, 0x70); | ||
130 | cx25840_write(client, 0x476, 0x1e); | ||
131 | cx25840_write(client, 0x477, 0x1e); | ||
132 | |||
133 | cx25840_write(client, 0x478, 0x1f); | ||
134 | cx25840_write(client, 0x479, 0x02); | ||
135 | cx25840_write(client, 0x47a, 0x50); | ||
136 | cx25840_write(client, 0x47b, 0x66); | ||
137 | |||
138 | cx25840_write(client, 0x47c, 0x1f); | ||
139 | cx25840_write(client, 0x47d, 0x7c); | ||
140 | cx25840_write(client, 0x47e, 0x08); | ||
141 | cx25840_write(client, 0x47f, 0x00); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | ||
146 | { | ||
147 | struct v4l2_format *fmt; | ||
148 | struct v4l2_sliced_vbi_format *svbi; | ||
149 | |||
150 | switch (cmd) { | ||
151 | case VIDIOC_G_FMT: | ||
152 | { | ||
153 | static u16 lcr2vbi[] = { | ||
154 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ | ||
155 | 0, V4L2_SLICED_WSS_625, 0, /* 4 */ | ||
156 | V4L2_SLICED_CAPTION_525, /* 6 */ | ||
157 | 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ | ||
158 | 0, 0, 0, 0 | ||
159 | }; | ||
160 | int i; | ||
161 | |||
162 | fmt = arg; | ||
163 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
164 | return -EINVAL; | ||
165 | svbi = &fmt->fmt.sliced; | ||
166 | memset(svbi, 0, sizeof(*svbi)); | ||
167 | /* we're done if raw VBI is active */ | ||
168 | if ((cx25840_read(client, 0x404) & 0x10) == 0) | ||
169 | break; | ||
170 | |||
171 | for (i = 7; i <= 23; i++) { | ||
172 | u8 v = cx25840_read(client, 0x424 + i - 7); | ||
173 | |||
174 | svbi->service_lines[0][i] = lcr2vbi[v >> 4]; | ||
175 | svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; | ||
176 | svbi->service_set |= | ||
177 | svbi->service_lines[0][i] | svbi->service_lines[1][i]; | ||
178 | } | ||
179 | break; | ||
180 | } | ||
181 | |||
182 | case VIDIOC_S_FMT: | ||
183 | { | ||
184 | int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); | ||
185 | int vbi_offset = is_pal ? 1 : 0; | ||
186 | int i, x; | ||
187 | u8 lcr[24]; | ||
188 | |||
189 | fmt = arg; | ||
190 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
191 | return -EINVAL; | ||
192 | svbi = &fmt->fmt.sliced; | ||
193 | if (svbi->service_set == 0) { | ||
194 | /* raw VBI */ | ||
195 | memset(svbi, 0, sizeof(*svbi)); | ||
196 | |||
197 | /* Setup VBI */ | ||
198 | cx25840_vbi_setup(client); | ||
199 | |||
200 | /* VBI Offset */ | ||
201 | cx25840_write(client, 0x47f, vbi_offset); | ||
202 | cx25840_write(client, 0x404, 0x2e); | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | for (x = 0; x <= 23; x++) | ||
207 | lcr[x] = 0x00; | ||
208 | |||
209 | /* Setup VBI */ | ||
210 | cx25840_vbi_setup(client); | ||
211 | |||
212 | /* Sliced VBI */ | ||
213 | cx25840_write(client, 0x404, 0x36); /* Ancillery data */ | ||
214 | cx25840_write(client, 0x406, 0x13); | ||
215 | cx25840_write(client, 0x47f, vbi_offset); | ||
216 | |||
217 | if (is_pal) { | ||
218 | for (i = 0; i <= 6; i++) | ||
219 | svbi->service_lines[0][i] = | ||
220 | svbi->service_lines[1][i] = 0; | ||
221 | } else { | ||
222 | for (i = 0; i <= 9; i++) | ||
223 | svbi->service_lines[0][i] = | ||
224 | svbi->service_lines[1][i] = 0; | ||
225 | |||
226 | for (i = 22; i <= 23; i++) | ||
227 | svbi->service_lines[0][i] = | ||
228 | svbi->service_lines[1][i] = 0; | ||
229 | } | ||
230 | |||
231 | for (i = 7; i <= 23; i++) { | ||
232 | for (x = 0; x <= 1; x++) { | ||
233 | switch (svbi->service_lines[1-x][i]) { | ||
234 | case V4L2_SLICED_TELETEXT_B: | ||
235 | lcr[i] |= 1 << (4 * x); | ||
236 | break; | ||
237 | case V4L2_SLICED_WSS_625: | ||
238 | lcr[i] |= 4 << (4 * x); | ||
239 | break; | ||
240 | case V4L2_SLICED_CAPTION_525: | ||
241 | lcr[i] |= 6 << (4 * x); | ||
242 | break; | ||
243 | case V4L2_SLICED_VPS: | ||
244 | lcr[i] |= 9 << (4 * x); | ||
245 | break; | ||
246 | } | ||
247 | } | ||
248 | } | ||
249 | |||
250 | for (x = 1, i = 0x424; i <= 0x434; i++, x++) { | ||
251 | cx25840_write(client, i, lcr[6 + x]); | ||
252 | } | ||
253 | |||
254 | cx25840_write(client, 0x43c, 0x16); | ||
255 | |||
256 | if (is_pal) { | ||
257 | cx25840_write(client, 0x474, 0x2a); | ||
258 | } else { | ||
259 | cx25840_write(client, 0x474, 0x1a + 6); | ||
260 | } | ||
261 | break; | ||
262 | } | ||
263 | |||
264 | case VIDIOC_INT_DECODE_VBI_LINE: | ||
265 | { | ||
266 | struct v4l2_decode_vbi_line *vbi = arg; | ||
267 | u8 *p = vbi->p; | ||
268 | int id1, id2, l, err = 0; | ||
269 | |||
270 | if (p[0] || p[1] != 0xff || p[2] != 0xff || | ||
271 | (p[3] != 0x55 && p[3] != 0x91)) { | ||
272 | vbi->line = vbi->type = 0; | ||
273 | break; | ||
274 | } | ||
275 | |||
276 | p += 4; | ||
277 | id1 = p[-1]; | ||
278 | id2 = p[0] & 0xf; | ||
279 | l = p[2] & 0x3f; | ||
280 | l += 5; | ||
281 | p += 4; | ||
282 | |||
283 | switch (id2) { | ||
284 | case 1: | ||
285 | id2 = V4L2_SLICED_TELETEXT_B; | ||
286 | break; | ||
287 | case 4: | ||
288 | id2 = V4L2_SLICED_WSS_625; | ||
289 | break; | ||
290 | case 6: | ||
291 | id2 = V4L2_SLICED_CAPTION_525; | ||
292 | err = !odd_parity(p[0]) || !odd_parity(p[1]); | ||
293 | break; | ||
294 | case 9: | ||
295 | id2 = V4L2_SLICED_VPS; | ||
296 | if (decode_vps(p, p) != 0) { | ||
297 | err = 1; | ||
298 | } | ||
299 | break; | ||
300 | default: | ||
301 | id2 = 0; | ||
302 | err = 1; | ||
303 | break; | ||
304 | } | ||
305 | |||
306 | vbi->type = err ? 0 : id2; | ||
307 | vbi->line = err ? 0 : l; | ||
308 | vbi->is_second_field = err ? 0 : (id1 == 0x55); | ||
309 | vbi->p = p; | ||
310 | break; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | return 0; | ||
315 | } | ||
diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840.h new file mode 100644 index 000000000000..5c3f0639fb77 --- /dev/null +++ b/drivers/media/video/cx25840/cx25840.h | |||
@@ -0,0 +1,85 @@ | |||
1 | /* cx25840 API header | ||
2 | * | ||
3 | * Copyright (C) 2003-2004 Chris Kennedy | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version 2 | ||
8 | * of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef _CX25840_H_ | ||
21 | #define _CX25840_H_ | ||
22 | |||
23 | |||
24 | #include <linux/videodev2.h> | ||
25 | #include <linux/i2c.h> | ||
26 | |||
27 | extern int cx25840_debug; | ||
28 | |||
29 | #define cx25840_dbg(fmt, arg...) do { if (cx25840_debug) \ | ||
30 | printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ | ||
31 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
32 | |||
33 | #define cx25840_err(fmt, arg...) do { \ | ||
34 | printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ | ||
35 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
36 | |||
37 | #define cx25840_info(fmt, arg...) do { \ | ||
38 | printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ | ||
39 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
40 | |||
41 | #define CX25840_CID_CARDTYPE (V4L2_CID_PRIVATE_BASE+0) | ||
42 | |||
43 | enum cx25840_cardtype { | ||
44 | CARDTYPE_PVR150, | ||
45 | CARDTYPE_PG600 | ||
46 | }; | ||
47 | |||
48 | enum cx25840_input { | ||
49 | CX25840_TUNER, | ||
50 | CX25840_COMPOSITE0, | ||
51 | CX25840_COMPOSITE1, | ||
52 | CX25840_SVIDEO0, | ||
53 | CX25840_SVIDEO1 | ||
54 | }; | ||
55 | |||
56 | struct cx25840_state { | ||
57 | enum cx25840_cardtype cardtype; | ||
58 | enum cx25840_input input; | ||
59 | int audio_input; | ||
60 | enum v4l2_audio_clock_freq audclk_freq; | ||
61 | }; | ||
62 | |||
63 | /* ----------------------------------------------------------------------- */ | ||
64 | /* cx25850-core.c */ | ||
65 | int cx25840_write(struct i2c_client *client, u16 addr, u8 value); | ||
66 | int cx25840_write4(struct i2c_client *client, u16 addr, u32 value); | ||
67 | u8 cx25840_read(struct i2c_client *client, u16 addr); | ||
68 | u32 cx25840_read4(struct i2c_client *client, u16 addr); | ||
69 | int cx25840_and_or(struct i2c_client *client, u16 addr, u8 mask, u8 value); | ||
70 | v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client); | ||
71 | |||
72 | /* ----------------------------------------------------------------------- */ | ||
73 | /* cx25850-firmware.c */ | ||
74 | int cx25840_loadfw(struct i2c_client *client); | ||
75 | |||
76 | /* ----------------------------------------------------------------------- */ | ||
77 | /* cx25850-audio.c */ | ||
78 | int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg); | ||
79 | |||
80 | /* ----------------------------------------------------------------------- */ | ||
81 | /* cx25850-vbi.c */ | ||
82 | void cx25840_vbi_setup(struct i2c_client *client); | ||
83 | int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg); | ||
84 | |||
85 | #endif | ||
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 9cce91ec334b..99ea955f5987 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -439,9 +439,6 @@ static int dvb_register(struct cx8802_dev *dev) | |||
439 | /* Put the analog decoder in standby to keep it quiet */ | 439 | /* Put the analog decoder in standby to keep it quiet */ |
440 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | 440 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); |
441 | 441 | ||
442 | /* Put the analog decoder in standby to keep it quiet */ | ||
443 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | ||
444 | |||
445 | /* register everything */ | 442 | /* register everything */ |
446 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); | 443 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); |
447 | } | 444 | } |
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 32c49df58adc..9b94f77d6fd7 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -120,9 +120,6 @@ static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
120 | if (buf[1]==0xff) | 120 | if (buf[1]==0xff) |
121 | return 0; | 121 | return 0; |
122 | 122 | ||
123 | /* avoid fast reapeating */ | ||
124 | if (buf[1]==ir->old) | ||
125 | return 0; | ||
126 | ir->old=buf[1]; | 123 | ir->old=buf[1]; |
127 | 124 | ||
128 | /* Rearranges bits to the right order */ | 125 | /* Rearranges bits to the right order */ |
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c index ed81934ef3cd..5abfc0fbf6de 100644 --- a/drivers/media/video/ir-kbd-gpio.c +++ b/drivers/media/video/ir-kbd-gpio.c | |||
@@ -221,24 +221,99 @@ static IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = { | |||
221 | [ 24 ] = KEY_MUTE // mute/unmute | 221 | [ 24 ] = KEY_MUTE // mute/unmute |
222 | }; | 222 | }; |
223 | 223 | ||
224 | static IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { | ||
225 | [0x00] = KEY_KP0, | ||
226 | [0x01] = KEY_KP1, | ||
227 | [0x02] = KEY_KP2, | ||
228 | [0x03] = KEY_KP3, | ||
229 | [0x04] = KEY_KP4, | ||
230 | [0x05] = KEY_KP5, | ||
231 | [0x06] = KEY_KP6, | ||
232 | [0x07] = KEY_KP7, | ||
233 | [0x08] = KEY_KP8, | ||
234 | [0x09] = KEY_KP9, | ||
235 | [0x0a] = KEY_TV, | ||
236 | [0x0b] = KEY_AUX, | ||
237 | [0x0c] = KEY_DVD, | ||
238 | [0x0d] = KEY_POWER, | ||
239 | [0x0e] = KEY_MHP, /* labelled 'Picture' */ | ||
240 | [0x0f] = KEY_AUDIO, | ||
241 | [0x10] = KEY_INFO, | ||
242 | [0x11] = KEY_F13, /* 16:9 */ | ||
243 | [0x12] = KEY_F14, /* 14:9 */ | ||
244 | [0x13] = KEY_EPG, | ||
245 | [0x14] = KEY_EXIT, | ||
246 | [0x15] = KEY_MENU, | ||
247 | [0x16] = KEY_UP, | ||
248 | [0x17] = KEY_DOWN, | ||
249 | [0x18] = KEY_LEFT, | ||
250 | [0x19] = KEY_RIGHT, | ||
251 | [0x1a] = KEY_ENTER, | ||
252 | [0x1b] = KEY_CHANNELUP, | ||
253 | [0x1c] = KEY_CHANNELDOWN, | ||
254 | [0x1d] = KEY_VOLUMEUP, | ||
255 | [0x1e] = KEY_VOLUMEDOWN, | ||
256 | [0x1f] = KEY_RED, | ||
257 | [0x20] = KEY_GREEN, | ||
258 | [0x21] = KEY_YELLOW, | ||
259 | [0x22] = KEY_BLUE, | ||
260 | [0x23] = KEY_SUBTITLE, | ||
261 | [0x24] = KEY_F15, /* AD */ | ||
262 | [0x25] = KEY_TEXT, | ||
263 | [0x26] = KEY_MUTE, | ||
264 | [0x27] = KEY_REWIND, | ||
265 | [0x28] = KEY_STOP, | ||
266 | [0x29] = KEY_PLAY, | ||
267 | [0x2a] = KEY_FASTFORWARD, | ||
268 | [0x2b] = KEY_F16, /* chapter */ | ||
269 | [0x2c] = KEY_PAUSE, | ||
270 | [0x2d] = KEY_PLAY, | ||
271 | [0x2e] = KEY_RECORD, | ||
272 | [0x2f] = KEY_F17, /* picture in picture */ | ||
273 | [0x30] = KEY_KPPLUS, /* zoom in */ | ||
274 | [0x31] = KEY_KPMINUS, /* zoom out */ | ||
275 | [0x32] = KEY_F18, /* capture */ | ||
276 | [0x33] = KEY_F19, /* web */ | ||
277 | [0x34] = KEY_EMAIL, | ||
278 | [0x35] = KEY_PHONE, | ||
279 | [0x36] = KEY_PC | ||
280 | }; | ||
281 | |||
224 | struct IR { | 282 | struct IR { |
225 | struct bttv_sub_device *sub; | 283 | struct bttv_sub_device *sub; |
226 | struct input_dev *input; | 284 | struct input_dev *input; |
227 | struct ir_input_state ir; | 285 | struct ir_input_state ir; |
228 | char name[32]; | 286 | char name[32]; |
229 | char phys[32]; | 287 | char phys[32]; |
288 | |||
289 | /* Usual gpio signalling */ | ||
290 | |||
230 | u32 mask_keycode; | 291 | u32 mask_keycode; |
231 | u32 mask_keydown; | 292 | u32 mask_keydown; |
232 | u32 mask_keyup; | 293 | u32 mask_keyup; |
233 | 294 | u32 polling; | |
234 | int polling; | ||
235 | u32 last_gpio; | 295 | u32 last_gpio; |
236 | struct work_struct work; | 296 | struct work_struct work; |
237 | struct timer_list timer; | 297 | struct timer_list timer; |
298 | |||
299 | /* RC5 gpio */ | ||
300 | |||
301 | u32 rc5_gpio; | ||
302 | struct timer_list timer_end; /* timer_end for code completion */ | ||
303 | struct timer_list timer_keyup; /* timer_end for key release */ | ||
304 | u32 last_rc5; /* last good rc5 code */ | ||
305 | u32 last_bit; /* last raw bit seen */ | ||
306 | u32 code; /* raw code under construction */ | ||
307 | struct timeval base_time; /* time of last seen code */ | ||
308 | int active; /* building raw code */ | ||
238 | }; | 309 | }; |
239 | 310 | ||
240 | static int debug; | 311 | static int debug; |
241 | module_param(debug, int, 0644); /* debug level (0,1,2) */ | 312 | module_param(debug, int, 0644); /* debug level (0,1,2) */ |
313 | static int repeat_delay = 500; | ||
314 | module_param(repeat_delay, int, 0644); | ||
315 | static int repeat_period = 33; | ||
316 | module_param(repeat_period, int, 0644); | ||
242 | 317 | ||
243 | #define DEVNAME "ir-kbd-gpio" | 318 | #define DEVNAME "ir-kbd-gpio" |
244 | #define dprintk(fmt, arg...) if (debug) \ | 319 | #define dprintk(fmt, arg...) if (debug) \ |
@@ -254,7 +329,7 @@ static struct bttv_sub_driver driver = { | |||
254 | .probe = ir_probe, | 329 | .probe = ir_probe, |
255 | .remove = ir_remove, | 330 | .remove = ir_remove, |
256 | }, | 331 | }, |
257 | .gpio_irq = ir_irq, | 332 | .gpio_irq = ir_irq, |
258 | }; | 333 | }; |
259 | 334 | ||
260 | /* ---------------------------------------------------------------------- */ | 335 | /* ---------------------------------------------------------------------- */ |
@@ -327,6 +402,173 @@ static void ir_work(void *data) | |||
327 | mod_timer(&ir->timer, timeout); | 402 | mod_timer(&ir->timer, timeout); |
328 | } | 403 | } |
329 | 404 | ||
405 | /* ---------------------------------------------------------------*/ | ||
406 | |||
407 | static int rc5_remote_gap = 885; | ||
408 | module_param(rc5_remote_gap, int, 0644); | ||
409 | static int rc5_key_timeout = 200; | ||
410 | module_param(rc5_key_timeout, int, 0644); | ||
411 | |||
412 | #define RC5_START(x) (((x)>>12)&3) | ||
413 | #define RC5_TOGGLE(x) (((x)>>11)&1) | ||
414 | #define RC5_ADDR(x) (((x)>>6)&31) | ||
415 | #define RC5_INSTR(x) ((x)&63) | ||
416 | |||
417 | /* decode raw bit pattern to RC5 code */ | ||
418 | static u32 rc5_decode(unsigned int code) | ||
419 | { | ||
420 | unsigned int org_code = code; | ||
421 | unsigned int pair; | ||
422 | unsigned int rc5 = 0; | ||
423 | int i; | ||
424 | |||
425 | code = (code << 1) | 1; | ||
426 | for (i = 0; i < 14; ++i) { | ||
427 | pair = code & 0x3; | ||
428 | code >>= 2; | ||
429 | |||
430 | rc5 <<= 1; | ||
431 | switch (pair) { | ||
432 | case 0: | ||
433 | case 2: | ||
434 | break; | ||
435 | case 1: | ||
436 | rc5 |= 1; | ||
437 | break; | ||
438 | case 3: | ||
439 | dprintk("bad code: %x\n", org_code); | ||
440 | return 0; | ||
441 | } | ||
442 | } | ||
443 | dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " | ||
444 | "instr=%x\n", rc5, org_code, RC5_START(rc5), | ||
445 | RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); | ||
446 | return rc5; | ||
447 | } | ||
448 | |||
449 | static int ir_rc5_irq(struct bttv_sub_device *sub) | ||
450 | { | ||
451 | struct IR *ir = dev_get_drvdata(&sub->dev); | ||
452 | struct timeval tv; | ||
453 | u32 gpio; | ||
454 | u32 gap; | ||
455 | unsigned long current_jiffies, timeout; | ||
456 | |||
457 | /* read gpio port */ | ||
458 | gpio = bttv_gpio_read(ir->sub->core); | ||
459 | |||
460 | /* remote IRQ? */ | ||
461 | if (!(gpio & 0x20)) | ||
462 | return 0; | ||
463 | |||
464 | /* get time of bit */ | ||
465 | current_jiffies = jiffies; | ||
466 | do_gettimeofday(&tv); | ||
467 | |||
468 | /* avoid overflow with gap >1s */ | ||
469 | if (tv.tv_sec - ir->base_time.tv_sec > 1) { | ||
470 | gap = 200000; | ||
471 | } else { | ||
472 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | ||
473 | tv.tv_usec - ir->base_time.tv_usec; | ||
474 | } | ||
475 | |||
476 | /* active code => add bit */ | ||
477 | if (ir->active) { | ||
478 | /* only if in the code (otherwise spurious IRQ or timer | ||
479 | late) */ | ||
480 | if (ir->last_bit < 28) { | ||
481 | ir->last_bit = (gap - rc5_remote_gap / 2) / | ||
482 | rc5_remote_gap; | ||
483 | ir->code |= 1 << ir->last_bit; | ||
484 | } | ||
485 | /* starting new code */ | ||
486 | } else { | ||
487 | ir->active = 1; | ||
488 | ir->code = 0; | ||
489 | ir->base_time = tv; | ||
490 | ir->last_bit = 0; | ||
491 | |||
492 | timeout = current_jiffies + (500 + 30 * HZ) / 1000; | ||
493 | mod_timer(&ir->timer_end, timeout); | ||
494 | } | ||
495 | |||
496 | /* toggle GPIO pin 4 to reset the irq */ | ||
497 | bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4)); | ||
498 | bttv_gpio_write(ir->sub->core, gpio | (1 << 4)); | ||
499 | return 1; | ||
500 | } | ||
501 | |||
502 | static void ir_rc5_timer_end(unsigned long data) | ||
503 | { | ||
504 | struct IR *ir = (struct IR *)data; | ||
505 | struct timeval tv; | ||
506 | unsigned long current_jiffies, timeout; | ||
507 | u32 gap; | ||
508 | |||
509 | /* get time */ | ||
510 | current_jiffies = jiffies; | ||
511 | do_gettimeofday(&tv); | ||
512 | |||
513 | /* avoid overflow with gap >1s */ | ||
514 | if (tv.tv_sec - ir->base_time.tv_sec > 1) { | ||
515 | gap = 200000; | ||
516 | } else { | ||
517 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | ||
518 | tv.tv_usec - ir->base_time.tv_usec; | ||
519 | } | ||
520 | |||
521 | /* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */ | ||
522 | if (gap < 28000) { | ||
523 | dprintk("spurious timer_end\n"); | ||
524 | return; | ||
525 | } | ||
526 | |||
527 | ir->active = 0; | ||
528 | if (ir->last_bit < 20) { | ||
529 | /* ignore spurious codes (caused by light/other remotes) */ | ||
530 | dprintk("short code: %x\n", ir->code); | ||
531 | } else { | ||
532 | u32 rc5 = rc5_decode(ir->code); | ||
533 | |||
534 | /* two start bits? */ | ||
535 | if (RC5_START(rc5) != 3) { | ||
536 | dprintk("rc5 start bits invalid: %u\n", RC5_START(rc5)); | ||
537 | |||
538 | /* right address? */ | ||
539 | } else if (RC5_ADDR(rc5) == 0x0) { | ||
540 | u32 toggle = RC5_TOGGLE(rc5); | ||
541 | u32 instr = RC5_INSTR(rc5); | ||
542 | |||
543 | /* Good code, decide if repeat/repress */ | ||
544 | if (toggle != RC5_TOGGLE(ir->last_rc5) || | ||
545 | instr != RC5_INSTR(ir->last_rc5)) { | ||
546 | dprintk("instruction %x, toggle %x\n", instr, | ||
547 | toggle); | ||
548 | ir_input_nokey(ir->input, &ir->ir); | ||
549 | ir_input_keydown(ir->input, &ir->ir, instr, | ||
550 | instr); | ||
551 | } | ||
552 | |||
553 | /* Set/reset key-up timer */ | ||
554 | timeout = current_jiffies + (500 + rc5_key_timeout | ||
555 | * HZ) / 1000; | ||
556 | mod_timer(&ir->timer_keyup, timeout); | ||
557 | |||
558 | /* Save code for repeat test */ | ||
559 | ir->last_rc5 = rc5; | ||
560 | } | ||
561 | } | ||
562 | } | ||
563 | |||
564 | static void ir_rc5_timer_keyup(unsigned long data) | ||
565 | { | ||
566 | struct IR *ir = (struct IR *)data; | ||
567 | |||
568 | dprintk("key released\n"); | ||
569 | ir_input_nokey(ir->input, &ir->ir); | ||
570 | } | ||
571 | |||
330 | /* ---------------------------------------------------------------------- */ | 572 | /* ---------------------------------------------------------------------- */ |
331 | 573 | ||
332 | static int ir_probe(struct device *dev) | 574 | static int ir_probe(struct device *dev) |
@@ -400,6 +642,12 @@ static int ir_probe(struct device *dev) | |||
400 | ir->mask_keyup = 0x006000; | 642 | ir->mask_keyup = 0x006000; |
401 | ir->polling = 50; // ms | 643 | ir->polling = 50; // ms |
402 | break; | 644 | break; |
645 | case BTTV_BOARD_NEBULA_DIGITV: | ||
646 | ir_codes = ir_codes_nebula; | ||
647 | driver.any_irq = ir_rc5_irq; | ||
648 | driver.gpio_irq = NULL; | ||
649 | ir->rc5_gpio = 1; | ||
650 | break; | ||
403 | } | 651 | } |
404 | if (NULL == ir_codes) { | 652 | if (NULL == ir_codes) { |
405 | kfree(ir); | 653 | kfree(ir); |
@@ -407,9 +655,17 @@ static int ir_probe(struct device *dev) | |||
407 | return -ENODEV; | 655 | return -ENODEV; |
408 | } | 656 | } |
409 | 657 | ||
410 | /* init hardware-specific stuff */ | 658 | if (ir->rc5_gpio) { |
411 | bttv_gpio_inout(sub->core, ir->mask_keycode | ir->mask_keydown, 0); | 659 | u32 gpio; |
412 | ir->sub = sub; | 660 | /* enable remote irq */ |
661 | bttv_gpio_inout(sub->core, (1 << 4), 1 << 4); | ||
662 | gpio = bttv_gpio_read(sub->core); | ||
663 | bttv_gpio_write(sub->core, gpio & ~(1 << 4)); | ||
664 | bttv_gpio_write(sub->core, gpio | (1 << 4)); | ||
665 | } else { | ||
666 | /* init hardware-specific stuff */ | ||
667 | bttv_gpio_inout(sub->core, ir->mask_keycode | ir->mask_keydown, 0); | ||
668 | } | ||
413 | 669 | ||
414 | /* init input device */ | 670 | /* init input device */ |
415 | snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)", | 671 | snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)", |
@@ -417,6 +673,7 @@ static int ir_probe(struct device *dev) | |||
417 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", | 673 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", |
418 | pci_name(sub->core->pci)); | 674 | pci_name(sub->core->pci)); |
419 | 675 | ||
676 | ir->sub = sub; | ||
420 | ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); | 677 | ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); |
421 | input_dev->name = ir->name; | 678 | input_dev->name = ir->name; |
422 | input_dev->phys = ir->phys; | 679 | input_dev->phys = ir->phys; |
@@ -437,11 +694,25 @@ static int ir_probe(struct device *dev) | |||
437 | ir->timer.function = ir_timer; | 694 | ir->timer.function = ir_timer; |
438 | ir->timer.data = (unsigned long)ir; | 695 | ir->timer.data = (unsigned long)ir; |
439 | schedule_work(&ir->work); | 696 | schedule_work(&ir->work); |
697 | } else if (ir->rc5_gpio) { | ||
698 | /* set timer_end for code completion */ | ||
699 | init_timer(&ir->timer_end); | ||
700 | ir->timer_end.function = ir_rc5_timer_end; | ||
701 | ir->timer_end.data = (unsigned long)ir; | ||
702 | |||
703 | init_timer(&ir->timer_keyup); | ||
704 | ir->timer_keyup.function = ir_rc5_timer_keyup; | ||
705 | ir->timer_keyup.data = (unsigned long)ir; | ||
440 | } | 706 | } |
441 | 707 | ||
442 | /* all done */ | 708 | /* all done */ |
443 | dev_set_drvdata(dev, ir); | 709 | dev_set_drvdata(dev, ir); |
444 | input_register_device(ir->input); | 710 | input_register_device(ir->input); |
711 | printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys); | ||
712 | |||
713 | /* the remote isn't as bouncy as a keyboard */ | ||
714 | ir->input->rep[REP_DELAY] = repeat_delay; | ||
715 | ir->input->rep[REP_PERIOD] = repeat_period; | ||
445 | 716 | ||
446 | return 0; | 717 | return 0; |
447 | } | 718 | } |
@@ -454,6 +725,15 @@ static int ir_remove(struct device *dev) | |||
454 | del_timer(&ir->timer); | 725 | del_timer(&ir->timer); |
455 | flush_scheduled_work(); | 726 | flush_scheduled_work(); |
456 | } | 727 | } |
728 | if (ir->rc5_gpio) { | ||
729 | u32 gpio; | ||
730 | |||
731 | del_timer(&ir->timer_end); | ||
732 | flush_scheduled_work(); | ||
733 | |||
734 | gpio = bttv_gpio_read(ir->sub->core); | ||
735 | bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4)); | ||
736 | } | ||
457 | 737 | ||
458 | input_unregister_device(ir->input); | 738 | input_unregister_device(ir->input); |
459 | kfree(ir); | 739 | kfree(ir); |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 0085567a1421..801c736e9328 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -183,6 +183,58 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
183 | return 1; | 183 | return 1; |
184 | } | 184 | } |
185 | 185 | ||
186 | /* The new pinnacle PCTV remote (with the colored buttons) | ||
187 | * | ||
188 | * Ricardo Cerqueira <v4l@cerqueira.org> | ||
189 | */ | ||
190 | |||
191 | int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
192 | { | ||
193 | unsigned char b[4]; | ||
194 | unsigned int start = 0,parity = 0,code = 0; | ||
195 | |||
196 | /* poll IR chip */ | ||
197 | if (4 != i2c_master_recv(&ir->c,b,4)) { | ||
198 | dprintk(2,"read error\n"); | ||
199 | return -EIO; | ||
200 | } | ||
201 | |||
202 | for (start = 0; start<4; start++) { | ||
203 | if (b[start] == 0x80) { | ||
204 | code=b[(start+3)%4]; | ||
205 | parity=b[(start+2)%4]; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | /* Empty Request */ | ||
210 | if (parity==0) | ||
211 | return 0; | ||
212 | |||
213 | /* Repeating... */ | ||
214 | if (ir->old == parity) | ||
215 | return 0; | ||
216 | |||
217 | |||
218 | ir->old = parity; | ||
219 | |||
220 | /* Reduce code value to fit inside IR_KEYTAB_SIZE | ||
221 | * | ||
222 | * this is the only value that results in 42 unique | ||
223 | * codes < 128 | ||
224 | */ | ||
225 | |||
226 | code %= 0x88; | ||
227 | |||
228 | *ir_raw = code; | ||
229 | *ir_key = code; | ||
230 | |||
231 | dprintk(1,"Pinnacle PCTV key %02x\n", code); | ||
232 | |||
233 | return 1; | ||
234 | } | ||
235 | |||
236 | EXPORT_SYMBOL_GPL(get_key_pinnacle); | ||
237 | |||
186 | /* ----------------------------------------------------------------------- */ | 238 | /* ----------------------------------------------------------------------- */ |
187 | 239 | ||
188 | static void ir_key_poll(struct IR_i2c *ir) | 240 | static void ir_key_poll(struct IR_i2c *ir) |
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c new file mode 100644 index 000000000000..0235cef07b31 --- /dev/null +++ b/drivers/media/video/saa7115.c | |||
@@ -0,0 +1,1376 @@ | |||
1 | /* saa7115 - Philips SAA7114/SAA7115 video decoder driver | ||
2 | * | ||
3 | * Based on saa7114 driver by Maxim Yevtyushkin, which is based on | ||
4 | * the saa7111 driver by Dave Perks. | ||
5 | * | ||
6 | * Copyright (C) 1998 Dave Perks <dperks@ibm.net> | ||
7 | * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com> | ||
8 | * | ||
9 | * Slight changes for video timing and attachment output by | ||
10 | * Wolfgang Scherr <scherr@net4you.net> | ||
11 | * | ||
12 | * Moved over to the linux >= 2.4.x i2c protocol (1/1/2003) | ||
13 | * by Ronald Bultje <rbultje@ronald.bitfreak.net> | ||
14 | * | ||
15 | * Added saa7115 support by Kevin Thayer <nufan_wfk at yahoo.com> | ||
16 | * (2/17/2003) | ||
17 | * | ||
18 | * VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl> | ||
19 | * | ||
20 | * This program is free software; you can redistribute it and/or | ||
21 | * modify it under the terms of the GNU General Public License | ||
22 | * as published by the Free Software Foundation; either version 2 | ||
23 | * of the License, or (at your option) any later version. | ||
24 | * | ||
25 | * This program is distributed in the hope that it will be useful, | ||
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
28 | * GNU General Public License for more details. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License | ||
31 | * along with this program; if not, write to the Free Software | ||
32 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
33 | */ | ||
34 | |||
35 | |||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/i2c.h> | ||
40 | #include <linux/videodev2.h> | ||
41 | #include <media/v4l2-common.h> | ||
42 | |||
43 | MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver"); | ||
44 | MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil"); | ||
45 | MODULE_LICENSE("GPL"); | ||
46 | |||
47 | static int debug = 0; | ||
48 | module_param(debug, int, 0644); | ||
49 | |||
50 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | ||
51 | |||
52 | #define saa7115_dbg(fmt,arg...) \ | ||
53 | do { \ | ||
54 | if (debug) \ | ||
55 | printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ | ||
56 | i2c_adapter_id(client->adapter), client->addr , ## arg); \ | ||
57 | } while (0) | ||
58 | |||
59 | #define saa7115_err(fmt, arg...) do { \ | ||
60 | printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ | ||
61 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
62 | #define saa7115_info(fmt, arg...) do { \ | ||
63 | printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ | ||
64 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
65 | |||
66 | static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END }; | ||
67 | |||
68 | |||
69 | I2C_CLIENT_INSMOD; | ||
70 | |||
71 | struct saa7115_state { | ||
72 | v4l2_std_id std; | ||
73 | int input; | ||
74 | int enable; | ||
75 | int bright; | ||
76 | int contrast; | ||
77 | int hue; | ||
78 | int sat; | ||
79 | enum v4l2_chip_ident ident; | ||
80 | enum v4l2_audio_clock_freq audclk_freq; | ||
81 | }; | ||
82 | |||
83 | /* ----------------------------------------------------------------------- */ | ||
84 | |||
85 | static inline int saa7115_write(struct i2c_client *client, u8 reg, u8 value) | ||
86 | { | ||
87 | return i2c_smbus_write_byte_data(client, reg, value); | ||
88 | } | ||
89 | |||
90 | static int saa7115_writeregs(struct i2c_client *client, const unsigned char *regs) | ||
91 | { | ||
92 | unsigned char reg, data; | ||
93 | |||
94 | while (*regs != 0x00) { | ||
95 | reg = *(regs++); | ||
96 | data = *(regs++); | ||
97 | if (saa7115_write(client, reg, data) < 0) | ||
98 | return -1; | ||
99 | } | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static inline int saa7115_read(struct i2c_client *client, u8 reg) | ||
104 | { | ||
105 | return i2c_smbus_read_byte_data(client, reg); | ||
106 | } | ||
107 | |||
108 | /* ----------------------------------------------------------------------- */ | ||
109 | |||
110 | /* If a value differs from the Hauppauge driver values, then the comment starts with | ||
111 | 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the | ||
112 | Hauppauge driver sets. */ | ||
113 | |||
114 | static const unsigned char saa7115_init_auto_input[] = { | ||
115 | 0x01, 0x48, /* white peak control disabled */ | ||
116 | 0x03, 0x20, /* was 0x30. 0x20: long vertical blanking */ | ||
117 | 0x04, 0x90, /* analog gain set to 0 */ | ||
118 | 0x05, 0x90, /* analog gain set to 0 */ | ||
119 | 0x06, 0xeb, /* horiz sync begin = -21 */ | ||
120 | 0x07, 0xe0, /* horiz sync stop = -17 */ | ||
121 | 0x0a, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */ | ||
122 | 0x0b, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */ | ||
123 | 0x0c, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */ | ||
124 | 0x0d, 0x00, /* chrominance hue control */ | ||
125 | 0x0f, 0x00, /* chrominance gain control: use automicatic mode */ | ||
126 | 0x10, 0x06, /* chrominance/luminance control: active adaptive combfilter */ | ||
127 | 0x11, 0x00, /* delay control */ | ||
128 | 0x12, 0x9d, /* RTS0 output control: VGATE */ | ||
129 | 0x13, 0x80, /* X-port output control: ITU656 standard mode, RTCO output enable RTCE */ | ||
130 | 0x14, 0x00, /* analog/ADC/auto compatibility control */ | ||
131 | 0x18, 0x40, /* raw data gain 0x00 = nominal */ | ||
132 | 0x19, 0x80, /* raw data offset 0x80 = 0 LSB */ | ||
133 | 0x1a, 0x77, /* color killer level control 0x77 = recommended */ | ||
134 | 0x1b, 0x42, /* misc chroma control 0x42 = recommended */ | ||
135 | 0x1c, 0xa9, /* combfilter control 0xA9 = recommended */ | ||
136 | 0x1d, 0x01, /* combfilter control 0x01 = recommended */ | ||
137 | 0x88, 0xd0, /* reset device */ | ||
138 | 0x88, 0xf0, /* set device programmed, all in operational mode */ | ||
139 | 0x00, 0x00 | ||
140 | }; | ||
141 | |||
142 | static const unsigned char saa7115_cfg_reset_scaler[] = { | ||
143 | 0x87, 0x00, /* disable I-port output */ | ||
144 | 0x88, 0xd0, /* reset scaler */ | ||
145 | 0x88, 0xf0, /* activate scaler */ | ||
146 | 0x87, 0x01, /* enable I-port output */ | ||
147 | 0x00, 0x00 | ||
148 | }; | ||
149 | |||
150 | /* ============== SAA7715 VIDEO templates ============= */ | ||
151 | |||
152 | static const unsigned char saa7115_cfg_60hz_fullres_x[] = { | ||
153 | 0xcc, 0xd0, /* hsize low (output), hor. output window size = 0x2d0 = 720 */ | ||
154 | 0xcd, 0x02, /* hsize hi (output) */ | ||
155 | |||
156 | /* Why not in 60hz-Land, too? */ | ||
157 | 0xd0, 0x01, /* downscale = 1 */ | ||
158 | 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */ | ||
159 | 0xd9, 0x04, | ||
160 | 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */ | ||
161 | 0xdd, 0x02, /* H-scaling incr chroma */ | ||
162 | |||
163 | 0x00, 0x00 | ||
164 | }; | ||
165 | static const unsigned char saa7115_cfg_60hz_fullres_y[] = { | ||
166 | 0xce, 0xf8, /* vsize low (output), ver. output window size = 248 (but 60hz is 240?) */ | ||
167 | 0xcf, 0x00, /* vsize hi (output) */ | ||
168 | |||
169 | /* Why not in 60hz-Land, too? */ | ||
170 | 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */ | ||
171 | 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */ | ||
172 | |||
173 | 0xe0, 0x00, /* V-scaling incr luma low */ | ||
174 | 0xe1, 0x04, /* " hi */ | ||
175 | 0xe2, 0x00, /* V-scaling incr chroma low */ | ||
176 | 0xe3, 0x04, /* " hi */ | ||
177 | |||
178 | 0x00, 0x00 | ||
179 | }; | ||
180 | |||
181 | static const unsigned char saa7115_cfg_60hz_video[] = { | ||
182 | 0x80, 0x00, /* reset tasks */ | ||
183 | 0x88, 0xd0, /* reset scaler */ | ||
184 | |||
185 | 0x15, 0x03, /* VGATE pulse start */ | ||
186 | 0x16, 0x11, /* VGATE pulse stop */ | ||
187 | 0x17, 0x9c, /* VGATE MSB and other values */ | ||
188 | |||
189 | 0x08, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */ | ||
190 | 0x0e, 0x07, /* lots of different stuff... video autodetection is on */ | ||
191 | |||
192 | 0x5a, 0x06, /* Vertical offset, standard 60hz value for ITU656 line counting */ | ||
193 | |||
194 | /* Task A */ | ||
195 | 0x90, 0x80, /* Task Handling Control */ | ||
196 | 0x91, 0x48, /* X-port formats/config */ | ||
197 | 0x92, 0x40, /* Input Ref. signal Def. */ | ||
198 | 0x93, 0x84, /* I-port config */ | ||
199 | 0x94, 0x01, /* hoffset low (input), 0x0002 is minimum */ | ||
200 | 0x95, 0x00, /* hoffset hi (input) */ | ||
201 | 0x96, 0xd0, /* hsize low (input), 0x02d0 = 720 */ | ||
202 | 0x97, 0x02, /* hsize hi (input) */ | ||
203 | 0x98, 0x05, /* voffset low (input) */ | ||
204 | 0x99, 0x00, /* voffset hi (input) */ | ||
205 | 0x9a, 0x0c, /* vsize low (input), 0x0c = 12 */ | ||
206 | 0x9b, 0x00, /* vsize hi (input) */ | ||
207 | 0x9c, 0xa0, /* hsize low (output), 0x05a0 = 1440 */ | ||
208 | 0x9d, 0x05, /* hsize hi (output) */ | ||
209 | 0x9e, 0x0c, /* vsize low (output), 0x0c = 12 */ | ||
210 | 0x9f, 0x00, /* vsize hi (output) */ | ||
211 | |||
212 | /* Task B */ | ||
213 | 0xc0, 0x00, /* Task Handling Control */ | ||
214 | 0xc1, 0x08, /* X-port formats/config */ | ||
215 | 0xc2, 0x00, /* Input Ref. signal Def. */ | ||
216 | 0xc3, 0x80, /* I-port config */ | ||
217 | 0xc4, 0x02, /* hoffset low (input), 0x0002 is minimum */ | ||
218 | 0xc5, 0x00, /* hoffset hi (input) */ | ||
219 | 0xc6, 0xd0, /* hsize low (input), 0x02d0 = 720 */ | ||
220 | 0xc7, 0x02, /* hsize hi (input) */ | ||
221 | 0xc8, 0x12, /* voffset low (input), 0x12 = 18 */ | ||
222 | 0xc9, 0x00, /* voffset hi (input) */ | ||
223 | 0xca, 0xf8, /* vsize low (input), 0xf8 = 248 */ | ||
224 | 0xcb, 0x00, /* vsize hi (input) */ | ||
225 | 0xcc, 0xd0, /* hsize low (output), 0x02d0 = 720 */ | ||
226 | 0xcd, 0x02, /* hsize hi (output) */ | ||
227 | |||
228 | 0xf0, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */ | ||
229 | 0xf1, 0x05, /* low bit with 0xF0 */ | ||
230 | 0xf5, 0xad, /* Set pulse generator register */ | ||
231 | 0xf6, 0x01, | ||
232 | |||
233 | 0x87, 0x00, /* Disable I-port output */ | ||
234 | 0x88, 0xd0, /* reset scaler */ | ||
235 | 0x80, 0x20, /* Activate only task "B", continuous mode (was 0xA0) */ | ||
236 | 0x88, 0xf0, /* activate scaler */ | ||
237 | 0x87, 0x01, /* Enable I-port output */ | ||
238 | 0x00, 0x00 | ||
239 | }; | ||
240 | |||
241 | static const unsigned char saa7115_cfg_50hz_fullres_x[] = { | ||
242 | 0xcc, 0xd0, /* hsize low (output), 720 same as 60hz */ | ||
243 | 0xcd, 0x02, /* hsize hi (output) */ | ||
244 | |||
245 | 0xd0, 0x01, /* down scale = 1 */ | ||
246 | 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */ | ||
247 | 0xd9, 0x04, | ||
248 | 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */ | ||
249 | 0xdd, 0x02, /* H-scaling incr chroma */ | ||
250 | |||
251 | 0x00, 0x00 | ||
252 | }; | ||
253 | static const unsigned char saa7115_cfg_50hz_fullres_y[] = { | ||
254 | 0xce, 0x20, /* vsize low (output), 0x0120 = 288 */ | ||
255 | 0xcf, 0x01, /* vsize hi (output) */ | ||
256 | |||
257 | 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */ | ||
258 | 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */ | ||
259 | |||
260 | 0xe0, 0x00, /* V-scaling incr luma low */ | ||
261 | 0xe1, 0x04, /* " hi */ | ||
262 | 0xe2, 0x00, /* V-scaling incr chroma low */ | ||
263 | 0xe3, 0x04, /* " hi */ | ||
264 | |||
265 | 0x00, 0x00 | ||
266 | }; | ||
267 | |||
268 | static const unsigned char saa7115_cfg_50hz_video[] = { | ||
269 | 0x80, 0x00, /* reset tasks */ | ||
270 | 0x88, 0xd0, /* reset scaler */ | ||
271 | |||
272 | 0x15, 0x37, /* VGATE start */ | ||
273 | 0x16, 0x16, /* VGATE stop */ | ||
274 | 0x17, 0x99, /* VGATE MSB and other values */ | ||
275 | |||
276 | 0x08, 0x28, /* 0x28 = PAL */ | ||
277 | 0x0e, 0x07, /* chrominance control 1 */ | ||
278 | |||
279 | 0x5a, 0x03, /* Vertical offset, standard 50hz value */ | ||
280 | |||
281 | /* Task A */ | ||
282 | 0x90, 0x81, /* Task Handling Control */ | ||
283 | 0x91, 0x48, /* X-port formats/config */ | ||
284 | 0x92, 0x40, /* Input Ref. signal Def. */ | ||
285 | 0x93, 0x84, /* I-port config */ | ||
286 | /* This is weird: the datasheet says that you should use 2 as the minimum value, */ | ||
287 | /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */ | ||
288 | 0x94, 0x00, /* hoffset low (input), 0x0002 is minimum */ | ||
289 | 0x95, 0x00, /* hoffset hi (input) */ | ||
290 | 0x96, 0xd0, /* hsize low (input), 0x02d0 = 720 */ | ||
291 | 0x97, 0x02, /* hsize hi (input) */ | ||
292 | 0x98, 0x03, /* voffset low (input) */ | ||
293 | 0x99, 0x00, /* voffset hi (input) */ | ||
294 | 0x9a, 0x12, /* vsize low (input), 0x12 = 18 */ | ||
295 | 0x9b, 0x00, /* vsize hi (input) */ | ||
296 | 0x9c, 0xa0, /* hsize low (output), 0x05a0 = 1440 */ | ||
297 | 0x9d, 0x05, /* hsize hi (output) */ | ||
298 | 0x9e, 0x12, /* vsize low (output), 0x12 = 18 */ | ||
299 | 0x9f, 0x00, /* vsize hi (output) */ | ||
300 | |||
301 | /* Task B */ | ||
302 | 0xc0, 0x00, /* Task Handling Control */ | ||
303 | 0xc1, 0x08, /* X-port formats/config */ | ||
304 | 0xc2, 0x00, /* Input Ref. signal Def. */ | ||
305 | 0xc3, 0x80, /* I-port config */ | ||
306 | 0xc4, 0x00, /* hoffset low (input), 0x0002 is minimum. See comment at 0x94 above. */ | ||
307 | 0xc5, 0x00, /* hoffset hi (input) */ | ||
308 | 0xc6, 0xd0, /* hsize low (input), 0x02d0 = 720 */ | ||
309 | 0xc7, 0x02, /* hsize hi (input) */ | ||
310 | 0xc8, 0x16, /* voffset low (input), 0x16 = 22 */ | ||
311 | 0xc9, 0x00, /* voffset hi (input) */ | ||
312 | 0xca, 0x20, /* vsize low (input), 0x0120 = 288 */ | ||
313 | 0xcb, 0x01, /* vsize hi (input) */ | ||
314 | 0xcc, 0xd0, /* hsize low (output), 0x02d0 = 720 */ | ||
315 | 0xcd, 0x02, /* hsize hi (output) */ | ||
316 | 0xce, 0x20, /* vsize low (output), 0x0120 = 288 */ | ||
317 | 0xcf, 0x01, /* vsize hi (output) */ | ||
318 | |||
319 | 0xf0, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */ | ||
320 | 0xf1, 0x05, /* low bit with 0xF0, (was 0x05) */ | ||
321 | 0xf5, 0xb0, /* Set pulse generator register */ | ||
322 | 0xf6, 0x01, | ||
323 | |||
324 | 0x87, 0x00, /* Disable I-port output */ | ||
325 | 0x88, 0xd0, /* reset scaler (was 0xD0) */ | ||
326 | 0x80, 0x20, /* Activate only task "B" */ | ||
327 | 0x88, 0xf0, /* activate scaler */ | ||
328 | 0x87, 0x01, /* Enable I-port output */ | ||
329 | 0x00, 0x00 | ||
330 | }; | ||
331 | |||
332 | /* ============== SAA7715 VIDEO templates (end) ======= */ | ||
333 | |||
334 | static const unsigned char saa7115_cfg_vbi_on[] = { | ||
335 | 0x80, 0x00, /* reset tasks */ | ||
336 | 0x88, 0xd0, /* reset scaler */ | ||
337 | 0x80, 0x30, /* Activate both tasks */ | ||
338 | 0x88, 0xf0, /* activate scaler */ | ||
339 | 0x87, 0x01, /* Enable I-port output */ | ||
340 | 0x00, 0x00 | ||
341 | }; | ||
342 | |||
343 | static const unsigned char saa7115_cfg_vbi_off[] = { | ||
344 | 0x80, 0x00, /* reset tasks */ | ||
345 | 0x88, 0xd0, /* reset scaler */ | ||
346 | 0x80, 0x20, /* Activate only task "B" */ | ||
347 | 0x88, 0xf0, /* activate scaler */ | ||
348 | 0x87, 0x01, /* Enable I-port output */ | ||
349 | 0x00, 0x00 | ||
350 | }; | ||
351 | |||
352 | static const unsigned char saa7115_init_misc[] = { | ||
353 | 0x38, 0x03, /* audio stuff */ | ||
354 | 0x39, 0x10, | ||
355 | 0x3a, 0x08, | ||
356 | |||
357 | 0x81, 0x01, /* reg 0x15,0x16 define blanking window */ | ||
358 | 0x82, 0x00, | ||
359 | 0x83, 0x01, /* I port settings */ | ||
360 | 0x84, 0x20, | ||
361 | 0x85, 0x21, | ||
362 | 0x86, 0xc5, | ||
363 | 0x87, 0x01, | ||
364 | |||
365 | /* Task A */ | ||
366 | 0xa0, 0x01, /* down scale = 1 */ | ||
367 | 0xa1, 0x00, /* prescale accumulation length = 1 */ | ||
368 | 0xa2, 0x00, /* dc gain and fir prefilter control */ | ||
369 | 0xa4, 0x80, /* Lum Brightness, nominal value = 0x80 */ | ||
370 | 0xa5, 0x40, /* Lum contrast, nominal value = 0x40 */ | ||
371 | 0xa6, 0x40, /* Chroma satur. nominal value = 0x80 */ | ||
372 | 0xa8, 0x00, /* hor lum scaling 0x0200 = 2 zoom */ | ||
373 | 0xa9, 0x02, /* note: 2 x zoom ensures that VBI lines have same length as video lines. */ | ||
374 | 0xaa, 0x00, /* H-phase offset Luma = 0 */ | ||
375 | 0xac, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */ | ||
376 | 0xad, 0x01, /* H-scaling incr chroma */ | ||
377 | 0xae, 0x00, /* H-phase offset chroma. must be offset luma / 2 */ | ||
378 | |||
379 | 0xb0, 0x00, /* V-scaling incr luma low */ | ||
380 | 0xb1, 0x04, /* " hi */ | ||
381 | 0xb2, 0x00, /* V-scaling incr chroma low */ | ||
382 | 0xb3, 0x04, /* " hi */ | ||
383 | 0xb4, 0x01, /* V-scaling mode control */ | ||
384 | 0xb8, 0x00, /* V-phase offset chroma 00 */ | ||
385 | 0xb9, 0x00, /* V-phase offset chroma 01 */ | ||
386 | 0xba, 0x00, /* V-phase offset chroma 10 */ | ||
387 | 0xbb, 0x00, /* V-phase offset chroma 11 */ | ||
388 | 0xbc, 0x00, /* V-phase offset luma 00 */ | ||
389 | 0xbd, 0x00, /* V-phase offset luma 01 */ | ||
390 | 0xbe, 0x00, /* V-phase offset luma 10 */ | ||
391 | 0xbf, 0x00, /* V-phase offset luma 11 */ | ||
392 | |||
393 | /* Task B */ | ||
394 | 0xd0, 0x01, /* down scale = 1 */ | ||
395 | 0xd1, 0x00, /* prescale accumulation length = 1 */ | ||
396 | 0xd2, 0x00, /* dc gain and fir prefilter control */ | ||
397 | 0xd4, 0x80, /* Lum Brightness, nominal value = 0x80 */ | ||
398 | 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */ | ||
399 | 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */ | ||
400 | 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */ | ||
401 | 0xd9, 0x04, | ||
402 | 0xda, 0x00, /* H-phase offset Luma = 0 */ | ||
403 | 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */ | ||
404 | 0xdd, 0x02, /* H-scaling incr chroma */ | ||
405 | 0xde, 0x00, /* H-phase offset chroma. must be offset luma / 2 */ | ||
406 | |||
407 | 0xe0, 0x00, /* V-scaling incr luma low */ | ||
408 | 0xe1, 0x04, /* " hi */ | ||
409 | 0xe2, 0x00, /* V-scaling incr chroma low */ | ||
410 | 0xe3, 0x04, /* " hi */ | ||
411 | 0xe4, 0x01, /* V-scaling mode control */ | ||
412 | 0xe8, 0x00, /* V-phase offset chroma 00 */ | ||
413 | 0xe9, 0x00, /* V-phase offset chroma 01 */ | ||
414 | 0xea, 0x00, /* V-phase offset chroma 10 */ | ||
415 | 0xeb, 0x00, /* V-phase offset chroma 11 */ | ||
416 | 0xec, 0x00, /* V-phase offset luma 00 */ | ||
417 | 0xed, 0x00, /* V-phase offset luma 01 */ | ||
418 | 0xee, 0x00, /* V-phase offset luma 10 */ | ||
419 | 0xef, 0x00, /* V-phase offset luma 11 */ | ||
420 | |||
421 | 0xf2, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */ | ||
422 | 0xf3, 0x46, | ||
423 | 0xf4, 0x00, | ||
424 | 0xf7, 0x4b, /* not the recommended settings! */ | ||
425 | 0xf8, 0x00, | ||
426 | 0xf9, 0x4b, | ||
427 | 0xfa, 0x00, | ||
428 | 0xfb, 0x4b, | ||
429 | 0xff, 0x88, /* PLL2 lock detection settings: 71 lines 50% phase error */ | ||
430 | |||
431 | /* Turn off VBI */ | ||
432 | 0x40, 0x20, /* No framing code errors allowed. */ | ||
433 | 0x41, 0xff, | ||
434 | 0x42, 0xff, | ||
435 | 0x43, 0xff, | ||
436 | 0x44, 0xff, | ||
437 | 0x45, 0xff, | ||
438 | 0x46, 0xff, | ||
439 | 0x47, 0xff, | ||
440 | 0x48, 0xff, | ||
441 | 0x49, 0xff, | ||
442 | 0x4a, 0xff, | ||
443 | 0x4b, 0xff, | ||
444 | 0x4c, 0xff, | ||
445 | 0x4d, 0xff, | ||
446 | 0x4e, 0xff, | ||
447 | 0x4f, 0xff, | ||
448 | 0x50, 0xff, | ||
449 | 0x51, 0xff, | ||
450 | 0x52, 0xff, | ||
451 | 0x53, 0xff, | ||
452 | 0x54, 0xff, | ||
453 | 0x55, 0xff, | ||
454 | 0x56, 0xff, | ||
455 | 0x57, 0xff, | ||
456 | 0x58, 0x40, | ||
457 | 0x59, 0x47, | ||
458 | 0x5b, 0x83, | ||
459 | 0x5d, 0xbd, | ||
460 | 0x5e, 0x35, | ||
461 | |||
462 | 0x02, 0x84, /* input tuner -> input 4, amplifier active */ | ||
463 | 0x09, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */ | ||
464 | |||
465 | 0x80, 0x20, /* enable task B */ | ||
466 | 0x88, 0xd0, | ||
467 | 0x88, 0xf0, | ||
468 | 0x00, 0x00 | ||
469 | }; | ||
470 | |||
471 | /* ============== SAA7715 AUDIO settings ============= */ | ||
472 | |||
473 | /* 48.0 kHz */ | ||
474 | static const unsigned char saa7115_cfg_48_audio[] = { | ||
475 | 0x34, 0xce, | ||
476 | 0x35, 0xfb, | ||
477 | 0x36, 0x30, | ||
478 | 0x00, 0x00 | ||
479 | }; | ||
480 | |||
481 | /* 44.1 kHz */ | ||
482 | static const unsigned char saa7115_cfg_441_audio[] = { | ||
483 | 0x34, 0xf2, | ||
484 | 0x35, 0x00, | ||
485 | 0x36, 0x2d, | ||
486 | 0x00, 0x00 | ||
487 | }; | ||
488 | |||
489 | /* 32.0 kHz */ | ||
490 | static const unsigned char saa7115_cfg_32_audio[] = { | ||
491 | 0x34, 0xdf, | ||
492 | 0x35, 0xa7, | ||
493 | 0x36, 0x20, | ||
494 | 0x00, 0x00 | ||
495 | }; | ||
496 | |||
497 | /* 48.0 kHz 60hz */ | ||
498 | static const unsigned char saa7115_cfg_60hz_48_audio[] = { | ||
499 | 0x30, 0xcd, | ||
500 | 0x31, 0x20, | ||
501 | 0x32, 0x03, | ||
502 | 0x00, 0x00 | ||
503 | }; | ||
504 | |||
505 | /* 48.0 kHz 50hz */ | ||
506 | static const unsigned char saa7115_cfg_50hz_48_audio[] = { | ||
507 | 0x30, 0x00, | ||
508 | 0x31, 0xc0, | ||
509 | 0x32, 0x03, | ||
510 | 0x00, 0x00 | ||
511 | }; | ||
512 | |||
513 | /* 44.1 kHz 60hz */ | ||
514 | static const unsigned char saa7115_cfg_60hz_441_audio[] = { | ||
515 | 0x30, 0xbc, | ||
516 | 0x31, 0xdf, | ||
517 | 0x32, 0x02, | ||
518 | 0x00, 0x00 | ||
519 | }; | ||
520 | |||
521 | /* 44.1 kHz 50hz */ | ||
522 | static const unsigned char saa7115_cfg_50hz_441_audio[] = { | ||
523 | 0x30, 0x00, | ||
524 | 0x31, 0x72, | ||
525 | 0x32, 0x03, | ||
526 | 0x00, 0x00 | ||
527 | }; | ||
528 | |||
529 | /* 32.0 kHz 60hz */ | ||
530 | static const unsigned char saa7115_cfg_60hz_32_audio[] = { | ||
531 | 0x30, 0xde, | ||
532 | 0x31, 0x15, | ||
533 | 0x32, 0x02, | ||
534 | 0x00, 0x00 | ||
535 | }; | ||
536 | |||
537 | /* 32.0 kHz 50hz */ | ||
538 | static const unsigned char saa7115_cfg_50hz_32_audio[] = { | ||
539 | 0x30, 0x00, | ||
540 | 0x31, 0x80, | ||
541 | 0x32, 0x02, | ||
542 | 0x00, 0x00 | ||
543 | }; | ||
544 | |||
545 | static int saa7115_odd_parity(u8 c) | ||
546 | { | ||
547 | c ^= (c >> 4); | ||
548 | c ^= (c >> 2); | ||
549 | c ^= (c >> 1); | ||
550 | |||
551 | return c & 1; | ||
552 | } | ||
553 | |||
554 | static int saa7115_decode_vps(u8 * dst, u8 * p) | ||
555 | { | ||
556 | static const u8 biphase_tbl[] = { | ||
557 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
558 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
559 | 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96, | ||
560 | 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2, | ||
561 | 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94, | ||
562 | 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0, | ||
563 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
564 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
565 | 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5, | ||
566 | 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1, | ||
567 | 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87, | ||
568 | 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3, | ||
569 | 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85, | ||
570 | 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1, | ||
571 | 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5, | ||
572 | 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1, | ||
573 | 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4, | ||
574 | 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0, | ||
575 | 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86, | ||
576 | 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2, | ||
577 | 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84, | ||
578 | 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0, | ||
579 | 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4, | ||
580 | 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0, | ||
581 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
582 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
583 | 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96, | ||
584 | 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2, | ||
585 | 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94, | ||
586 | 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0, | ||
587 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
588 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
589 | }; | ||
590 | int i; | ||
591 | u8 c, err = 0; | ||
592 | |||
593 | for (i = 0; i < 2 * 13; i += 2) { | ||
594 | err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]]; | ||
595 | c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4); | ||
596 | dst[i / 2] = c; | ||
597 | } | ||
598 | return err & 0xf0; | ||
599 | } | ||
600 | |||
601 | static int saa7115_decode_wss(u8 * p) | ||
602 | { | ||
603 | static const int wss_bits[8] = { | ||
604 | 0, 0, 0, 1, 0, 1, 1, 1 | ||
605 | }; | ||
606 | unsigned char parity; | ||
607 | int wss = 0; | ||
608 | int i; | ||
609 | |||
610 | for (i = 0; i < 16; i++) { | ||
611 | int b1 = wss_bits[p[i] & 7]; | ||
612 | int b2 = wss_bits[(p[i] >> 3) & 7]; | ||
613 | |||
614 | if (b1 == b2) | ||
615 | return -1; | ||
616 | wss |= b2 << i; | ||
617 | } | ||
618 | parity = wss & 15; | ||
619 | parity ^= parity >> 2; | ||
620 | parity ^= parity >> 1; | ||
621 | |||
622 | if (!(parity & 1)) | ||
623 | return -1; | ||
624 | |||
625 | return wss; | ||
626 | } | ||
627 | |||
628 | |||
629 | static int saa7115_set_audio_clock_freq(struct i2c_client *client, enum v4l2_audio_clock_freq freq) | ||
630 | { | ||
631 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
632 | |||
633 | saa7115_dbg("set audio clock freq: %d\n", freq); | ||
634 | switch (freq) { | ||
635 | case V4L2_AUDCLK_32_KHZ: | ||
636 | saa7115_writeregs(client, saa7115_cfg_32_audio); | ||
637 | if (state->std & V4L2_STD_525_60) { | ||
638 | saa7115_writeregs(client, saa7115_cfg_60hz_32_audio); | ||
639 | } else { | ||
640 | saa7115_writeregs(client, saa7115_cfg_50hz_32_audio); | ||
641 | } | ||
642 | break; | ||
643 | case V4L2_AUDCLK_441_KHZ: | ||
644 | saa7115_writeregs(client, saa7115_cfg_441_audio); | ||
645 | if (state->std & V4L2_STD_525_60) { | ||
646 | saa7115_writeregs(client, saa7115_cfg_60hz_441_audio); | ||
647 | } else { | ||
648 | saa7115_writeregs(client, saa7115_cfg_50hz_441_audio); | ||
649 | } | ||
650 | break; | ||
651 | case V4L2_AUDCLK_48_KHZ: | ||
652 | saa7115_writeregs(client, saa7115_cfg_48_audio); | ||
653 | if (state->std & V4L2_STD_525_60) { | ||
654 | saa7115_writeregs(client, saa7115_cfg_60hz_48_audio); | ||
655 | } else { | ||
656 | saa7115_writeregs(client, saa7115_cfg_50hz_48_audio); | ||
657 | } | ||
658 | break; | ||
659 | default: | ||
660 | saa7115_dbg("invalid audio setting %d\n", freq); | ||
661 | return -EINVAL; | ||
662 | } | ||
663 | state->audclk_freq = freq; | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
668 | { | ||
669 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
670 | |||
671 | switch (ctrl->id) { | ||
672 | case V4L2_CID_BRIGHTNESS: | ||
673 | if (ctrl->value < 0 || ctrl->value > 255) { | ||
674 | saa7115_err("invalid brightness setting %d\n", ctrl->value); | ||
675 | return -ERANGE; | ||
676 | } | ||
677 | |||
678 | state->bright = ctrl->value; | ||
679 | saa7115_write(client, 0x0a, state->bright); | ||
680 | break; | ||
681 | |||
682 | case V4L2_CID_CONTRAST: | ||
683 | if (ctrl->value < 0 || ctrl->value > 127) { | ||
684 | saa7115_err("invalid contrast setting %d\n", ctrl->value); | ||
685 | return -ERANGE; | ||
686 | } | ||
687 | |||
688 | state->contrast = ctrl->value; | ||
689 | saa7115_write(client, 0x0b, state->contrast); | ||
690 | break; | ||
691 | |||
692 | case V4L2_CID_SATURATION: | ||
693 | if (ctrl->value < 0 || ctrl->value > 127) { | ||
694 | saa7115_err("invalid saturation setting %d\n", ctrl->value); | ||
695 | return -ERANGE; | ||
696 | } | ||
697 | |||
698 | state->sat = ctrl->value; | ||
699 | saa7115_write(client, 0x0c, state->sat); | ||
700 | break; | ||
701 | |||
702 | case V4L2_CID_HUE: | ||
703 | if (ctrl->value < -127 || ctrl->value > 127) { | ||
704 | saa7115_err("invalid hue setting %d\n", ctrl->value); | ||
705 | return -ERANGE; | ||
706 | } | ||
707 | |||
708 | state->hue = ctrl->value; | ||
709 | saa7115_write(client, 0x0d, state->hue); | ||
710 | break; | ||
711 | } | ||
712 | |||
713 | return 0; | ||
714 | } | ||
715 | |||
716 | static int saa7115_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
717 | { | ||
718 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
719 | |||
720 | switch (ctrl->id) { | ||
721 | case V4L2_CID_BRIGHTNESS: | ||
722 | ctrl->value = state->bright; | ||
723 | break; | ||
724 | case V4L2_CID_CONTRAST: | ||
725 | ctrl->value = state->contrast; | ||
726 | break; | ||
727 | case V4L2_CID_SATURATION: | ||
728 | ctrl->value = state->sat; | ||
729 | break; | ||
730 | case V4L2_CID_HUE: | ||
731 | ctrl->value = state->hue; | ||
732 | break; | ||
733 | default: | ||
734 | return -EINVAL; | ||
735 | } | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std) | ||
741 | { | ||
742 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
743 | int taskb = saa7115_read(client, 0x80) & 0x10; | ||
744 | |||
745 | // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. | ||
746 | if (std & V4L2_STD_525_60) { | ||
747 | saa7115_dbg("decoder set standard 60 Hz\n"); | ||
748 | saa7115_writeregs(client, saa7115_cfg_60hz_video); | ||
749 | } else { | ||
750 | saa7115_dbg("decoder set standard 50 Hz\n"); | ||
751 | saa7115_writeregs(client, saa7115_cfg_50hz_video); | ||
752 | } | ||
753 | |||
754 | state->std = std; | ||
755 | |||
756 | /* restart task B if needed */ | ||
757 | if (taskb && state->ident == V4L2_IDENT_SAA7114) { | ||
758 | saa7115_writeregs(client, saa7115_cfg_vbi_on); | ||
759 | } | ||
760 | |||
761 | /* switch audio mode too! */ | ||
762 | saa7115_set_audio_clock_freq(client, state->audclk_freq); | ||
763 | } | ||
764 | |||
765 | static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client) | ||
766 | { | ||
767 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
768 | |||
769 | return state->std; | ||
770 | } | ||
771 | |||
772 | static void saa7115_log_status(struct i2c_client *client) | ||
773 | { | ||
774 | static const char * const audclk_freq_strs[] = { | ||
775 | "44.1 kHz", | ||
776 | "48 kHz", | ||
777 | "32 kHz" | ||
778 | }; | ||
779 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
780 | int reg1e, reg1f; | ||
781 | int signalOk; | ||
782 | int vcr; | ||
783 | |||
784 | saa7115_info("Audio frequency: %s\n", audclk_freq_strs[state->audclk_freq]); | ||
785 | if (client->name[6] == '4') { | ||
786 | /* status for the saa7114 */ | ||
787 | reg1f = saa7115_read(client, 0x1f); | ||
788 | signalOk = (reg1f & 0xc1) == 0x81; | ||
789 | saa7115_info("Video signal: %s\n", signalOk ? "ok" : "bad"); | ||
790 | saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); | ||
791 | return; | ||
792 | } | ||
793 | |||
794 | /* status for the saa7115 */ | ||
795 | reg1e = saa7115_read(client, 0x1e); | ||
796 | reg1f = saa7115_read(client, 0x1f); | ||
797 | |||
798 | signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80; | ||
799 | vcr = !(reg1f & 0x10); | ||
800 | |||
801 | saa7115_info("Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad"); | ||
802 | saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); | ||
803 | |||
804 | switch (reg1e & 0x03) { | ||
805 | case 1: | ||
806 | saa7115_info("Detected format: NTSC\n"); | ||
807 | break; | ||
808 | case 2: | ||
809 | saa7115_info("Detected format: PAL\n"); | ||
810 | break; | ||
811 | case 3: | ||
812 | saa7115_info("Detected format: SECAM\n"); | ||
813 | break; | ||
814 | default: | ||
815 | saa7115_info("Detected format: BW/No color\n"); | ||
816 | break; | ||
817 | } | ||
818 | } | ||
819 | |||
820 | /* setup the sliced VBI lcr registers according to the sliced VBI format */ | ||
821 | static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_format *fmt) | ||
822 | { | ||
823 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
824 | int is_50hz = (state->std & V4L2_STD_625_50); | ||
825 | u8 lcr[24]; | ||
826 | int i, x; | ||
827 | |||
828 | /* saa7114 doesn't yet support VBI */ | ||
829 | if (state->ident == V4L2_IDENT_SAA7114) | ||
830 | return; | ||
831 | |||
832 | for (i = 0; i <= 23; i++) | ||
833 | lcr[i] = 0xff; | ||
834 | |||
835 | if (fmt->service_set == 0) { | ||
836 | /* raw VBI */ | ||
837 | if (is_50hz) | ||
838 | for (i = 6; i <= 23; i++) | ||
839 | lcr[i] = 0xdd; | ||
840 | else | ||
841 | for (i = 10; i <= 21; i++) | ||
842 | lcr[i] = 0xdd; | ||
843 | } else { | ||
844 | /* sliced VBI */ | ||
845 | /* first clear lines that cannot be captured */ | ||
846 | if (is_50hz) { | ||
847 | for (i = 0; i <= 5; i++) | ||
848 | fmt->service_lines[0][i] = | ||
849 | fmt->service_lines[1][i] = 0; | ||
850 | } | ||
851 | else { | ||
852 | for (i = 0; i <= 9; i++) | ||
853 | fmt->service_lines[0][i] = | ||
854 | fmt->service_lines[1][i] = 0; | ||
855 | for (i = 22; i <= 23; i++) | ||
856 | fmt->service_lines[0][i] = | ||
857 | fmt->service_lines[1][i] = 0; | ||
858 | } | ||
859 | |||
860 | /* Now set the lcr values according to the specified service */ | ||
861 | for (i = 6; i <= 23; i++) { | ||
862 | lcr[i] = 0; | ||
863 | for (x = 0; x <= 1; x++) { | ||
864 | switch (fmt->service_lines[1-x][i]) { | ||
865 | case 0: | ||
866 | lcr[i] |= 0xf << (4 * x); | ||
867 | break; | ||
868 | case V4L2_SLICED_TELETEXT_B: | ||
869 | lcr[i] |= 1 << (4 * x); | ||
870 | break; | ||
871 | case V4L2_SLICED_CAPTION_525: | ||
872 | lcr[i] |= 4 << (4 * x); | ||
873 | break; | ||
874 | case V4L2_SLICED_WSS_625: | ||
875 | lcr[i] |= 5 << (4 * x); | ||
876 | break; | ||
877 | case V4L2_SLICED_VPS: | ||
878 | lcr[i] |= 7 << (4 * x); | ||
879 | break; | ||
880 | } | ||
881 | } | ||
882 | } | ||
883 | } | ||
884 | |||
885 | /* write the lcr registers */ | ||
886 | for (i = 2; i <= 23; i++) { | ||
887 | saa7115_write(client, i - 2 + 0x41, lcr[i]); | ||
888 | } | ||
889 | |||
890 | /* enable/disable raw VBI capturing */ | ||
891 | saa7115_writeregs(client, fmt->service_set == 0 ? saa7115_cfg_vbi_on : saa7115_cfg_vbi_off); | ||
892 | } | ||
893 | |||
894 | static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | ||
895 | { | ||
896 | static u16 lcr2vbi[] = { | ||
897 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ | ||
898 | 0, V4L2_SLICED_CAPTION_525, /* 4 */ | ||
899 | V4L2_SLICED_WSS_625, 0, /* 5 */ | ||
900 | V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */ | ||
901 | 0, 0, 0, 0 | ||
902 | }; | ||
903 | struct v4l2_sliced_vbi_format *sliced = &fmt->fmt.sliced; | ||
904 | int i; | ||
905 | |||
906 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
907 | return -EINVAL; | ||
908 | memset(sliced, 0, sizeof(*sliced)); | ||
909 | /* done if using raw VBI */ | ||
910 | if (saa7115_read(client, 0x80) & 0x10) | ||
911 | return 0; | ||
912 | for (i = 2; i <= 23; i++) { | ||
913 | u8 v = saa7115_read(client, i - 2 + 0x41); | ||
914 | |||
915 | sliced->service_lines[0][i] = lcr2vbi[v >> 4]; | ||
916 | sliced->service_lines[1][i] = lcr2vbi[v & 0xf]; | ||
917 | sliced->service_set |= | ||
918 | sliced->service_lines[0][i] | sliced->service_lines[1][i]; | ||
919 | } | ||
920 | return 0; | ||
921 | } | ||
922 | |||
923 | static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | ||
924 | { | ||
925 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
926 | struct v4l2_pix_format *pix; | ||
927 | int HPSC, HFSC; | ||
928 | int VSCY, Vsrc; | ||
929 | int is_50hz = state->std & V4L2_STD_625_50; | ||
930 | |||
931 | if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { | ||
932 | saa7115_set_lcr(client, &fmt->fmt.sliced); | ||
933 | return 0; | ||
934 | } | ||
935 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
936 | return -EINVAL; | ||
937 | |||
938 | pix = &(fmt->fmt.pix); | ||
939 | |||
940 | saa7115_dbg("decoder set size\n"); | ||
941 | |||
942 | /* FIXME need better bounds checking here */ | ||
943 | if ((pix->width < 1) || (pix->width > 1440)) | ||
944 | return -EINVAL; | ||
945 | if ((pix->height < 1) || (pix->height > 960)) | ||
946 | return -EINVAL; | ||
947 | |||
948 | /* probably have a valid size, let's set it */ | ||
949 | /* Set output width/height */ | ||
950 | /* width */ | ||
951 | saa7115_write(client, 0xcc, (u8) (pix->width & 0xff)); | ||
952 | saa7115_write(client, 0xcd, (u8) ((pix->width >> 8) & 0xff)); | ||
953 | /* height */ | ||
954 | saa7115_write(client, 0xce, (u8) (pix->height & 0xff)); | ||
955 | saa7115_write(client, 0xcf, (u8) ((pix->height >> 8) & 0xff)); | ||
956 | |||
957 | /* Scaling settings */ | ||
958 | /* Hprescaler is floor(inres/outres) */ | ||
959 | /* FIXME hardcoding input res */ | ||
960 | if (pix->width != 720) { | ||
961 | HPSC = (int)(720 / pix->width); | ||
962 | /* 0 is not allowed (div. by zero) */ | ||
963 | HPSC = HPSC ? HPSC : 1; | ||
964 | HFSC = (int)((1024 * 720) / (HPSC * pix->width)); | ||
965 | |||
966 | saa7115_dbg("Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC); | ||
967 | /* FIXME hardcodes to "Task B" | ||
968 | * write H prescaler integer */ | ||
969 | saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f)); | ||
970 | |||
971 | /* write H fine-scaling (luminance) */ | ||
972 | saa7115_write(client, 0xd8, (u8) (HFSC & 0xff)); | ||
973 | saa7115_write(client, 0xd9, (u8) ((HFSC >> 8) & 0xff)); | ||
974 | /* write H fine-scaling (chrominance) | ||
975 | * must be lum/2, so i'll just bitshift :) */ | ||
976 | saa7115_write(client, 0xDC, (u8) ((HFSC >> 1) & 0xff)); | ||
977 | saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff)); | ||
978 | } else { | ||
979 | if (is_50hz) { | ||
980 | saa7115_dbg("Setting full 50hz width\n"); | ||
981 | saa7115_writeregs(client, saa7115_cfg_50hz_fullres_x); | ||
982 | } else { | ||
983 | saa7115_dbg("Setting full 60hz width\n"); | ||
984 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); | ||
985 | } | ||
986 | } | ||
987 | |||
988 | Vsrc = is_50hz ? 576 : 480; | ||
989 | |||
990 | if (pix->height != Vsrc) { | ||
991 | VSCY = (int)((1024 * Vsrc) / pix->height); | ||
992 | saa7115_dbg("Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY); | ||
993 | |||
994 | /* Correct Contrast and Luminance */ | ||
995 | saa7115_write(client, 0xd5, (u8) (64 * 1024 / VSCY)); | ||
996 | saa7115_write(client, 0xd6, (u8) (64 * 1024 / VSCY)); | ||
997 | |||
998 | /* write V fine-scaling (luminance) */ | ||
999 | saa7115_write(client, 0xe0, (u8) (VSCY & 0xff)); | ||
1000 | saa7115_write(client, 0xe1, (u8) ((VSCY >> 8) & 0xff)); | ||
1001 | /* write V fine-scaling (chrominance) */ | ||
1002 | saa7115_write(client, 0xe2, (u8) (VSCY & 0xff)); | ||
1003 | saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff)); | ||
1004 | } else { | ||
1005 | if (is_50hz) { | ||
1006 | saa7115_dbg("Setting full 50Hz height\n"); | ||
1007 | saa7115_writeregs(client, saa7115_cfg_50hz_fullres_y); | ||
1008 | } else { | ||
1009 | saa7115_dbg("Setting full 60hz height\n"); | ||
1010 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); | ||
1011 | } | ||
1012 | } | ||
1013 | |||
1014 | saa7115_writeregs(client, saa7115_cfg_reset_scaler); | ||
1015 | return 0; | ||
1016 | } | ||
1017 | |||
1018 | /* Decode the sliced VBI data stream as created by the saa7115. | ||
1019 | The format is described in the saa7115 datasheet in Tables 25 and 26 | ||
1020 | and in Figure 33. | ||
1021 | The current implementation uses SAV/EAV codes and not the ancillary data | ||
1022 | headers. The vbi->p pointer points to the SDID byte right after the SAV | ||
1023 | code. */ | ||
1024 | static void saa7115_decode_vbi_line(struct i2c_client *client, | ||
1025 | struct v4l2_decode_vbi_line *vbi) | ||
1026 | { | ||
1027 | static const char vbi_no_data_pattern[] = { | ||
1028 | 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0 | ||
1029 | }; | ||
1030 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
1031 | u8 *p = vbi->p; | ||
1032 | u32 wss; | ||
1033 | int id1, id2; /* the ID1 and ID2 bytes from the internal header */ | ||
1034 | |||
1035 | vbi->type = 0; /* mark result as a failure */ | ||
1036 | id1 = p[2]; | ||
1037 | id2 = p[3]; | ||
1038 | /* Note: the field bit is inverted for 60 Hz video */ | ||
1039 | if (state->std & V4L2_STD_525_60) | ||
1040 | id1 ^= 0x40; | ||
1041 | |||
1042 | /* Skip internal header, p now points to the start of the payload */ | ||
1043 | p += 4; | ||
1044 | vbi->p = p; | ||
1045 | |||
1046 | /* calculate field and line number of the VBI packet (1-23) */ | ||
1047 | vbi->is_second_field = ((id1 & 0x40) != 0); | ||
1048 | vbi->line = (id1 & 0x3f) << 3; | ||
1049 | vbi->line |= (id2 & 0x70) >> 4; | ||
1050 | |||
1051 | /* Obtain data type */ | ||
1052 | id2 &= 0xf; | ||
1053 | |||
1054 | /* If the VBI slicer does not detect any signal it will fill up | ||
1055 | the payload buffer with 0xa0 bytes. */ | ||
1056 | if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern))) | ||
1057 | return; | ||
1058 | |||
1059 | /* decode payloads */ | ||
1060 | switch (id2) { | ||
1061 | case 1: | ||
1062 | vbi->type = V4L2_SLICED_TELETEXT_B; | ||
1063 | break; | ||
1064 | case 4: | ||
1065 | if (!saa7115_odd_parity(p[0]) || !saa7115_odd_parity(p[1])) | ||
1066 | return; | ||
1067 | vbi->type = V4L2_SLICED_CAPTION_525; | ||
1068 | break; | ||
1069 | case 5: | ||
1070 | wss = saa7115_decode_wss(p); | ||
1071 | if (wss == -1) | ||
1072 | return; | ||
1073 | p[0] = wss & 0xff; | ||
1074 | p[1] = wss >> 8; | ||
1075 | vbi->type = V4L2_SLICED_WSS_625; | ||
1076 | break; | ||
1077 | case 7: | ||
1078 | if (saa7115_decode_vps(p, p) != 0) | ||
1079 | return; | ||
1080 | vbi->type = V4L2_SLICED_VPS; | ||
1081 | break; | ||
1082 | default: | ||
1083 | return; | ||
1084 | } | ||
1085 | } | ||
1086 | |||
1087 | /* ============ SAA7115 AUDIO settings (end) ============= */ | ||
1088 | |||
1089 | static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) | ||
1090 | { | ||
1091 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
1092 | int *iarg = arg; | ||
1093 | |||
1094 | /* ioctls to allow direct access to the saa7115 registers for testing */ | ||
1095 | switch (cmd) { | ||
1096 | case VIDIOC_S_FMT: | ||
1097 | return saa7115_set_v4lfmt(client, (struct v4l2_format *)arg); | ||
1098 | |||
1099 | case VIDIOC_G_FMT: | ||
1100 | return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg); | ||
1101 | |||
1102 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | ||
1103 | return saa7115_set_audio_clock_freq(client, *(enum v4l2_audio_clock_freq *)arg); | ||
1104 | |||
1105 | case VIDIOC_G_TUNER: | ||
1106 | { | ||
1107 | struct v4l2_tuner *vt = arg; | ||
1108 | int status; | ||
1109 | |||
1110 | status = saa7115_read(client, 0x1f); | ||
1111 | |||
1112 | saa7115_dbg("status: 0x%02x\n", status); | ||
1113 | vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0; | ||
1114 | break; | ||
1115 | } | ||
1116 | |||
1117 | case VIDIOC_LOG_STATUS: | ||
1118 | saa7115_log_status(client); | ||
1119 | break; | ||
1120 | |||
1121 | case VIDIOC_G_CTRL: | ||
1122 | return saa7115_get_v4lctrl(client, (struct v4l2_control *)arg); | ||
1123 | |||
1124 | case VIDIOC_S_CTRL: | ||
1125 | return saa7115_set_v4lctrl(client, (struct v4l2_control *)arg); | ||
1126 | |||
1127 | case VIDIOC_G_STD: | ||
1128 | *(v4l2_std_id *)arg = saa7115_get_v4lstd(client); | ||
1129 | break; | ||
1130 | |||
1131 | case VIDIOC_S_STD: | ||
1132 | saa7115_set_v4lstd(client, *(v4l2_std_id *)arg); | ||
1133 | break; | ||
1134 | |||
1135 | case VIDIOC_G_INPUT: | ||
1136 | *(int *)arg = state->input; | ||
1137 | break; | ||
1138 | |||
1139 | case VIDIOC_S_INPUT: | ||
1140 | saa7115_dbg("decoder set input %d\n", *iarg); | ||
1141 | /* inputs from 0-9 are available */ | ||
1142 | if (*iarg < 0 || *iarg > 9) { | ||
1143 | return -EINVAL; | ||
1144 | } | ||
1145 | |||
1146 | if (state->input == *iarg) | ||
1147 | break; | ||
1148 | saa7115_dbg("now setting %s input\n", | ||
1149 | *iarg >= 6 ? "S-Video" : "Composite"); | ||
1150 | state->input = *iarg; | ||
1151 | |||
1152 | /* select mode */ | ||
1153 | saa7115_write(client, 0x02, | ||
1154 | (saa7115_read(client, 0x02) & 0xf0) | | ||
1155 | state->input); | ||
1156 | |||
1157 | /* bypass chrominance trap for modes 6..9 */ | ||
1158 | saa7115_write(client, 0x09, | ||
1159 | (saa7115_read(client, 0x09) & 0x7f) | | ||
1160 | (state->input < 6 ? 0x0 : 0x80)); | ||
1161 | break; | ||
1162 | |||
1163 | case VIDIOC_STREAMON: | ||
1164 | case VIDIOC_STREAMOFF: | ||
1165 | saa7115_dbg("%s output\n", | ||
1166 | (cmd == VIDIOC_STREAMON) ? "enable" : "disable"); | ||
1167 | |||
1168 | if (state->enable != (cmd == VIDIOC_STREAMON)) { | ||
1169 | state->enable = (cmd == VIDIOC_STREAMON); | ||
1170 | saa7115_write(client, 0x87, state->enable); | ||
1171 | } | ||
1172 | break; | ||
1173 | |||
1174 | case VIDIOC_INT_DECODE_VBI_LINE: | ||
1175 | saa7115_decode_vbi_line(client, arg); | ||
1176 | break; | ||
1177 | |||
1178 | case VIDIOC_INT_RESET: | ||
1179 | saa7115_dbg("decoder RESET\n"); | ||
1180 | saa7115_writeregs(client, saa7115_cfg_reset_scaler); | ||
1181 | break; | ||
1182 | |||
1183 | case VIDIOC_INT_G_VBI_DATA: | ||
1184 | { | ||
1185 | struct v4l2_sliced_vbi_data *data = arg; | ||
1186 | |||
1187 | switch (data->id) { | ||
1188 | case V4L2_SLICED_WSS_625: | ||
1189 | if (saa7115_read(client, 0x6b) & 0xc0) | ||
1190 | return -EIO; | ||
1191 | data->data[0] = saa7115_read(client, 0x6c); | ||
1192 | data->data[1] = saa7115_read(client, 0x6d); | ||
1193 | return 0; | ||
1194 | case V4L2_SLICED_CAPTION_525: | ||
1195 | if (data->field == 0) { | ||
1196 | /* CC */ | ||
1197 | if (saa7115_read(client, 0x66) & 0xc0) | ||
1198 | return -EIO; | ||
1199 | data->data[0] = saa7115_read(client, 0x67); | ||
1200 | data->data[1] = saa7115_read(client, 0x68); | ||
1201 | return 0; | ||
1202 | } | ||
1203 | /* XDS */ | ||
1204 | if (saa7115_read(client, 0x66) & 0x30) | ||
1205 | return -EIO; | ||
1206 | data->data[0] = saa7115_read(client, 0x69); | ||
1207 | data->data[1] = saa7115_read(client, 0x6a); | ||
1208 | return 0; | ||
1209 | default: | ||
1210 | return -EINVAL; | ||
1211 | } | ||
1212 | break; | ||
1213 | } | ||
1214 | |||
1215 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1216 | case VIDIOC_INT_G_REGISTER: | ||
1217 | { | ||
1218 | struct v4l2_register *reg = arg; | ||
1219 | |||
1220 | if (reg->i2c_id != I2C_DRIVERID_SAA711X) | ||
1221 | return -EINVAL; | ||
1222 | reg->val = saa7115_read(client, reg->reg & 0xff); | ||
1223 | break; | ||
1224 | } | ||
1225 | |||
1226 | case VIDIOC_INT_S_REGISTER: | ||
1227 | { | ||
1228 | struct v4l2_register *reg = arg; | ||
1229 | |||
1230 | if (reg->i2c_id != I2C_DRIVERID_SAA711X) | ||
1231 | return -EINVAL; | ||
1232 | if (!capable(CAP_SYS_ADMIN)) | ||
1233 | return -EPERM; | ||
1234 | saa7115_write(client, reg->reg & 0xff, reg->val & 0xff); | ||
1235 | break; | ||
1236 | } | ||
1237 | #endif | ||
1238 | |||
1239 | case VIDIOC_INT_G_CHIP_IDENT: | ||
1240 | *iarg = state->ident; | ||
1241 | break; | ||
1242 | |||
1243 | default: | ||
1244 | return -EINVAL; | ||
1245 | } | ||
1246 | |||
1247 | return 0; | ||
1248 | } | ||
1249 | |||
1250 | /* ----------------------------------------------------------------------- */ | ||
1251 | |||
1252 | static struct i2c_driver i2c_driver_saa7115; | ||
1253 | |||
1254 | static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) | ||
1255 | { | ||
1256 | struct i2c_client *client; | ||
1257 | struct saa7115_state *state; | ||
1258 | u8 chip_id; | ||
1259 | |||
1260 | /* Check if the adapter supports the needed features */ | ||
1261 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
1262 | return 0; | ||
1263 | |||
1264 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
1265 | if (client == 0) | ||
1266 | return -ENOMEM; | ||
1267 | memset(client, 0, sizeof(struct i2c_client)); | ||
1268 | client->addr = address; | ||
1269 | client->adapter = adapter; | ||
1270 | client->driver = &i2c_driver_saa7115; | ||
1271 | client->flags = I2C_CLIENT_ALLOW_USE; | ||
1272 | snprintf(client->name, sizeof(client->name) - 1, "saa7115"); | ||
1273 | |||
1274 | saa7115_dbg("detecting saa7115 client on address 0x%x\n", address << 1); | ||
1275 | |||
1276 | saa7115_write(client, 0, 5); | ||
1277 | chip_id = saa7115_read(client, 0) & 0x0f; | ||
1278 | if (chip_id != 4 && chip_id != 5) { | ||
1279 | saa7115_dbg("saa7115 not found\n"); | ||
1280 | kfree(client); | ||
1281 | return 0; | ||
1282 | } | ||
1283 | if (chip_id == 4) { | ||
1284 | snprintf(client->name, sizeof(client->name) - 1, "saa7114"); | ||
1285 | } | ||
1286 | saa7115_info("saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name); | ||
1287 | |||
1288 | state = kmalloc(sizeof(struct saa7115_state), GFP_KERNEL); | ||
1289 | i2c_set_clientdata(client, state); | ||
1290 | if (state == NULL) { | ||
1291 | kfree(client); | ||
1292 | return -ENOMEM; | ||
1293 | } | ||
1294 | memset(state, 0, sizeof(struct saa7115_state)); | ||
1295 | state->std = V4L2_STD_NTSC; | ||
1296 | state->input = -1; | ||
1297 | state->enable = 1; | ||
1298 | state->bright = 128; | ||
1299 | state->contrast = 64; | ||
1300 | state->hue = 0; | ||
1301 | state->sat = 64; | ||
1302 | state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115; | ||
1303 | state->audclk_freq = V4L2_AUDCLK_48_KHZ; | ||
1304 | |||
1305 | saa7115_dbg("writing init values\n"); | ||
1306 | |||
1307 | /* init to 60hz/48khz */ | ||
1308 | saa7115_writeregs(client, saa7115_init_auto_input); | ||
1309 | saa7115_writeregs(client, saa7115_init_misc); | ||
1310 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); | ||
1311 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); | ||
1312 | saa7115_writeregs(client, saa7115_cfg_60hz_video); | ||
1313 | saa7115_writeregs(client, saa7115_cfg_48_audio); | ||
1314 | saa7115_writeregs(client, saa7115_cfg_60hz_48_audio); | ||
1315 | saa7115_writeregs(client, saa7115_cfg_reset_scaler); | ||
1316 | |||
1317 | i2c_attach_client(client); | ||
1318 | |||
1319 | saa7115_dbg("status: (1E) 0x%02x, (1F) 0x%02x\n", | ||
1320 | saa7115_read(client, 0x1e), saa7115_read(client, 0x1f)); | ||
1321 | |||
1322 | return 0; | ||
1323 | } | ||
1324 | |||
1325 | static int saa7115_probe(struct i2c_adapter *adapter) | ||
1326 | { | ||
1327 | #ifdef I2C_CLASS_TV_ANALOG | ||
1328 | if (adapter->class & I2C_CLASS_TV_ANALOG) | ||
1329 | #else | ||
1330 | if (adapter->id == I2C_HW_B_BT848) | ||
1331 | #endif | ||
1332 | return i2c_probe(adapter, &addr_data, &saa7115_attach); | ||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1336 | static int saa7115_detach(struct i2c_client *client) | ||
1337 | { | ||
1338 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
1339 | int err; | ||
1340 | |||
1341 | err = i2c_detach_client(client); | ||
1342 | if (err) { | ||
1343 | return err; | ||
1344 | } | ||
1345 | |||
1346 | kfree(state); | ||
1347 | kfree(client); | ||
1348 | return 0; | ||
1349 | } | ||
1350 | |||
1351 | /* ----------------------------------------------------------------------- */ | ||
1352 | |||
1353 | /* i2c implementation */ | ||
1354 | static struct i2c_driver i2c_driver_saa7115 = { | ||
1355 | .name = "saa7115", | ||
1356 | .id = I2C_DRIVERID_SAA711X, | ||
1357 | .flags = I2C_DF_NOTIFY, | ||
1358 | .attach_adapter = saa7115_probe, | ||
1359 | .detach_client = saa7115_detach, | ||
1360 | .command = saa7115_command, | ||
1361 | .owner = THIS_MODULE, | ||
1362 | }; | ||
1363 | |||
1364 | |||
1365 | static int __init saa7115_init_module(void) | ||
1366 | { | ||
1367 | return i2c_add_driver(&i2c_driver_saa7115); | ||
1368 | } | ||
1369 | |||
1370 | static void __exit saa7115_cleanup_module(void) | ||
1371 | { | ||
1372 | i2c_del_driver(&i2c_driver_saa7115); | ||
1373 | } | ||
1374 | |||
1375 | module_init(saa7115_init_module); | ||
1376 | module_exit(saa7115_cleanup_module); | ||
diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 9aa8827de2c3..25b30f352d84 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
37 | #include <asm/page.h> | 37 | #include <asm/page.h> |
38 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
39 | #include <asm/segment.h> | ||
40 | #include <linux/types.h> | 39 | #include <linux/types.h> |
41 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
42 | #include <linux/videodev.h> | 41 | #include <linux/videodev.h> |
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c new file mode 100644 index 000000000000..843431f10e3b --- /dev/null +++ b/drivers/media/video/saa7127.c | |||
@@ -0,0 +1,849 @@ | |||
1 | /* | ||
2 | * saa7127 - Philips SAA7127/SAA7129 video encoder driver | ||
3 | * | ||
4 | * Copyright (C) 2003 Roy Bulter <rbulter@hetnet.nl> | ||
5 | * | ||
6 | * Based on SAA7126 video encoder driver by Gillem & Andreas Oberritter | ||
7 | * | ||
8 | * Copyright (C) 2000-2001 Gillem <htoa@gmx.net> | ||
9 | * Copyright (C) 2002 Andreas Oberritter <obi@saftware.de> | ||
10 | * | ||
11 | * Based on Stadis 4:2:2 MPEG-2 Decoder Driver by Nathan Laredo | ||
12 | * | ||
13 | * Copyright (C) 1999 Nathan Laredo <laredo@gnu.org> | ||
14 | * | ||
15 | * This driver is designed for the Hauppauge 250/350 Linux driver | ||
16 | * from the ivtv Project | ||
17 | * | ||
18 | * Copyright (C) 2003 Kevin Thayer <nufan_wfk@yahoo.com> | ||
19 | * | ||
20 | * Dual output support: | ||
21 | * Copyright (C) 2004 Eric Varsanyi | ||
22 | * | ||
23 | * NTSC Tuning and 7.5 IRE Setup | ||
24 | * Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
25 | * | ||
26 | * VBI additions & cleanup: | ||
27 | * Copyright (C) 2004, 2005 Hans Verkuil <hverkuil@xs4all.nl> | ||
28 | * | ||
29 | * Note: the saa7126 is identical to the saa7127, and the saa7128 is | ||
30 | * identical to the saa7129, except that the saa7126 and saa7128 have | ||
31 | * macrovision anti-taping support. This driver will almost certainly | ||
32 | * work find for those chips, except of course for the missing anti-taping | ||
33 | * support. | ||
34 | * | ||
35 | * This program is free software; you can redistribute it and/or modify | ||
36 | * it under the terms of the GNU General Public License as published by | ||
37 | * the Free Software Foundation; either version 2 of the License, or | ||
38 | * (at your option) any later version. | ||
39 | * | ||
40 | * This program is distributed in the hope that it will be useful, | ||
41 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
42 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
43 | * GNU General Public License for more details. | ||
44 | * | ||
45 | * You should have received a copy of the GNU General Public License | ||
46 | * along with this program; if not, write to the Free Software | ||
47 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
48 | */ | ||
49 | |||
50 | |||
51 | #include <linux/kernel.h> | ||
52 | #include <linux/module.h> | ||
53 | #include <linux/slab.h> | ||
54 | #include <linux/i2c.h> | ||
55 | #include <linux/videodev2.h> | ||
56 | #include <media/v4l2-common.h> | ||
57 | |||
58 | static int debug = 0; | ||
59 | static int test_image = 0; | ||
60 | |||
61 | MODULE_DESCRIPTION("Philips SAA7127/9 video encoder driver"); | ||
62 | MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil"); | ||
63 | MODULE_LICENSE("GPL"); | ||
64 | module_param(debug, int, 0644); | ||
65 | module_param(test_image, int, 0644); | ||
66 | MODULE_PARM_DESC(debug, "debug level (0-2)"); | ||
67 | MODULE_PARM_DESC(test_image, "test_image (0-1)"); | ||
68 | |||
69 | #define saa7127_dbg(fmt, arg...) \ | ||
70 | do { \ | ||
71 | if (debug >= 1) \ | ||
72 | printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ | ||
73 | i2c_adapter_id(client->adapter), client->addr , ## arg); \ | ||
74 | } while (0) | ||
75 | |||
76 | /* High volume debug. Use with care. */ | ||
77 | #define saa7127_dbg_highvol(fmt, arg...) \ | ||
78 | do { \ | ||
79 | if (debug == 2) \ | ||
80 | printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ | ||
81 | i2c_adapter_id(client->adapter), client->addr , ## arg); \ | ||
82 | } while (0) | ||
83 | |||
84 | #define saa7127_err(fmt, arg...) do { \ | ||
85 | printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ | ||
86 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
87 | #define saa7127_info(fmt, arg...) do { \ | ||
88 | printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ | ||
89 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
90 | |||
91 | static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; | ||
92 | |||
93 | |||
94 | I2C_CLIENT_INSMOD; | ||
95 | |||
96 | /* | ||
97 | * SAA7127 registers | ||
98 | */ | ||
99 | |||
100 | #define SAA7127_REG_STATUS 0x00 | ||
101 | #define SAA7127_REG_WIDESCREEN_CONFIG 0x26 | ||
102 | #define SAA7127_REG_WIDESCREEN_ENABLE 0x27 | ||
103 | #define SAA7127_REG_BURST_START 0x28 | ||
104 | #define SAA7127_REG_BURST_END 0x29 | ||
105 | #define SAA7127_REG_COPYGEN_0 0x2a | ||
106 | #define SAA7127_REG_COPYGEN_1 0x2b | ||
107 | #define SAA7127_REG_COPYGEN_2 0x2c | ||
108 | #define SAA7127_REG_OUTPUT_PORT_CONTROL 0x2d | ||
109 | #define SAA7127_REG_GAIN_LUMINANCE_RGB 0x38 | ||
110 | #define SAA7127_REG_GAIN_COLORDIFF_RGB 0x39 | ||
111 | #define SAA7127_REG_INPUT_PORT_CONTROL_1 0x3a | ||
112 | #define SAA7129_REG_FADE_KEY_COL2 0x4f | ||
113 | #define SAA7127_REG_CHROMA_PHASE 0x5a | ||
114 | #define SAA7127_REG_GAINU 0x5b | ||
115 | #define SAA7127_REG_GAINV 0x5c | ||
116 | #define SAA7127_REG_BLACK_LEVEL 0x5d | ||
117 | #define SAA7127_REG_BLANKING_LEVEL 0x5e | ||
118 | #define SAA7127_REG_VBI_BLANKING 0x5f | ||
119 | #define SAA7127_REG_DAC_CONTROL 0x61 | ||
120 | #define SAA7127_REG_BURST_AMP 0x62 | ||
121 | #define SAA7127_REG_SUBC3 0x63 | ||
122 | #define SAA7127_REG_SUBC2 0x64 | ||
123 | #define SAA7127_REG_SUBC1 0x65 | ||
124 | #define SAA7127_REG_SUBC0 0x66 | ||
125 | #define SAA7127_REG_LINE_21_ODD_0 0x67 | ||
126 | #define SAA7127_REG_LINE_21_ODD_1 0x68 | ||
127 | #define SAA7127_REG_LINE_21_EVEN_0 0x69 | ||
128 | #define SAA7127_REG_LINE_21_EVEN_1 0x6a | ||
129 | #define SAA7127_REG_RCV_PORT_CONTROL 0x6b | ||
130 | #define SAA7127_REG_VTRIG 0x6c | ||
131 | #define SAA7127_REG_HTRIG_HI 0x6d | ||
132 | #define SAA7127_REG_MULTI 0x6e | ||
133 | #define SAA7127_REG_CLOSED_CAPTION 0x6f | ||
134 | #define SAA7127_REG_RCV2_OUTPUT_START 0x70 | ||
135 | #define SAA7127_REG_RCV2_OUTPUT_END 0x71 | ||
136 | #define SAA7127_REG_RCV2_OUTPUT_MSBS 0x72 | ||
137 | #define SAA7127_REG_TTX_REQUEST_H_START 0x73 | ||
138 | #define SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH 0x74 | ||
139 | #define SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT 0x75 | ||
140 | #define SAA7127_REG_TTX_ODD_REQ_VERT_START 0x76 | ||
141 | #define SAA7127_REG_TTX_ODD_REQ_VERT_END 0x77 | ||
142 | #define SAA7127_REG_TTX_EVEN_REQ_VERT_START 0x78 | ||
143 | #define SAA7127_REG_TTX_EVEN_REQ_VERT_END 0x79 | ||
144 | #define SAA7127_REG_FIRST_ACTIVE 0x7a | ||
145 | #define SAA7127_REG_LAST_ACTIVE 0x7b | ||
146 | #define SAA7127_REG_MSB_VERTICAL 0x7c | ||
147 | #define SAA7127_REG_DISABLE_TTX_LINE_LO_0 0x7e | ||
148 | #define SAA7127_REG_DISABLE_TTX_LINE_LO_1 0x7f | ||
149 | |||
150 | /* | ||
151 | ********************************************************************** | ||
152 | * | ||
153 | * Arrays with configuration parameters for the SAA7127 | ||
154 | * | ||
155 | ********************************************************************** | ||
156 | */ | ||
157 | |||
158 | struct i2c_reg_value { | ||
159 | unsigned char reg; | ||
160 | unsigned char value; | ||
161 | }; | ||
162 | |||
163 | static const struct i2c_reg_value saa7129_init_config_extra[] = { | ||
164 | { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x38 }, | ||
165 | { SAA7127_REG_VTRIG, 0xfa }, | ||
166 | }; | ||
167 | |||
168 | static const struct i2c_reg_value saa7127_init_config_common[] = { | ||
169 | { SAA7127_REG_WIDESCREEN_CONFIG, 0x0d }, | ||
170 | { SAA7127_REG_WIDESCREEN_ENABLE, 0x00 }, | ||
171 | { SAA7127_REG_COPYGEN_0, 0x77 }, | ||
172 | { SAA7127_REG_COPYGEN_1, 0x41 }, | ||
173 | { SAA7127_REG_COPYGEN_2, 0x00 }, /* Macrovision enable/disable */ | ||
174 | { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x9e }, | ||
175 | { SAA7127_REG_GAIN_LUMINANCE_RGB, 0x00 }, | ||
176 | { SAA7127_REG_GAIN_COLORDIFF_RGB, 0x00 }, | ||
177 | { SAA7127_REG_INPUT_PORT_CONTROL_1, 0x80 }, /* for color bars */ | ||
178 | { SAA7127_REG_LINE_21_ODD_0, 0x77 }, | ||
179 | { SAA7127_REG_LINE_21_ODD_1, 0x41 }, | ||
180 | { SAA7127_REG_LINE_21_EVEN_0, 0x88 }, | ||
181 | { SAA7127_REG_LINE_21_EVEN_1, 0x41 }, | ||
182 | { SAA7127_REG_RCV_PORT_CONTROL, 0x12 }, | ||
183 | { SAA7127_REG_VTRIG, 0xf9 }, | ||
184 | { SAA7127_REG_HTRIG_HI, 0x00 }, | ||
185 | { SAA7127_REG_RCV2_OUTPUT_START, 0x41 }, | ||
186 | { SAA7127_REG_RCV2_OUTPUT_END, 0xc3 }, | ||
187 | { SAA7127_REG_RCV2_OUTPUT_MSBS, 0x00 }, | ||
188 | { SAA7127_REG_TTX_REQUEST_H_START, 0x3e }, | ||
189 | { SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH, 0xb8 }, | ||
190 | { SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT, 0x03 }, | ||
191 | { SAA7127_REG_TTX_ODD_REQ_VERT_START, 0x15 }, | ||
192 | { SAA7127_REG_TTX_ODD_REQ_VERT_END, 0x16 }, | ||
193 | { SAA7127_REG_TTX_EVEN_REQ_VERT_START, 0x15 }, | ||
194 | { SAA7127_REG_TTX_EVEN_REQ_VERT_END, 0x16 }, | ||
195 | { SAA7127_REG_FIRST_ACTIVE, 0x1a }, | ||
196 | { SAA7127_REG_LAST_ACTIVE, 0x01 }, | ||
197 | { SAA7127_REG_MSB_VERTICAL, 0xc0 }, | ||
198 | { SAA7127_REG_DISABLE_TTX_LINE_LO_0, 0x00 }, | ||
199 | { SAA7127_REG_DISABLE_TTX_LINE_LO_1, 0x00 }, | ||
200 | { 0, 0 } | ||
201 | }; | ||
202 | |||
203 | #define SAA7127_60HZ_DAC_CONTROL 0x15 | ||
204 | static const struct i2c_reg_value saa7127_init_config_60hz[] = { | ||
205 | { SAA7127_REG_BURST_START, 0x19 }, | ||
206 | /* BURST_END is also used as a chip ID in saa7127_detect_client */ | ||
207 | { SAA7127_REG_BURST_END, 0x1d }, | ||
208 | { SAA7127_REG_CHROMA_PHASE, 0xa3 }, | ||
209 | { SAA7127_REG_GAINU, 0x98 }, | ||
210 | { SAA7127_REG_GAINV, 0xd3 }, | ||
211 | { SAA7127_REG_BLACK_LEVEL, 0x39 }, | ||
212 | { SAA7127_REG_BLANKING_LEVEL, 0x2e }, | ||
213 | { SAA7127_REG_VBI_BLANKING, 0x2e }, | ||
214 | { SAA7127_REG_DAC_CONTROL, 0x15 }, | ||
215 | { SAA7127_REG_BURST_AMP, 0x4d }, | ||
216 | { SAA7127_REG_SUBC3, 0x1f }, | ||
217 | { SAA7127_REG_SUBC2, 0x7c }, | ||
218 | { SAA7127_REG_SUBC1, 0xf0 }, | ||
219 | { SAA7127_REG_SUBC0, 0x21 }, | ||
220 | { SAA7127_REG_MULTI, 0x90 }, | ||
221 | { SAA7127_REG_CLOSED_CAPTION, 0x11 }, | ||
222 | { 0, 0 } | ||
223 | }; | ||
224 | |||
225 | #define SAA7127_50HZ_DAC_CONTROL 0x02 | ||
226 | struct i2c_reg_value saa7127_init_config_50hz[] = { | ||
227 | { SAA7127_REG_BURST_START, 0x21 }, | ||
228 | /* BURST_END is also used as a chip ID in saa7127_detect_client */ | ||
229 | { SAA7127_REG_BURST_END, 0x1d }, | ||
230 | { SAA7127_REG_CHROMA_PHASE, 0x3f }, | ||
231 | { SAA7127_REG_GAINU, 0x7d }, | ||
232 | { SAA7127_REG_GAINV, 0xaf }, | ||
233 | { SAA7127_REG_BLACK_LEVEL, 0x33 }, | ||
234 | { SAA7127_REG_BLANKING_LEVEL, 0x35 }, | ||
235 | { SAA7127_REG_VBI_BLANKING, 0x35 }, | ||
236 | { SAA7127_REG_DAC_CONTROL, 0x02 }, | ||
237 | { SAA7127_REG_BURST_AMP, 0x2f }, | ||
238 | { SAA7127_REG_SUBC3, 0xcb }, | ||
239 | { SAA7127_REG_SUBC2, 0x8a }, | ||
240 | { SAA7127_REG_SUBC1, 0x09 }, | ||
241 | { SAA7127_REG_SUBC0, 0x2a }, | ||
242 | { SAA7127_REG_MULTI, 0xa0 }, | ||
243 | { SAA7127_REG_CLOSED_CAPTION, 0x00 }, | ||
244 | { 0, 0 } | ||
245 | }; | ||
246 | |||
247 | /* Enumeration for the Supported input types */ | ||
248 | enum saa7127_input_type { | ||
249 | SAA7127_INPUT_TYPE_NORMAL, | ||
250 | SAA7127_INPUT_TYPE_TEST_IMAGE | ||
251 | }; | ||
252 | |||
253 | /* Enumeration for the Supported Output signal types */ | ||
254 | enum saa7127_output_type { | ||
255 | SAA7127_OUTPUT_TYPE_BOTH, | ||
256 | SAA7127_OUTPUT_TYPE_COMPOSITE, | ||
257 | SAA7127_OUTPUT_TYPE_SVIDEO, | ||
258 | SAA7127_OUTPUT_TYPE_RGB, | ||
259 | SAA7127_OUTPUT_TYPE_YUV_C, | ||
260 | SAA7127_OUTPUT_TYPE_YUV_V | ||
261 | }; | ||
262 | |||
263 | /* | ||
264 | ********************************************************************** | ||
265 | * | ||
266 | * Encoder Struct, holds the configuration state of the encoder | ||
267 | * | ||
268 | ********************************************************************** | ||
269 | */ | ||
270 | |||
271 | struct saa7127_state { | ||
272 | v4l2_std_id std; | ||
273 | enum v4l2_chip_ident ident; | ||
274 | enum saa7127_input_type input_type; | ||
275 | enum saa7127_output_type output_type; | ||
276 | int video_enable; | ||
277 | int wss_enable; | ||
278 | u16 wss_mode; | ||
279 | int cc_enable; | ||
280 | u16 cc_data; | ||
281 | int xds_enable; | ||
282 | u16 xds_data; | ||
283 | int vps_enable; | ||
284 | u8 vps_data[5]; | ||
285 | u8 reg_2d; | ||
286 | u8 reg_3a; | ||
287 | u8 reg_3a_cb; /* colorbar bit */ | ||
288 | u8 reg_61; | ||
289 | }; | ||
290 | |||
291 | static const char * const output_strs[] = | ||
292 | { | ||
293 | "S-Video + Composite", | ||
294 | "Composite", | ||
295 | "S-Video", | ||
296 | "RGB", | ||
297 | "YUV C", | ||
298 | "YUV V" | ||
299 | }; | ||
300 | |||
301 | static const char * const wss_strs[] = { | ||
302 | "invalid", | ||
303 | "letterbox 14:9 center", | ||
304 | "letterbox 14:9 top", | ||
305 | "invalid", | ||
306 | "letterbox 16:9 top", | ||
307 | "invalid", | ||
308 | "invalid", | ||
309 | "16:9 full format anamorphic" | ||
310 | "4:3 full format", | ||
311 | "invalid", | ||
312 | "invalid", | ||
313 | "letterbox 16:9 center", | ||
314 | "invalid", | ||
315 | "letterbox >16:9 center", | ||
316 | "14:9 full format center", | ||
317 | "invalid", | ||
318 | }; | ||
319 | |||
320 | /* ----------------------------------------------------------------------- */ | ||
321 | |||
322 | static int saa7127_read(struct i2c_client *client, u8 reg) | ||
323 | { | ||
324 | return i2c_smbus_read_byte_data(client, reg); | ||
325 | } | ||
326 | |||
327 | /* ----------------------------------------------------------------------- */ | ||
328 | |||
329 | static int saa7127_write(struct i2c_client *client, u8 reg, u8 val) | ||
330 | { | ||
331 | int i; | ||
332 | |||
333 | for (i = 0; i < 3; i++) { | ||
334 | if (i2c_smbus_write_byte_data(client, reg, val) == 0) | ||
335 | return 0; | ||
336 | } | ||
337 | saa7127_err("I2C Write Problem\n"); | ||
338 | return -1; | ||
339 | } | ||
340 | |||
341 | /* ----------------------------------------------------------------------- */ | ||
342 | |||
343 | static int saa7127_write_inittab(struct i2c_client *client, | ||
344 | const struct i2c_reg_value *regs) | ||
345 | { | ||
346 | while (regs->reg != 0) { | ||
347 | saa7127_write(client, regs->reg, regs->value); | ||
348 | regs++; | ||
349 | } | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | /* ----------------------------------------------------------------------- */ | ||
354 | |||
355 | static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) | ||
356 | { | ||
357 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
358 | int enable = (data->line != 0); | ||
359 | |||
360 | if (enable && (data->field != 0 || data->line != 16)) | ||
361 | return -EINVAL; | ||
362 | if (state->vps_enable != enable) { | ||
363 | saa7127_dbg("Turn VPS Signal %s\n", enable ? "on" : "off"); | ||
364 | saa7127_write(client, 0x54, enable << 7); | ||
365 | state->vps_enable = enable; | ||
366 | } | ||
367 | if (!enable) | ||
368 | return 0; | ||
369 | |||
370 | state->vps_data[0] = data->data[4]; | ||
371 | state->vps_data[1] = data->data[10]; | ||
372 | state->vps_data[2] = data->data[11]; | ||
373 | state->vps_data[3] = data->data[12]; | ||
374 | state->vps_data[4] = data->data[13]; | ||
375 | saa7127_dbg("Set VPS data %02x %02x %02x %02x %02x\n", | ||
376 | state->vps_data[0], state->vps_data[1], | ||
377 | state->vps_data[2], state->vps_data[3], | ||
378 | state->vps_data[4]); | ||
379 | saa7127_write(client, 0x55, state->vps_data[0]); | ||
380 | saa7127_write(client, 0x56, state->vps_data[1]); | ||
381 | saa7127_write(client, 0x57, state->vps_data[2]); | ||
382 | saa7127_write(client, 0x58, state->vps_data[3]); | ||
383 | saa7127_write(client, 0x59, state->vps_data[4]); | ||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | /* ----------------------------------------------------------------------- */ | ||
388 | |||
389 | static int saa7127_set_cc(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) | ||
390 | { | ||
391 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
392 | u16 cc = data->data[0] << 8 | data->data[1]; | ||
393 | int enable = (data->line != 0); | ||
394 | |||
395 | if (enable && (data->field != 0 || data->line != 21)) | ||
396 | return -EINVAL; | ||
397 | if (state->cc_enable != enable) { | ||
398 | saa7127_dbg("Turn CC %s\n", enable ? "on" : "off"); | ||
399 | saa7127_write(client, SAA7127_REG_CLOSED_CAPTION, | ||
400 | (enable << 6) | 0x11); | ||
401 | state->cc_enable = enable; | ||
402 | } | ||
403 | if (!enable) | ||
404 | return 0; | ||
405 | |||
406 | saa7127_dbg_highvol("CC data: %04x\n", cc); | ||
407 | saa7127_write(client, SAA7127_REG_LINE_21_ODD_0, cc & 0xff); | ||
408 | saa7127_write(client, SAA7127_REG_LINE_21_ODD_1, cc >> 8); | ||
409 | state->cc_data = cc; | ||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | /* ----------------------------------------------------------------------- */ | ||
414 | |||
415 | static int saa7127_set_xds(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) | ||
416 | { | ||
417 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
418 | u16 xds = data->data[1] << 8 | data->data[0]; | ||
419 | int enable = (data->line != 0); | ||
420 | |||
421 | if (enable && (data->field != 1 || data->line != 21)) | ||
422 | return -EINVAL; | ||
423 | if (state->xds_enable != enable) { | ||
424 | saa7127_dbg("Turn XDS %s\n", enable ? "on" : "off"); | ||
425 | saa7127_write(client, SAA7127_REG_CLOSED_CAPTION, | ||
426 | (enable << 7) | 0x11); | ||
427 | state->xds_enable = enable; | ||
428 | } | ||
429 | if (!enable) | ||
430 | return 0; | ||
431 | |||
432 | saa7127_dbg_highvol("XDS data: %04x\n", xds); | ||
433 | saa7127_write(client, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff); | ||
434 | saa7127_write(client, SAA7127_REG_LINE_21_EVEN_1, xds >> 8); | ||
435 | state->xds_data = xds; | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | /* ----------------------------------------------------------------------- */ | ||
440 | |||
441 | static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) | ||
442 | { | ||
443 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
444 | int enable = (data->line != 0); | ||
445 | |||
446 | if (enable && (data->field != 0 || data->line != 23)) | ||
447 | return -EINVAL; | ||
448 | if (state->wss_enable != enable) { | ||
449 | saa7127_dbg("Turn WSS %s\n", enable ? "on" : "off"); | ||
450 | saa7127_write(client, 0x27, enable << 7); | ||
451 | state->wss_enable = enable; | ||
452 | } | ||
453 | if (!enable) | ||
454 | return 0; | ||
455 | |||
456 | saa7127_write(client, 0x26, data->data[0]); | ||
457 | saa7127_write(client, 0x27, 0x80 | (data->data[1] & 0x3f)); | ||
458 | saa7127_dbg("WSS mode: %s\n", wss_strs[data->data[0] & 0xf]); | ||
459 | state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0]; | ||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | /* ----------------------------------------------------------------------- */ | ||
464 | |||
465 | static int saa7127_set_video_enable(struct i2c_client *client, int enable) | ||
466 | { | ||
467 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
468 | |||
469 | if (enable) { | ||
470 | saa7127_dbg("Enable Video Output\n"); | ||
471 | saa7127_write(client, 0x2d, state->reg_2d); | ||
472 | saa7127_write(client, 0x61, state->reg_61); | ||
473 | } else { | ||
474 | saa7127_dbg("Disable Video Output\n"); | ||
475 | saa7127_write(client, 0x2d, (state->reg_2d & 0xf0)); | ||
476 | saa7127_write(client, 0x61, (state->reg_61 | 0xc0)); | ||
477 | } | ||
478 | state->video_enable = enable; | ||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | /* ----------------------------------------------------------------------- */ | ||
483 | |||
484 | static int saa7127_set_std(struct i2c_client *client, v4l2_std_id std) | ||
485 | { | ||
486 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
487 | const struct i2c_reg_value *inittab; | ||
488 | |||
489 | if (std & V4L2_STD_525_60) { | ||
490 | saa7127_dbg("Selecting 60 Hz video Standard\n"); | ||
491 | inittab = saa7127_init_config_60hz; | ||
492 | state->reg_61 = SAA7127_60HZ_DAC_CONTROL; | ||
493 | } else { | ||
494 | saa7127_dbg("Selecting 50 Hz video Standard\n"); | ||
495 | inittab = saa7127_init_config_50hz; | ||
496 | state->reg_61 = SAA7127_50HZ_DAC_CONTROL; | ||
497 | } | ||
498 | |||
499 | /* Write Table */ | ||
500 | saa7127_write_inittab(client, inittab); | ||
501 | state->std = std; | ||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | /* ----------------------------------------------------------------------- */ | ||
506 | |||
507 | static int saa7127_set_output_type(struct i2c_client *client, int output) | ||
508 | { | ||
509 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
510 | |||
511 | switch (output) { | ||
512 | case SAA7127_OUTPUT_TYPE_RGB: | ||
513 | state->reg_2d = 0x0f; /* RGB + CVBS (for sync) */ | ||
514 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | ||
515 | break; | ||
516 | |||
517 | case SAA7127_OUTPUT_TYPE_COMPOSITE: | ||
518 | state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */ | ||
519 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | ||
520 | break; | ||
521 | |||
522 | case SAA7127_OUTPUT_TYPE_SVIDEO: | ||
523 | state->reg_2d = 0xff; /* 11111111 croma -> R, luma -> CVBS + G + B */ | ||
524 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | ||
525 | break; | ||
526 | |||
527 | case SAA7127_OUTPUT_TYPE_YUV_V: | ||
528 | state->reg_2d = 0x4f; /* reg 2D = 01001111, all DAC's on, RGB + VBS */ | ||
529 | state->reg_3a = 0x0b; /* reg 3A = 00001011, bypass RGB-matrix */ | ||
530 | break; | ||
531 | |||
532 | case SAA7127_OUTPUT_TYPE_YUV_C: | ||
533 | state->reg_2d = 0x0f; /* reg 2D = 00001111, all DAC's on, RGB + CVBS */ | ||
534 | state->reg_3a = 0x0b; /* reg 3A = 00001011, bypass RGB-matrix */ | ||
535 | break; | ||
536 | |||
537 | case SAA7127_OUTPUT_TYPE_BOTH: | ||
538 | state->reg_2d = 0xbf; | ||
539 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | ||
540 | break; | ||
541 | |||
542 | default: | ||
543 | return -EINVAL; | ||
544 | } | ||
545 | saa7127_dbg("Selecting %s output type\n", output_strs[output]); | ||
546 | |||
547 | /* Configure Encoder */ | ||
548 | saa7127_write(client, 0x2d, state->reg_2d); | ||
549 | saa7127_write(client, 0x3a, state->reg_3a | state->reg_3a_cb); | ||
550 | state->output_type = output; | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | /* ----------------------------------------------------------------------- */ | ||
555 | |||
556 | static int saa7127_set_input_type(struct i2c_client *client, int input) | ||
557 | { | ||
558 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
559 | |||
560 | switch (input) { | ||
561 | case SAA7127_INPUT_TYPE_NORMAL: /* avia */ | ||
562 | saa7127_dbg("Selecting Normal Encoder Input\n"); | ||
563 | state->reg_3a_cb = 0; | ||
564 | break; | ||
565 | |||
566 | case SAA7127_INPUT_TYPE_TEST_IMAGE: /* color bar */ | ||
567 | saa7127_dbg("Selecting Color Bar generator\n"); | ||
568 | state->reg_3a_cb = 0x80; | ||
569 | break; | ||
570 | |||
571 | default: | ||
572 | return -EINVAL; | ||
573 | } | ||
574 | saa7127_write(client, 0x3a, state->reg_3a | state->reg_3a_cb); | ||
575 | state->input_type = input; | ||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | /* ----------------------------------------------------------------------- */ | ||
580 | |||
581 | static int saa7127_command(struct i2c_client *client, | ||
582 | unsigned int cmd, void *arg) | ||
583 | { | ||
584 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
585 | struct v4l2_format *fmt = arg; | ||
586 | int *iarg = arg; | ||
587 | |||
588 | switch (cmd) { | ||
589 | case VIDIOC_S_STD: | ||
590 | if (state->std == *(v4l2_std_id *)arg) | ||
591 | break; | ||
592 | return saa7127_set_std(client, *(v4l2_std_id *)arg); | ||
593 | |||
594 | case VIDIOC_G_STD: | ||
595 | *(v4l2_std_id *)arg = state->std; | ||
596 | break; | ||
597 | |||
598 | case VIDIOC_S_INPUT: | ||
599 | if (state->input_type == *iarg) | ||
600 | break; | ||
601 | return saa7127_set_input_type(client, *iarg); | ||
602 | |||
603 | case VIDIOC_S_OUTPUT: | ||
604 | if (state->output_type == *iarg) | ||
605 | break; | ||
606 | return saa7127_set_output_type(client, *iarg); | ||
607 | |||
608 | case VIDIOC_STREAMON: | ||
609 | case VIDIOC_STREAMOFF: | ||
610 | if (state->video_enable == (cmd == VIDIOC_STREAMON)) | ||
611 | break; | ||
612 | return saa7127_set_video_enable(client, cmd == VIDIOC_STREAMON); | ||
613 | |||
614 | case VIDIOC_G_FMT: | ||
615 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
616 | return -EINVAL; | ||
617 | |||
618 | memset(&fmt->fmt.sliced, 0, sizeof(fmt->fmt.sliced)); | ||
619 | if (state->vps_enable) | ||
620 | fmt->fmt.sliced.service_lines[0][16] = V4L2_SLICED_VPS; | ||
621 | if (state->wss_enable) | ||
622 | fmt->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625; | ||
623 | if (state->cc_enable) { | ||
624 | fmt->fmt.sliced.service_lines[0][21] = V4L2_SLICED_CAPTION_525; | ||
625 | fmt->fmt.sliced.service_lines[1][21] = V4L2_SLICED_CAPTION_525; | ||
626 | } | ||
627 | fmt->fmt.sliced.service_set = | ||
628 | (state->vps_enable ? V4L2_SLICED_VPS : 0) | | ||
629 | (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) | | ||
630 | (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0); | ||
631 | break; | ||
632 | |||
633 | case VIDIOC_LOG_STATUS: | ||
634 | saa7127_info("Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz"); | ||
635 | saa7127_info("Input: %s\n", state->input_type ? "color bars" : "normal"); | ||
636 | saa7127_info("Output: %s\n", state->video_enable ? | ||
637 | output_strs[state->output_type] : "disabled"); | ||
638 | saa7127_info("WSS: %s\n", state->wss_enable ? | ||
639 | wss_strs[state->wss_mode] : "disabled"); | ||
640 | saa7127_info("VPS: %s\n", state->vps_enable ? "enabled" : "disabled"); | ||
641 | saa7127_info("CC: %s\n", state->cc_enable ? "enabled" : "disabled"); | ||
642 | break; | ||
643 | |||
644 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
645 | case VIDIOC_INT_G_REGISTER: | ||
646 | { | ||
647 | struct v4l2_register *reg = arg; | ||
648 | |||
649 | if (reg->i2c_id != I2C_DRIVERID_SAA7127) | ||
650 | return -EINVAL; | ||
651 | reg->val = saa7127_read(client, reg->reg & 0xff); | ||
652 | break; | ||
653 | } | ||
654 | |||
655 | case VIDIOC_INT_S_REGISTER: | ||
656 | { | ||
657 | struct v4l2_register *reg = arg; | ||
658 | |||
659 | if (reg->i2c_id != I2C_DRIVERID_SAA7127) | ||
660 | return -EINVAL; | ||
661 | if (!capable(CAP_SYS_ADMIN)) | ||
662 | return -EPERM; | ||
663 | saa7127_write(client, reg->reg & 0xff, reg->val & 0xff); | ||
664 | break; | ||
665 | } | ||
666 | #endif | ||
667 | |||
668 | case VIDIOC_INT_S_VBI_DATA: | ||
669 | { | ||
670 | struct v4l2_sliced_vbi_data *data = arg; | ||
671 | |||
672 | switch (data->id) { | ||
673 | case V4L2_SLICED_WSS_625: | ||
674 | return saa7127_set_wss(client, data); | ||
675 | case V4L2_SLICED_VPS: | ||
676 | return saa7127_set_vps(client, data); | ||
677 | case V4L2_SLICED_CAPTION_525: | ||
678 | if (data->field == 0) | ||
679 | return saa7127_set_cc(client, data); | ||
680 | return saa7127_set_xds(client, data); | ||
681 | default: | ||
682 | return -EINVAL; | ||
683 | } | ||
684 | break; | ||
685 | } | ||
686 | |||
687 | case VIDIOC_INT_G_CHIP_IDENT: | ||
688 | *(enum v4l2_chip_ident *)arg = state->ident; | ||
689 | break; | ||
690 | |||
691 | default: | ||
692 | return -EINVAL; | ||
693 | } | ||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | /* ----------------------------------------------------------------------- */ | ||
698 | |||
699 | struct i2c_driver i2c_driver_saa7127; | ||
700 | |||
701 | /* ----------------------------------------------------------------------- */ | ||
702 | |||
703 | static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind) | ||
704 | { | ||
705 | struct i2c_client *client; | ||
706 | struct saa7127_state *state; | ||
707 | struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */ | ||
708 | int read_result = 0; | ||
709 | |||
710 | /* Check if the adapter supports the needed features */ | ||
711 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
712 | return 0; | ||
713 | |||
714 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
715 | if (client == 0) | ||
716 | return -ENOMEM; | ||
717 | |||
718 | memset(client, 0, sizeof(struct i2c_client)); | ||
719 | client->addr = address; | ||
720 | client->adapter = adapter; | ||
721 | client->driver = &i2c_driver_saa7127; | ||
722 | client->flags = I2C_CLIENT_ALLOW_USE; | ||
723 | snprintf(client->name, sizeof(client->name) - 1, "saa7127"); | ||
724 | |||
725 | saa7127_dbg("detecting saa7127 client on address 0x%x\n", address << 1); | ||
726 | |||
727 | /* First test register 0: Bits 5-7 are a version ID (should be 0), | ||
728 | and bit 2 should also be 0. | ||
729 | This is rather general, so the second test is more specific and | ||
730 | looks at the 'ending point of burst in clock cycles' which is | ||
731 | 0x1d after a reset and not expected to ever change. */ | ||
732 | if ((saa7127_read(client, 0) & 0xe4) != 0 || | ||
733 | (saa7127_read(client, 0x29) & 0x3f) != 0x1d) { | ||
734 | saa7127_dbg("saa7127 not found\n"); | ||
735 | kfree(client); | ||
736 | return 0; | ||
737 | } | ||
738 | state = kmalloc(sizeof(struct saa7127_state), GFP_KERNEL); | ||
739 | |||
740 | if (state == NULL) { | ||
741 | kfree(client); | ||
742 | return (-ENOMEM); | ||
743 | } | ||
744 | |||
745 | i2c_set_clientdata(client, state); | ||
746 | memset(state, 0, sizeof(struct saa7127_state)); | ||
747 | |||
748 | /* Configure Encoder */ | ||
749 | |||
750 | saa7127_dbg("Configuring encoder\n"); | ||
751 | saa7127_write_inittab(client, saa7127_init_config_common); | ||
752 | saa7127_set_std(client, V4L2_STD_NTSC); | ||
753 | saa7127_set_output_type(client, SAA7127_OUTPUT_TYPE_BOTH); | ||
754 | saa7127_set_vps(client, &vbi); | ||
755 | saa7127_set_wss(client, &vbi); | ||
756 | saa7127_set_cc(client, &vbi); | ||
757 | saa7127_set_xds(client, &vbi); | ||
758 | if (test_image == 1) { | ||
759 | /* The Encoder has an internal Colorbar generator */ | ||
760 | /* This can be used for debugging */ | ||
761 | saa7127_set_input_type(client, SAA7127_INPUT_TYPE_TEST_IMAGE); | ||
762 | } else { | ||
763 | saa7127_set_input_type(client, SAA7127_INPUT_TYPE_NORMAL); | ||
764 | } | ||
765 | saa7127_set_video_enable(client, 1); | ||
766 | |||
767 | /* Detect if it's an saa7129 */ | ||
768 | read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2); | ||
769 | saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa); | ||
770 | if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) { | ||
771 | saa7127_info("saa7129 found @ 0x%x (%s)\n", address << 1, adapter->name); | ||
772 | saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, read_result); | ||
773 | saa7127_write_inittab(client, saa7129_init_config_extra); | ||
774 | state->ident = V4L2_IDENT_SAA7129; | ||
775 | } else { | ||
776 | saa7127_info("saa7127 found @ 0x%x (%s)\n", address << 1, adapter->name); | ||
777 | state->ident = V4L2_IDENT_SAA7127; | ||
778 | } | ||
779 | |||
780 | i2c_attach_client(client); | ||
781 | |||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | /* ----------------------------------------------------------------------- */ | ||
786 | |||
787 | static int saa7127_probe(struct i2c_adapter *adapter) | ||
788 | { | ||
789 | #ifdef I2C_CLASS_TV_ANALOG | ||
790 | if (adapter->class & I2C_CLASS_TV_ANALOG) | ||
791 | #else | ||
792 | if (adapter->id == I2C_HW_B_BT848) | ||
793 | #endif | ||
794 | return i2c_probe(adapter, &addr_data, saa7127_attach); | ||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | /* ----------------------------------------------------------------------- */ | ||
799 | |||
800 | static int saa7127_detach(struct i2c_client *client) | ||
801 | { | ||
802 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
803 | int err; | ||
804 | |||
805 | /* Turn off TV output */ | ||
806 | saa7127_set_video_enable(client, 0); | ||
807 | |||
808 | err = i2c_detach_client(client); | ||
809 | |||
810 | if (err) { | ||
811 | return err; | ||
812 | } | ||
813 | |||
814 | kfree(state); | ||
815 | kfree(client); | ||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | /* ----------------------------------------------------------------------- */ | ||
820 | |||
821 | struct i2c_driver i2c_driver_saa7127 = { | ||
822 | .name = "saa7127", | ||
823 | .id = I2C_DRIVERID_SAA7127, | ||
824 | .flags = I2C_DF_NOTIFY, | ||
825 | .attach_adapter = saa7127_probe, | ||
826 | .detach_client = saa7127_detach, | ||
827 | .command = saa7127_command, | ||
828 | .owner = THIS_MODULE, | ||
829 | }; | ||
830 | |||
831 | |||
832 | /* ----------------------------------------------------------------------- */ | ||
833 | |||
834 | static int __init saa7127_init_module(void) | ||
835 | { | ||
836 | return i2c_add_driver(&i2c_driver_saa7127); | ||
837 | } | ||
838 | |||
839 | /* ----------------------------------------------------------------------- */ | ||
840 | |||
841 | static void __exit saa7127_cleanup_module(void) | ||
842 | { | ||
843 | i2c_del_driver(&i2c_driver_saa7127); | ||
844 | } | ||
845 | |||
846 | /* ----------------------------------------------------------------------- */ | ||
847 | |||
848 | module_init(saa7127_init_module); | ||
849 | module_exit(saa7127_cleanup_module); | ||
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 624e8808a517..7bdeabe638ca 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig | |||
@@ -1,10 +1,11 @@ | |||
1 | config VIDEO_SAA7134 | 1 | config VIDEO_SAA7134 |
2 | tristate "Philips SAA7134 support" | 2 | tristate "Philips SAA7134 support" |
3 | depends on VIDEO_DEV && PCI && I2C && SOUND | 3 | depends on VIDEO_DEV && PCI && I2C && SOUND && SND |
4 | select VIDEO_BUF | 4 | select VIDEO_BUF |
5 | select VIDEO_IR | 5 | select VIDEO_IR |
6 | select VIDEO_TUNER | 6 | select VIDEO_TUNER |
7 | select CRC32 | 7 | select CRC32 |
8 | select SND_PCM_OSS | ||
8 | ---help--- | 9 | ---help--- |
9 | This is a video4linux driver for Philips SAA713x based | 10 | This is a video4linux driver for Philips SAA713x based |
10 | TV cards. | 11 | TV cards. |
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile index e0b28f0533af..4226b61cc613 100644 --- a/drivers/media/video/saa7134/Makefile +++ b/drivers/media/video/saa7134/Makefile | |||
@@ -1,10 +1,11 @@ | |||
1 | 1 | ||
2 | saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \ | 2 | saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \ |
3 | saa7134-oss.o saa7134-ts.o saa7134-tvaudio.o \ | 3 | saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o \ |
4 | saa7134-vbi.o saa7134-video.o saa7134-input.o | 4 | saa7134-video.o saa7134-input.o |
5 | 5 | ||
6 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o \ | 6 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o \ |
7 | saa6752hs.o saa7134-alsa.o | 7 | saa6752hs.o saa7134-alsa.o \ |
8 | saa7134-oss.o | ||
8 | obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o | 9 | obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o |
9 | 10 | ||
10 | EXTRA_CFLAGS += -I$(src)/.. | 11 | EXTRA_CFLAGS += -I$(src)/.. |
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 4f3c42354329..5707c666660b 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -30,7 +30,9 @@ | |||
30 | #include <sound/core.h> | 30 | #include <sound/core.h> |
31 | #include <sound/control.h> | 31 | #include <sound/control.h> |
32 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
33 | #include <sound/pcm_params.h> | ||
33 | #include <sound/initval.h> | 34 | #include <sound/initval.h> |
35 | #include <linux/interrupt.h> | ||
34 | 36 | ||
35 | #include "saa7134.h" | 37 | #include "saa7134.h" |
36 | #include "saa7134-reg.h" | 38 | #include "saa7134-reg.h" |
@@ -56,6 +58,8 @@ static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; | |||
56 | module_param_array(index, int, NULL, 0444); | 58 | module_param_array(index, int, NULL, 0444); |
57 | MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s)."); | 59 | MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s)."); |
58 | 60 | ||
61 | int position; | ||
62 | |||
59 | #define dprintk(fmt, arg...) if (debug) \ | 63 | #define dprintk(fmt, arg...) if (debug) \ |
60 | printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) | 64 | printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) |
61 | 65 | ||
@@ -68,7 +72,7 @@ typedef struct snd_card_saa7134 { | |||
68 | int mixer_volume[MIXER_ADDR_LAST+1][2]; | 72 | int mixer_volume[MIXER_ADDR_LAST+1][2]; |
69 | int capture_source[MIXER_ADDR_LAST+1][2]; | 73 | int capture_source[MIXER_ADDR_LAST+1][2]; |
70 | struct pci_dev *pci; | 74 | struct pci_dev *pci; |
71 | struct saa7134_dev *saadev; | 75 | struct saa7134_dev *dev; |
72 | 76 | ||
73 | unsigned long iobase; | 77 | unsigned long iobase; |
74 | int irq; | 78 | int irq; |
@@ -83,12 +87,10 @@ typedef struct snd_card_saa7134 { | |||
83 | */ | 87 | */ |
84 | 88 | ||
85 | typedef struct snd_card_saa7134_pcm { | 89 | typedef struct snd_card_saa7134_pcm { |
86 | struct saa7134_dev *saadev; | 90 | struct saa7134_dev *dev; |
87 | 91 | ||
88 | spinlock_t lock; | 92 | spinlock_t lock; |
89 | unsigned int pcm_size; /* buffer size */ | 93 | |
90 | unsigned int pcm_count; /* bytes per period */ | ||
91 | unsigned int pcm_bps; /* bytes per second */ | ||
92 | snd_pcm_substream_t *substream; | 94 | snd_pcm_substream_t *substream; |
93 | } snd_card_saa7134_pcm_t; | 95 | } snd_card_saa7134_pcm_t; |
94 | 96 | ||
@@ -100,13 +102,11 @@ static snd_card_t *snd_saa7134_cards[SNDRV_CARDS]; | |||
100 | * | 102 | * |
101 | * Called when the capture device is released or the buffer overflows | 103 | * Called when the capture device is released or the buffer overflows |
102 | * | 104 | * |
103 | * - Copied verbatim from saa7134-oss's dsp_dma_stop. Can be dropped | 105 | * - Copied verbatim from saa7134-oss's dsp_dma_stop. |
104 | * if we just share dsp_dma_stop and use it here | ||
105 | * | 106 | * |
106 | */ | 107 | */ |
107 | 108 | ||
108 | static void saa7134_dma_stop(struct saa7134_dev *dev) | 109 | static void saa7134_dma_stop(struct saa7134_dev *dev) |
109 | |||
110 | { | 110 | { |
111 | dev->dmasound.dma_blk = -1; | 111 | dev->dmasound.dma_blk = -1; |
112 | dev->dmasound.dma_running = 0; | 112 | dev->dmasound.dma_running = 0; |
@@ -118,8 +118,7 @@ static void saa7134_dma_stop(struct saa7134_dev *dev) | |||
118 | * | 118 | * |
119 | * Called when preparing the capture device for use | 119 | * Called when preparing the capture device for use |
120 | * | 120 | * |
121 | * - Copied verbatim from saa7134-oss's dsp_dma_start. Can be dropped | 121 | * - Copied verbatim from saa7134-oss's dsp_dma_start. |
122 | * if we just share dsp_dma_start and use it here | ||
123 | * | 122 | * |
124 | */ | 123 | */ |
125 | 124 | ||
@@ -170,9 +169,9 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) | |||
170 | if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) { | 169 | if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) { |
171 | dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count, | 170 | dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count, |
172 | dev->dmasound.bufsize, dev->dmasound.blocks); | 171 | dev->dmasound.bufsize, dev->dmasound.blocks); |
172 | spin_unlock(&dev->slock); | ||
173 | snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN); | 173 | snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN); |
174 | saa7134_dma_stop(dev); | 174 | return; |
175 | goto done; | ||
176 | } | 175 | } |
177 | 176 | ||
178 | /* next block addr */ | 177 | /* next block addr */ |
@@ -194,6 +193,7 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) | |||
194 | snd_pcm_period_elapsed(dev->dmasound.substream); | 193 | snd_pcm_period_elapsed(dev->dmasound.substream); |
195 | spin_lock(&dev->slock); | 194 | spin_lock(&dev->slock); |
196 | } | 195 | } |
196 | |||
197 | done: | 197 | done: |
198 | spin_unlock(&dev->slock); | 198 | spin_unlock(&dev->slock); |
199 | 199 | ||
@@ -209,7 +209,9 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) | |||
209 | 209 | ||
210 | static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id, struct pt_regs *regs) | 210 | static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id, struct pt_regs *regs) |
211 | { | 211 | { |
212 | struct saa7134_dev *dev = (struct saa7134_dev*) dev_id; | 212 | struct saa7134_dmasound *dmasound = dev_id; |
213 | struct saa7134_dev *dev = dmasound->priv_data; | ||
214 | |||
213 | unsigned long report, status; | 215 | unsigned long report, status; |
214 | int loop, handled = 0; | 216 | int loop, handled = 0; |
215 | 217 | ||
@@ -248,56 +250,23 @@ static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, | |||
248 | int cmd) | 250 | int cmd) |
249 | { | 251 | { |
250 | snd_pcm_runtime_t *runtime = substream->runtime; | 252 | snd_pcm_runtime_t *runtime = substream->runtime; |
251 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; | 253 | snd_card_saa7134_pcm_t *pcm = runtime->private_data; |
252 | struct saa7134_dev *dev=saapcm->saadev; | 254 | struct saa7134_dev *dev=pcm->dev; |
253 | int err = 0; | 255 | int err = 0; |
254 | 256 | ||
255 | spin_lock_irq(&dev->slock); | 257 | spin_lock(&dev->slock); |
256 | if (cmd == SNDRV_PCM_TRIGGER_START) { | 258 | if (cmd == SNDRV_PCM_TRIGGER_START) { |
257 | /* start dma */ | 259 | /* start dma */ |
258 | saa7134_dma_start(dev); | 260 | saa7134_dma_start(dev); |
259 | } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { | 261 | } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { |
260 | /* stop dma */ | 262 | /* stop dma */ |
261 | saa7134_dma_stop(dev); | 263 | saa7134_dma_stop(dev); |
262 | } else { | 264 | } else { |
263 | err = -EINVAL; | 265 | err = -EINVAL; |
264 | } | 266 | } |
265 | spin_unlock_irq(&dev->slock); | 267 | spin_unlock(&dev->slock); |
266 | |||
267 | return err; | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * DMA buffer config | ||
272 | * | ||
273 | * Sets the values that will later be used as the size of the buffer, | ||
274 | * size of the fragments, and total number of fragments. | ||
275 | * Must be called during the preparation stage, before memory is | ||
276 | * allocated | ||
277 | * | ||
278 | * - Copied verbatim from saa7134-oss. Can be dropped | ||
279 | * if we just share dsp_buffer_conf from OSS. | ||
280 | */ | ||
281 | 268 | ||
282 | static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) | 269 | return err; |
283 | { | ||
284 | if (blksize < 0x100) | ||
285 | blksize = 0x100; | ||
286 | if (blksize > 0x10000) | ||
287 | blksize = 0x10000; | ||
288 | |||
289 | if (blocks < 2) | ||
290 | blocks = 2; | ||
291 | if ((blksize * blocks) > 1024*1024) | ||
292 | blocks = 1024*1024 / blksize; | ||
293 | |||
294 | dev->dmasound.blocks = blocks; | ||
295 | dev->dmasound.blksize = blksize; | ||
296 | dev->dmasound.bufsize = blksize * blocks; | ||
297 | |||
298 | dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", | ||
299 | blocks,blksize,blksize * blocks / 1024); | ||
300 | return 0; | ||
301 | } | 270 | } |
302 | 271 | ||
303 | /* | 272 | /* |
@@ -307,16 +276,16 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) | |||
307 | * ALSA, but I was unable to use ALSA's own DMA, and had to force the | 276 | * ALSA, but I was unable to use ALSA's own DMA, and had to force the |
308 | * usage of V4L's | 277 | * usage of V4L's |
309 | * | 278 | * |
310 | * - Copied verbatim from saa7134-oss. Can be dropped | 279 | * - Copied verbatim from saa7134-oss. |
311 | * if we just share dsp_buffer_init from OSS. | 280 | * |
312 | */ | 281 | */ |
313 | 282 | ||
314 | static int dsp_buffer_init(struct saa7134_dev *dev) | 283 | static int dsp_buffer_init(struct saa7134_dev *dev) |
315 | { | 284 | { |
316 | int err; | 285 | int err; |
317 | 286 | ||
318 | if (!dev->dmasound.bufsize) | 287 | BUG_ON(!dev->dmasound.bufsize); |
319 | BUG(); | 288 | |
320 | videobuf_dma_init(&dev->dmasound.dma); | 289 | videobuf_dma_init(&dev->dmasound.dma); |
321 | err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE, | 290 | err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE, |
322 | (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT); | 291 | (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT); |
@@ -326,6 +295,28 @@ static int dsp_buffer_init(struct saa7134_dev *dev) | |||
326 | } | 295 | } |
327 | 296 | ||
328 | /* | 297 | /* |
298 | * DMA buffer release | ||
299 | * | ||
300 | * Called after closing the device, during snd_card_saa7134_capture_close | ||
301 | * | ||
302 | */ | ||
303 | |||
304 | static int dsp_buffer_free(struct saa7134_dev *dev) | ||
305 | { | ||
306 | if (!dev->dmasound.blksize) | ||
307 | BUG(); | ||
308 | |||
309 | videobuf_dma_free(&dev->dmasound.dma); | ||
310 | |||
311 | dev->dmasound.blocks = 0; | ||
312 | dev->dmasound.blksize = 0; | ||
313 | dev->dmasound.bufsize = 0; | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | |||
319 | /* | ||
329 | * ALSA PCM preparation | 320 | * ALSA PCM preparation |
330 | * | 321 | * |
331 | * - One of the ALSA capture callbacks. | 322 | * - One of the ALSA capture callbacks. |
@@ -340,84 +331,30 @@ static int dsp_buffer_init(struct saa7134_dev *dev) | |||
340 | static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | 331 | static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) |
341 | { | 332 | { |
342 | snd_pcm_runtime_t *runtime = substream->runtime; | 333 | snd_pcm_runtime_t *runtime = substream->runtime; |
343 | int err, bswap, sign; | 334 | int bswap, sign; |
344 | u32 fmt, control; | 335 | u32 fmt, control; |
345 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | 336 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
346 | struct saa7134_dev *dev; | 337 | struct saa7134_dev *dev; |
347 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; | 338 | snd_card_saa7134_pcm_t *pcm = runtime->private_data; |
348 | unsigned int bps; | ||
349 | unsigned long size; | ||
350 | unsigned count; | ||
351 | |||
352 | size = snd_pcm_lib_buffer_bytes(substream); | ||
353 | count = snd_pcm_lib_period_bytes(substream); | ||
354 | |||
355 | saapcm->saadev->dmasound.substream = substream; | ||
356 | bps = runtime->rate * runtime->channels; | ||
357 | bps *= snd_pcm_format_width(runtime->format); | ||
358 | bps /= 8; | ||
359 | if (bps <= 0) | ||
360 | return -EINVAL; | ||
361 | saapcm->pcm_bps = bps; | ||
362 | saapcm->pcm_size = snd_pcm_lib_buffer_bytes(substream); | ||
363 | saapcm->pcm_count = snd_pcm_lib_period_bytes(substream); | ||
364 | |||
365 | 339 | ||
366 | dev=saa7134->saadev; | 340 | pcm->dev->dmasound.substream = substream; |
367 | 341 | ||
368 | dsp_buffer_conf(dev,saapcm->pcm_count,(saapcm->pcm_size/saapcm->pcm_count)); | 342 | dev = saa7134->dev; |
369 | 343 | ||
370 | err = dsp_buffer_init(dev); | 344 | if (snd_pcm_format_width(runtime->format) == 8) |
371 | if (0 != err) | ||
372 | goto fail2; | ||
373 | |||
374 | /* prepare buffer */ | ||
375 | if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->dmasound.dma))) | ||
376 | return err; | ||
377 | if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) | ||
378 | goto fail1; | ||
379 | if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt, | ||
380 | dev->dmasound.dma.sglist, | ||
381 | dev->dmasound.dma.sglen, | ||
382 | 0))) | ||
383 | goto fail2; | ||
384 | |||
385 | |||
386 | |||
387 | switch (runtime->format) { | ||
388 | case SNDRV_PCM_FORMAT_U8: | ||
389 | case SNDRV_PCM_FORMAT_S8: | ||
390 | fmt = 0x00; | 345 | fmt = 0x00; |
391 | break; | 346 | else |
392 | case SNDRV_PCM_FORMAT_U16_LE: | ||
393 | case SNDRV_PCM_FORMAT_U16_BE: | ||
394 | case SNDRV_PCM_FORMAT_S16_LE: | ||
395 | case SNDRV_PCM_FORMAT_S16_BE: | ||
396 | fmt = 0x01; | 347 | fmt = 0x01; |
397 | break; | ||
398 | default: | ||
399 | err = -EINVAL; | ||
400 | return 1; | ||
401 | } | ||
402 | 348 | ||
403 | switch (runtime->format) { | 349 | if (snd_pcm_format_signed(runtime->format)) |
404 | case SNDRV_PCM_FORMAT_S8: | ||
405 | case SNDRV_PCM_FORMAT_S16_LE: | ||
406 | case SNDRV_PCM_FORMAT_S16_BE: | ||
407 | sign = 1; | 350 | sign = 1; |
408 | break; | 351 | else |
409 | default: | ||
410 | sign = 0; | 352 | sign = 0; |
411 | break; | ||
412 | } | ||
413 | 353 | ||
414 | switch (runtime->format) { | 354 | if (snd_pcm_format_big_endian(runtime->format)) |
415 | case SNDRV_PCM_FORMAT_U16_BE: | 355 | bswap = 1; |
416 | case SNDRV_PCM_FORMAT_S16_BE: | 356 | else |
417 | bswap = 1; break; | 357 | bswap = 0; |
418 | default: | ||
419 | bswap = 0; break; | ||
420 | } | ||
421 | 358 | ||
422 | switch (dev->pci->device) { | 359 | switch (dev->pci->device) { |
423 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | 360 | case PCI_DEVICE_ID_PHILIPS_SAA7134: |
@@ -445,7 +382,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | |||
445 | fmt |= 0x04; | 382 | fmt |= 0x04; |
446 | saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -1); | 383 | saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -1); |
447 | saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); | 384 | saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); |
448 | //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); | ||
449 | break; | 385 | break; |
450 | } | 386 | } |
451 | 387 | ||
@@ -459,12 +395,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | |||
459 | if (bswap) | 395 | if (bswap) |
460 | control |= SAA7134_RS_CONTROL_BSWAP; | 396 | control |= SAA7134_RS_CONTROL_BSWAP; |
461 | 397 | ||
462 | /* I should be able to use runtime->dma_addr in the control | ||
463 | byte, but it doesn't work. So I allocate the DMA using the | ||
464 | V4L functions, and force ALSA to use that as the DMA area */ | ||
465 | |||
466 | runtime->dma_area = dev->dmasound.dma.vmalloc; | ||
467 | |||
468 | saa_writel(SAA7134_RS_BA1(6),0); | 398 | saa_writel(SAA7134_RS_BA1(6),0); |
469 | saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize); | 399 | saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize); |
470 | saa_writel(SAA7134_RS_PITCH(6),0); | 400 | saa_writel(SAA7134_RS_PITCH(6),0); |
@@ -473,12 +403,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | |||
473 | dev->dmasound.rate = runtime->rate; | 403 | dev->dmasound.rate = runtime->rate; |
474 | 404 | ||
475 | return 0; | 405 | return 0; |
476 | fail2: | ||
477 | saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); | ||
478 | fail1: | ||
479 | videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); | ||
480 | return err; | ||
481 | |||
482 | 406 | ||
483 | } | 407 | } |
484 | 408 | ||
@@ -496,10 +420,8 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | |||
496 | static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream) | 420 | static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream) |
497 | { | 421 | { |
498 | snd_pcm_runtime_t *runtime = substream->runtime; | 422 | snd_pcm_runtime_t *runtime = substream->runtime; |
499 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; | 423 | snd_card_saa7134_pcm_t *pcm = runtime->private_data; |
500 | struct saa7134_dev *dev=saapcm->saadev; | 424 | struct saa7134_dev *dev=pcm->dev; |
501 | |||
502 | |||
503 | 425 | ||
504 | if (dev->dmasound.read_count) { | 426 | if (dev->dmasound.read_count) { |
505 | dev->dmasound.read_count -= snd_pcm_lib_period_bytes(substream); | 427 | dev->dmasound.read_count -= snd_pcm_lib_period_bytes(substream); |
@@ -540,9 +462,9 @@ static snd_pcm_hardware_t snd_card_saa7134_capture = | |||
540 | 462 | ||
541 | static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) | 463 | static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) |
542 | { | 464 | { |
543 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; | 465 | snd_card_saa7134_pcm_t *pcm = runtime->private_data; |
544 | 466 | ||
545 | kfree(saapcm); | 467 | kfree(pcm); |
546 | } | 468 | } |
547 | 469 | ||
548 | 470 | ||
@@ -552,17 +474,76 @@ static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) | |||
552 | * - One of the ALSA capture callbacks. | 474 | * - One of the ALSA capture callbacks. |
553 | * | 475 | * |
554 | * Called on initialization, right before the PCM preparation | 476 | * Called on initialization, right before the PCM preparation |
555 | * Usually used in ALSA to allocate the DMA, but since we don't use the | ||
556 | * ALSA DMA it does nothing | ||
557 | * | 477 | * |
558 | */ | 478 | */ |
559 | 479 | ||
560 | static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, | 480 | static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, |
561 | snd_pcm_hw_params_t * hw_params) | 481 | snd_pcm_hw_params_t * hw_params) |
562 | { | 482 | { |
483 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | ||
484 | struct saa7134_dev *dev; | ||
485 | unsigned int period_size, periods; | ||
486 | int err; | ||
563 | 487 | ||
564 | return 0; | 488 | period_size = params_period_bytes(hw_params); |
489 | periods = params_periods(hw_params); | ||
490 | |||
491 | snd_assert(period_size >= 0x100 && period_size <= 0x10000, | ||
492 | return -EINVAL); | ||
493 | snd_assert(periods >= 2, return -EINVAL); | ||
494 | snd_assert(period_size * periods <= 1024 * 1024, return -EINVAL); | ||
565 | 495 | ||
496 | dev = saa7134->dev; | ||
497 | |||
498 | if (dev->dmasound.blocks == periods && | ||
499 | dev->dmasound.blksize == period_size) | ||
500 | return 0; | ||
501 | |||
502 | /* release the old buffer */ | ||
503 | if (substream->runtime->dma_area) { | ||
504 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); | ||
505 | videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); | ||
506 | dsp_buffer_free(dev); | ||
507 | substream->runtime->dma_area = NULL; | ||
508 | } | ||
509 | dev->dmasound.blocks = periods; | ||
510 | dev->dmasound.blksize = period_size; | ||
511 | dev->dmasound.bufsize = period_size * periods; | ||
512 | |||
513 | err = dsp_buffer_init(dev); | ||
514 | if (0 != err) { | ||
515 | dev->dmasound.blocks = 0; | ||
516 | dev->dmasound.blksize = 0; | ||
517 | dev->dmasound.bufsize = 0; | ||
518 | return err; | ||
519 | } | ||
520 | |||
521 | if (0 != (err = videobuf_dma_pci_map(dev->pci, &dev->dmasound.dma))) { | ||
522 | dsp_buffer_free(dev); | ||
523 | return err; | ||
524 | } | ||
525 | if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) { | ||
526 | videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); | ||
527 | dsp_buffer_free(dev); | ||
528 | return err; | ||
529 | } | ||
530 | if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt, | ||
531 | dev->dmasound.dma.sglist, | ||
532 | dev->dmasound.dma.sglen, | ||
533 | 0))) { | ||
534 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); | ||
535 | videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); | ||
536 | dsp_buffer_free(dev); | ||
537 | return err; | ||
538 | } | ||
539 | |||
540 | /* I should be able to use runtime->dma_addr in the control | ||
541 | byte, but it doesn't work. So I allocate the DMA using the | ||
542 | V4L functions, and force ALSA to use that as the DMA area */ | ||
543 | |||
544 | substream->runtime->dma_area = dev->dmasound.dma.vmalloc; | ||
545 | |||
546 | return 1; | ||
566 | 547 | ||
567 | } | 548 | } |
568 | 549 | ||
@@ -572,33 +553,23 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, | |||
572 | * - One of the ALSA capture callbacks. | 553 | * - One of the ALSA capture callbacks. |
573 | * | 554 | * |
574 | * Called after closing the device, but before snd_card_saa7134_capture_close | 555 | * Called after closing the device, but before snd_card_saa7134_capture_close |
575 | * Usually used in ALSA to free the DMA, but since we don't use the | 556 | * It stops the DMA audio and releases the buffers. |
576 | * ALSA DMA I'm almost sure this isn't necessary. | ||
577 | * | 557 | * |
578 | */ | 558 | */ |
579 | 559 | ||
580 | static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) | 560 | static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) |
581 | { | 561 | { |
582 | return 0; | 562 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
583 | } | 563 | struct saa7134_dev *dev; |
584 | |||
585 | /* | ||
586 | * DMA buffer release | ||
587 | * | ||
588 | * Called after closing the device, during snd_card_saa7134_capture_close | ||
589 | * | ||
590 | */ | ||
591 | |||
592 | static int dsp_buffer_free(struct saa7134_dev *dev) | ||
593 | { | ||
594 | if (!dev->dmasound.blksize) | ||
595 | BUG(); | ||
596 | 564 | ||
597 | videobuf_dma_free(&dev->dmasound.dma); | 565 | dev = saa7134->dev; |
598 | 566 | ||
599 | dev->dmasound.blocks = 0; | 567 | if (substream->runtime->dma_area) { |
600 | dev->dmasound.blksize = 0; | 568 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); |
601 | dev->dmasound.bufsize = 0; | 569 | videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); |
570 | dsp_buffer_free(dev); | ||
571 | substream->runtime->dma_area = NULL; | ||
572 | } | ||
602 | 573 | ||
603 | return 0; | 574 | return 0; |
604 | } | 575 | } |
@@ -608,21 +579,12 @@ static int dsp_buffer_free(struct saa7134_dev *dev) | |||
608 | * | 579 | * |
609 | * - One of the ALSA capture callbacks. | 580 | * - One of the ALSA capture callbacks. |
610 | * | 581 | * |
611 | * Called after closing the device. It stops the DMA audio and releases | 582 | * Called after closing the device. |
612 | * the buffers | ||
613 | * | 583 | * |
614 | */ | 584 | */ |
615 | 585 | ||
616 | static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) | 586 | static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) |
617 | { | 587 | { |
618 | snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); | ||
619 | struct saa7134_dev *dev = chip->saadev; | ||
620 | |||
621 | /* unlock buffer */ | ||
622 | saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); | ||
623 | videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); | ||
624 | |||
625 | dsp_buffer_free(dev); | ||
626 | return 0; | 588 | return 0; |
627 | } | 589 | } |
628 | 590 | ||
@@ -639,29 +601,28 @@ static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) | |||
639 | static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) | 601 | static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) |
640 | { | 602 | { |
641 | snd_pcm_runtime_t *runtime = substream->runtime; | 603 | snd_pcm_runtime_t *runtime = substream->runtime; |
642 | snd_card_saa7134_pcm_t *saapcm; | 604 | snd_card_saa7134_pcm_t *pcm; |
643 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | 605 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
644 | struct saa7134_dev *dev = saa7134->saadev; | 606 | struct saa7134_dev *dev = saa7134->dev; |
645 | int err; | 607 | int err; |
646 | 608 | ||
647 | down(&dev->dmasound.lock); | 609 | down(&dev->dmasound.lock); |
648 | 610 | ||
649 | dev->dmasound.afmt = SNDRV_PCM_FORMAT_U8; | ||
650 | dev->dmasound.channels = 2; | ||
651 | dev->dmasound.read_count = 0; | 611 | dev->dmasound.read_count = 0; |
652 | dev->dmasound.read_offset = 0; | 612 | dev->dmasound.read_offset = 0; |
653 | 613 | ||
654 | up(&dev->dmasound.lock); | 614 | up(&dev->dmasound.lock); |
655 | 615 | ||
656 | saapcm = kzalloc(sizeof(*saapcm), GFP_KERNEL); | 616 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
657 | if (saapcm == NULL) | 617 | if (pcm == NULL) |
658 | return -ENOMEM; | 618 | return -ENOMEM; |
659 | saapcm->saadev=saa7134->saadev; | ||
660 | 619 | ||
661 | spin_lock_init(&saapcm->lock); | 620 | pcm->dev=saa7134->dev; |
662 | 621 | ||
663 | saapcm->substream = substream; | 622 | spin_lock_init(&pcm->lock); |
664 | runtime->private_data = saapcm; | 623 | |
624 | pcm->substream = substream; | ||
625 | runtime->private_data = pcm; | ||
665 | runtime->private_free = snd_card_saa7134_runtime_free; | 626 | runtime->private_free = snd_card_saa7134_runtime_free; |
666 | runtime->hw = snd_card_saa7134_capture; | 627 | runtime->hw = snd_card_saa7134_capture; |
667 | 628 | ||
@@ -736,7 +697,6 @@ static int snd_saa7134_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ | |||
736 | static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 697 | static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) |
737 | { | 698 | { |
738 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | 699 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); |
739 | unsigned long flags; | ||
740 | int change, addr = kcontrol->private_value; | 700 | int change, addr = kcontrol->private_value; |
741 | int left, right; | 701 | int left, right; |
742 | 702 | ||
@@ -750,12 +710,12 @@ static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ | |||
750 | right = 0; | 710 | right = 0; |
751 | if (right > 20) | 711 | if (right > 20) |
752 | right = 20; | 712 | right = 20; |
753 | spin_lock_irqsave(&chip->mixer_lock, flags); | 713 | spin_lock_irq(&chip->mixer_lock); |
754 | change = chip->mixer_volume[addr][0] != left || | 714 | change = chip->mixer_volume[addr][0] != left || |
755 | chip->mixer_volume[addr][1] != right; | 715 | chip->mixer_volume[addr][1] != right; |
756 | chip->mixer_volume[addr][0] = left; | 716 | chip->mixer_volume[addr][0] = left; |
757 | chip->mixer_volume[addr][1] = right; | 717 | chip->mixer_volume[addr][1] = right; |
758 | spin_unlock_irqrestore(&chip->mixer_lock, flags); | 718 | spin_unlock_irq(&chip->mixer_lock); |
759 | return change; | 719 | return change; |
760 | } | 720 | } |
761 | 721 | ||
@@ -777,38 +737,37 @@ static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_ | |||
777 | static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 737 | static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) |
778 | { | 738 | { |
779 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | 739 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); |
780 | unsigned long flags; | ||
781 | int addr = kcontrol->private_value; | 740 | int addr = kcontrol->private_value; |
782 | 741 | ||
783 | spin_lock_irqsave(&chip->mixer_lock, flags); | 742 | spin_lock_irq(&chip->mixer_lock); |
784 | ucontrol->value.integer.value[0] = chip->capture_source[addr][0]; | 743 | ucontrol->value.integer.value[0] = chip->capture_source[addr][0]; |
785 | ucontrol->value.integer.value[1] = chip->capture_source[addr][1]; | 744 | ucontrol->value.integer.value[1] = chip->capture_source[addr][1]; |
786 | spin_unlock_irqrestore(&chip->mixer_lock, flags); | 745 | spin_unlock_irq(&chip->mixer_lock); |
746 | |||
787 | return 0; | 747 | return 0; |
788 | } | 748 | } |
789 | 749 | ||
790 | static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 750 | static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) |
791 | { | 751 | { |
792 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | 752 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); |
793 | unsigned long flags; | ||
794 | int change, addr = kcontrol->private_value; | 753 | int change, addr = kcontrol->private_value; |
795 | int left, right; | 754 | int left, right; |
796 | u32 anabar, xbarin; | 755 | u32 anabar, xbarin; |
797 | int analog_io, rate; | 756 | int analog_io, rate; |
798 | struct saa7134_dev *dev; | 757 | struct saa7134_dev *dev; |
799 | 758 | ||
800 | dev = chip->saadev; | 759 | dev = chip->dev; |
801 | 760 | ||
802 | left = ucontrol->value.integer.value[0] & 1; | 761 | left = ucontrol->value.integer.value[0] & 1; |
803 | right = ucontrol->value.integer.value[1] & 1; | 762 | right = ucontrol->value.integer.value[1] & 1; |
804 | spin_lock_irqsave(&chip->mixer_lock, flags); | 763 | spin_lock_irq(&chip->mixer_lock); |
805 | 764 | ||
806 | change = chip->capture_source[addr][0] != left || | 765 | change = chip->capture_source[addr][0] != left || |
807 | chip->capture_source[addr][1] != right; | 766 | chip->capture_source[addr][1] != right; |
808 | chip->capture_source[addr][0] = left; | 767 | chip->capture_source[addr][0] = left; |
809 | chip->capture_source[addr][1] = right; | 768 | chip->capture_source[addr][1] = right; |
810 | dev->dmasound.input=addr; | 769 | dev->dmasound.input=addr; |
811 | spin_unlock_irqrestore(&chip->mixer_lock, flags); | 770 | spin_unlock_irq(&chip->mixer_lock); |
812 | 771 | ||
813 | 772 | ||
814 | if (change) { | 773 | if (change) { |
@@ -898,43 +857,44 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) | |||
898 | return 0; | 857 | return 0; |
899 | } | 858 | } |
900 | 859 | ||
901 | static int snd_saa7134_free(snd_card_saa7134_t *chip) | 860 | static void snd_saa7134_free(snd_card_t * card) |
902 | { | 861 | { |
903 | return 0; | 862 | snd_card_saa7134_t *chip = card->private_data; |
904 | } | 863 | |
864 | if (chip->dev->dmasound.priv_data == NULL) | ||
865 | return; | ||
866 | |||
867 | if (chip->irq >= 0) { | ||
868 | synchronize_irq(chip->irq); | ||
869 | free_irq(chip->irq, &chip->dev->dmasound); | ||
870 | } | ||
871 | |||
872 | chip->dev->dmasound.priv_data = NULL; | ||
905 | 873 | ||
906 | static int snd_saa7134_dev_free(snd_device_t *device) | ||
907 | { | ||
908 | snd_card_saa7134_t *chip = device->device_data; | ||
909 | return snd_saa7134_free(chip); | ||
910 | } | 874 | } |
911 | 875 | ||
912 | /* | 876 | /* |
913 | * ALSA initialization | 877 | * ALSA initialization |
914 | * | 878 | * |
915 | * Called by saa7134-core, it creates the basic structures and registers | 879 | * Called by the init routine, once for each saa7134 device present, |
916 | * the ALSA devices | 880 | * it creates the basic structures and registers the ALSA devices |
917 | * | 881 | * |
918 | */ | 882 | */ |
919 | 883 | ||
920 | int alsa_card_saa7134_create (struct saa7134_dev *saadev) | 884 | int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) |
921 | { | 885 | { |
922 | static int dev; | ||
923 | 886 | ||
924 | snd_card_t *card; | 887 | snd_card_t *card; |
925 | snd_card_saa7134_t *chip; | 888 | snd_card_saa7134_t *chip; |
926 | int err; | 889 | int err; |
927 | static snd_device_ops_t ops = { | ||
928 | .dev_free = snd_saa7134_dev_free, | ||
929 | }; | ||
930 | 890 | ||
931 | 891 | ||
932 | if (dev >= SNDRV_CARDS) | 892 | if (devnum >= SNDRV_CARDS) |
933 | return -ENODEV; | 893 | return -ENODEV; |
934 | if (!enable[dev]) | 894 | if (!enable[devnum]) |
935 | return -ENODEV; | 895 | return -ENODEV; |
936 | 896 | ||
937 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 897 | card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, sizeof(snd_card_saa7134_t)); |
938 | 898 | ||
939 | if (card == NULL) | 899 | if (card == NULL) |
940 | return -ENOMEM; | 900 | return -ENOMEM; |
@@ -943,34 +903,33 @@ int alsa_card_saa7134_create (struct saa7134_dev *saadev) | |||
943 | 903 | ||
944 | /* Card "creation" */ | 904 | /* Card "creation" */ |
945 | 905 | ||
946 | chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); | 906 | card->private_free = snd_saa7134_free; |
947 | if (chip == NULL) { | 907 | chip = (snd_card_saa7134_t *) card->private_data; |
948 | return -ENOMEM; | ||
949 | } | ||
950 | 908 | ||
951 | spin_lock_init(&chip->lock); | 909 | spin_lock_init(&chip->lock); |
952 | spin_lock_init(&chip->mixer_lock); | 910 | spin_lock_init(&chip->mixer_lock); |
953 | 911 | ||
954 | chip->saadev = saadev; | 912 | chip->dev = dev; |
955 | 913 | ||
956 | chip->card = card; | 914 | chip->card = card; |
957 | 915 | ||
958 | chip->pci = saadev->pci; | 916 | chip->pci = dev->pci; |
959 | chip->irq = saadev->pci->irq; | 917 | chip->iobase = pci_resource_start(dev->pci, 0); |
960 | chip->iobase = pci_resource_start(saadev->pci, 0); | ||
961 | 918 | ||
962 | err = request_irq(saadev->pci->irq, saa7134_alsa_irq, | 919 | |
963 | SA_SHIRQ | SA_INTERRUPT, saadev->name, saadev); | 920 | err = request_irq(dev->pci->irq, saa7134_alsa_irq, |
921 | SA_SHIRQ | SA_INTERRUPT, dev->name, | ||
922 | (void*) &dev->dmasound); | ||
964 | 923 | ||
965 | if (err < 0) { | 924 | if (err < 0) { |
966 | printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n", | 925 | printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n", |
967 | saadev->name, saadev->pci->irq); | 926 | dev->name, dev->pci->irq); |
968 | goto __nodev; | 927 | goto __nodev; |
969 | } | 928 | } |
970 | 929 | ||
971 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { | 930 | chip->irq = dev->pci->irq; |
972 | goto __nodev; | 931 | |
973 | } | 932 | init_MUTEX(&dev->dmasound.lock); |
974 | 933 | ||
975 | if ((err = snd_card_saa7134_new_mixer(chip)) < 0) | 934 | if ((err = snd_card_saa7134_new_mixer(chip)) < 0) |
976 | goto __nodev; | 935 | goto __nodev; |
@@ -984,16 +943,15 @@ int alsa_card_saa7134_create (struct saa7134_dev *saadev) | |||
984 | 943 | ||
985 | strcpy(card->shortname, "SAA7134"); | 944 | strcpy(card->shortname, "SAA7134"); |
986 | sprintf(card->longname, "%s at 0x%lx irq %d", | 945 | sprintf(card->longname, "%s at 0x%lx irq %d", |
987 | chip->saadev->name, chip->iobase, chip->irq); | 946 | chip->dev->name, chip->iobase, chip->irq); |
988 | 947 | ||
989 | if ((err = snd_card_register(card)) == 0) { | 948 | if ((err = snd_card_register(card)) == 0) { |
990 | snd_saa7134_cards[dev] = card; | 949 | snd_saa7134_cards[devnum] = card; |
991 | return 0; | 950 | return 0; |
992 | } | 951 | } |
993 | 952 | ||
994 | __nodev: | 953 | __nodev: |
995 | snd_card_free(card); | 954 | snd_card_free(card); |
996 | kfree(chip); | ||
997 | return err; | 955 | return err; |
998 | } | 956 | } |
999 | 957 | ||
@@ -1007,21 +965,29 @@ __nodev: | |||
1007 | 965 | ||
1008 | static int saa7134_alsa_init(void) | 966 | static int saa7134_alsa_init(void) |
1009 | { | 967 | { |
1010 | struct saa7134_dev *saadev = NULL; | 968 | struct saa7134_dev *dev = NULL; |
1011 | struct list_head *list; | 969 | struct list_head *list; |
1012 | 970 | ||
1013 | printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n"); | 971 | position = 0; |
1014 | 972 | ||
1015 | list_for_each(list,&saa7134_devlist) { | 973 | printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n"); |
1016 | saadev = list_entry(list, struct saa7134_dev, devlist); | ||
1017 | alsa_card_saa7134_create(saadev); | ||
1018 | } | ||
1019 | 974 | ||
1020 | if (saadev == NULL) | 975 | list_for_each(list,&saa7134_devlist) { |
976 | dev = list_entry(list, struct saa7134_dev, devlist); | ||
977 | if (dev->dmasound.priv_data == NULL) { | ||
978 | dev->dmasound.priv_data = dev; | ||
979 | alsa_card_saa7134_create(dev,position); | ||
980 | position++; | ||
981 | } else { | ||
982 | printk(KERN_ERR "saa7134 ALSA: DMA sound is being handled by OSS. ignoring %s\n",dev->name); | ||
983 | return -EBUSY; | ||
984 | } | ||
985 | } | ||
986 | |||
987 | if (dev == NULL) | ||
1021 | printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n"); | 988 | printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n"); |
1022 | 989 | ||
1023 | return 0; | 990 | return 0; |
1024 | |||
1025 | } | 991 | } |
1026 | 992 | ||
1027 | /* | 993 | /* |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 663d03e5bc67..75abc20b0ccd 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -2529,6 +2529,32 @@ struct saa7134_board saa7134_boards[] = { | |||
2529 | .amux = LINE1, | 2529 | .amux = LINE1, |
2530 | }}, | 2530 | }}, |
2531 | }, | 2531 | }, |
2532 | [SAA7134_BOARD_MSI_TVATANYWHERE_PLUS] = { | ||
2533 | .name = "MSI TV@Anywhere plus", | ||
2534 | .audio_clock = 0x00187de7, | ||
2535 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
2536 | .radio_type = UNSET, | ||
2537 | .tuner_addr = ADDR_UNSET, | ||
2538 | .radio_addr = ADDR_UNSET, | ||
2539 | .inputs = {{ | ||
2540 | .name = name_tv, | ||
2541 | .vmux = 1, | ||
2542 | .amux = TV, | ||
2543 | .tv = 1, | ||
2544 | },{ | ||
2545 | .name = name_comp1, | ||
2546 | .vmux = 3, | ||
2547 | .amux = LINE1, | ||
2548 | },{ | ||
2549 | .name = name_svideo, | ||
2550 | .vmux = 0, | ||
2551 | .amux = LINE1, | ||
2552 | }}, | ||
2553 | .radio = { | ||
2554 | .name = name_radio, | ||
2555 | .amux = LINE1, | ||
2556 | }, | ||
2557 | }, | ||
2532 | }; | 2558 | }; |
2533 | 2559 | ||
2534 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); | 2560 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); |
@@ -2970,6 +2996,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
2970 | .subdevice = 0x2018, | 2996 | .subdevice = 0x2018, |
2971 | .driver_data = SAA7134_BOARD_PHILIPS_TIGER, | 2997 | .driver_data = SAA7134_BOARD_PHILIPS_TIGER, |
2972 | },{ | 2998 | },{ |
2999 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3000 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3001 | .subvendor = 0x1462, | ||
3002 | .subdevice = 0x6231, | ||
3003 | .driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS, | ||
3004 | },{ | ||
2973 | /* --- boards without eeprom + subsystem ID --- */ | 3005 | /* --- boards without eeprom + subsystem ID --- */ |
2974 | .vendor = PCI_VENDOR_ID_PHILIPS, | 3006 | .vendor = PCI_VENDOR_ID_PHILIPS, |
2975 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 3007 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 19b88744fb31..4275d2ddb864 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -53,13 +53,13 @@ static unsigned int gpio_tracking = 0; | |||
53 | module_param(gpio_tracking, int, 0644); | 53 | module_param(gpio_tracking, int, 0644); |
54 | MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); | 54 | MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); |
55 | 55 | ||
56 | static unsigned int oss = 0; | ||
57 | module_param(oss, int, 0444); | ||
58 | MODULE_PARM_DESC(oss,"register oss devices (default: no)"); | ||
59 | |||
60 | static unsigned int alsa = 0; | 56 | static unsigned int alsa = 0; |
61 | module_param(alsa, int, 0444); | 57 | module_param(alsa, int, 0644); |
62 | MODULE_PARM_DESC(alsa,"register alsa devices (default: no)"); | 58 | MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]"); |
59 | |||
60 | static unsigned int oss = 0; | ||
61 | module_param(oss, int, 0644); | ||
62 | MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]"); | ||
63 | 63 | ||
64 | static unsigned int latency = UNSET; | 64 | static unsigned int latency = UNSET; |
65 | module_param(latency, int, 0444); | 65 | module_param(latency, int, 0444); |
@@ -68,24 +68,18 @@ MODULE_PARM_DESC(latency,"pci latency timer"); | |||
68 | static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 68 | static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
69 | static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 69 | static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
70 | static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 70 | static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
71 | static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | ||
72 | static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | ||
73 | static unsigned int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 71 | static unsigned int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
74 | static unsigned int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 72 | static unsigned int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
75 | 73 | ||
76 | module_param_array(video_nr, int, NULL, 0444); | 74 | module_param_array(video_nr, int, NULL, 0444); |
77 | module_param_array(vbi_nr, int, NULL, 0444); | 75 | module_param_array(vbi_nr, int, NULL, 0444); |
78 | module_param_array(radio_nr, int, NULL, 0444); | 76 | module_param_array(radio_nr, int, NULL, 0444); |
79 | module_param_array(dsp_nr, int, NULL, 0444); | ||
80 | module_param_array(mixer_nr, int, NULL, 0444); | ||
81 | module_param_array(tuner, int, NULL, 0444); | 77 | module_param_array(tuner, int, NULL, 0444); |
82 | module_param_array(card, int, NULL, 0444); | 78 | module_param_array(card, int, NULL, 0444); |
83 | 79 | ||
84 | MODULE_PARM_DESC(video_nr, "video device number"); | 80 | MODULE_PARM_DESC(video_nr, "video device number"); |
85 | MODULE_PARM_DESC(vbi_nr, "vbi device number"); | 81 | MODULE_PARM_DESC(vbi_nr, "vbi device number"); |
86 | MODULE_PARM_DESC(radio_nr, "radio device number"); | 82 | MODULE_PARM_DESC(radio_nr, "radio device number"); |
87 | MODULE_PARM_DESC(dsp_nr, "oss dsp device number"); | ||
88 | MODULE_PARM_DESC(mixer_nr, "oss mixer device number"); | ||
89 | MODULE_PARM_DESC(tuner, "tuner type"); | 83 | MODULE_PARM_DESC(tuner, "tuner type"); |
90 | MODULE_PARM_DESC(card, "card type"); | 84 | MODULE_PARM_DESC(card, "card type"); |
91 | 85 | ||
@@ -195,6 +189,7 @@ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg) | |||
195 | static int need_empress; | 189 | static int need_empress; |
196 | static int need_dvb; | 190 | static int need_dvb; |
197 | static int need_alsa; | 191 | static int need_alsa; |
192 | static int need_oss; | ||
198 | 193 | ||
199 | static int pending_call(struct notifier_block *self, unsigned long state, | 194 | static int pending_call(struct notifier_block *self, unsigned long state, |
200 | void *module) | 195 | void *module) |
@@ -208,6 +203,8 @@ static int pending_call(struct notifier_block *self, unsigned long state, | |||
208 | request_module("saa7134-dvb"); | 203 | request_module("saa7134-dvb"); |
209 | if (need_alsa) | 204 | if (need_alsa) |
210 | request_module("saa7134-alsa"); | 205 | request_module("saa7134-alsa"); |
206 | if (need_oss) | ||
207 | request_module("saa7134-oss"); | ||
211 | return NOTIFY_DONE; | 208 | return NOTIFY_DONE; |
212 | } | 209 | } |
213 | 210 | ||
@@ -218,10 +215,11 @@ static struct notifier_block pending_notifier = { | |||
218 | 215 | ||
219 | static void request_module_depend(char *name, int *flag) | 216 | static void request_module_depend(char *name, int *flag) |
220 | { | 217 | { |
218 | int err; | ||
221 | switch (THIS_MODULE->state) { | 219 | switch (THIS_MODULE->state) { |
222 | case MODULE_STATE_COMING: | 220 | case MODULE_STATE_COMING: |
223 | if (!pending_registered) { | 221 | if (!pending_registered) { |
224 | register_module_notifier(&pending_notifier); | 222 | err = register_module_notifier(&pending_notifier); |
225 | pending_registered = 1; | 223 | pending_registered = 1; |
226 | } | 224 | } |
227 | *flag = 1; | 225 | *flag = 1; |
@@ -578,12 +576,14 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
578 | goto out; | 576 | goto out; |
579 | } | 577 | } |
580 | 578 | ||
581 | /* If alsa support is active and we get a sound report, exit | 579 | /* If dmasound support is active and we get a sound report, exit |
582 | and let the saa7134-alsa module deal with it */ | 580 | and let the saa7134-alsa/oss module deal with it */ |
583 | 581 | ||
584 | if ((report & SAA7134_IRQ_REPORT_DONE_RA3) && alsa) { | 582 | if ((report & SAA7134_IRQ_REPORT_DONE_RA3) && |
583 | (dev->dmasound.priv_data != NULL) ) | ||
584 | { | ||
585 | if (irq_debug > 1) | 585 | if (irq_debug > 1) |
586 | printk(KERN_DEBUG "%s/irq: ignoring interrupt for ALSA\n", | 586 | printk(KERN_DEBUG "%s/irq: ignoring interrupt for DMA sound\n", |
587 | dev->name); | 587 | dev->name); |
588 | goto out; | 588 | goto out; |
589 | } | 589 | } |
@@ -609,12 +609,6 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
609 | card_has_mpeg(dev)) | 609 | card_has_mpeg(dev)) |
610 | saa7134_irq_ts_done(dev,status); | 610 | saa7134_irq_ts_done(dev,status); |
611 | 611 | ||
612 | if ((report & SAA7134_IRQ_REPORT_DONE_RA3)) { | ||
613 | if (oss) { | ||
614 | saa7134_irq_oss_done(dev,status); | ||
615 | } | ||
616 | } | ||
617 | |||
618 | if ((report & (SAA7134_IRQ_REPORT_GPIO16 | | 612 | if ((report & (SAA7134_IRQ_REPORT_GPIO16 | |
619 | SAA7134_IRQ_REPORT_GPIO18)) && | 613 | SAA7134_IRQ_REPORT_GPIO18)) && |
620 | dev->remote) | 614 | dev->remote) |
@@ -689,14 +683,6 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) | |||
689 | * audio will not work. | 683 | * audio will not work. |
690 | */ | 684 | */ |
691 | 685 | ||
692 | switch (dev->pci->device) { | ||
693 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
694 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
695 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
696 | saa7134_oss_init1(dev); | ||
697 | break; | ||
698 | } | ||
699 | |||
700 | /* enable peripheral devices */ | 686 | /* enable peripheral devices */ |
701 | saa_writeb(SAA7134_SPECIAL_MODE, 0x01); | 687 | saa_writeb(SAA7134_SPECIAL_MODE, 0x01); |
702 | 688 | ||
@@ -728,8 +714,6 @@ static int saa7134_hwinit2(struct saa7134_dev *dev) | |||
728 | irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 | | 714 | irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 | |
729 | SAA7134_IRQ2_INTE_GPIO18A | | 715 | SAA7134_IRQ2_INTE_GPIO18A | |
730 | SAA7134_IRQ2_INTE_GPIO16 ); | 716 | SAA7134_IRQ2_INTE_GPIO16 ); |
731 | else if (dev->has_remote == SAA7134_REMOTE_I2C) | ||
732 | request_module("ir-kbd-i2c"); | ||
733 | 717 | ||
734 | saa_writel(SAA7134_IRQ1, 0); | 718 | saa_writel(SAA7134_IRQ1, 0); |
735 | saa_writel(SAA7134_IRQ2, irq2_mask); | 719 | saa_writel(SAA7134_IRQ2, irq2_mask); |
@@ -742,13 +726,6 @@ static int saa7134_hwfini(struct saa7134_dev *dev) | |||
742 | { | 726 | { |
743 | dprintk("hwfini\n"); | 727 | dprintk("hwfini\n"); |
744 | 728 | ||
745 | switch (dev->pci->device) { | ||
746 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
747 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
748 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
749 | saa7134_oss_fini(dev); | ||
750 | break; | ||
751 | } | ||
752 | if (card_has_mpeg(dev)) | 729 | if (card_has_mpeg(dev)) |
753 | saa7134_ts_fini(dev); | 730 | saa7134_ts_fini(dev); |
754 | saa7134_input_fini(dev); | 731 | saa7134_input_fini(dev); |
@@ -986,11 +963,12 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
986 | if (card_is_dvb(dev)) | 963 | if (card_is_dvb(dev)) |
987 | request_module_depend("saa7134-dvb",&need_dvb); | 964 | request_module_depend("saa7134-dvb",&need_dvb); |
988 | 965 | ||
989 | if (!oss && alsa) { | 966 | |
990 | dprintk("Requesting ALSA module\n"); | 967 | if (alsa) |
991 | request_module_depend("saa7134-alsa",&need_alsa); | 968 | request_module_depend("saa7134-alsa",&need_alsa); |
992 | } | ||
993 | 969 | ||
970 | if (oss) | ||
971 | request_module_depend("saa7134-oss",&need_oss); | ||
994 | 972 | ||
995 | v4l2_prio_init(&dev->prio); | 973 | v4l2_prio_init(&dev->prio); |
996 | 974 | ||
@@ -1024,32 +1002,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
1024 | dev->name,dev->radio_dev->minor & 0x1f); | 1002 | dev->name,dev->radio_dev->minor & 0x1f); |
1025 | } | 1003 | } |
1026 | 1004 | ||
1027 | /* register oss devices */ | ||
1028 | switch (dev->pci->device) { | ||
1029 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
1030 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
1031 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
1032 | if (oss) { | ||
1033 | err = dev->dmasound.minor_dsp = | ||
1034 | register_sound_dsp(&saa7134_dsp_fops, | ||
1035 | dsp_nr[dev->nr]); | ||
1036 | if (err < 0) { | ||
1037 | goto fail4; | ||
1038 | } | ||
1039 | printk(KERN_INFO "%s: registered device dsp%d\n", | ||
1040 | dev->name,dev->dmasound.minor_dsp >> 4); | ||
1041 | |||
1042 | err = dev->dmasound.minor_mixer = | ||
1043 | register_sound_mixer(&saa7134_mixer_fops, | ||
1044 | mixer_nr[dev->nr]); | ||
1045 | if (err < 0) | ||
1046 | goto fail5; | ||
1047 | printk(KERN_INFO "%s: registered device mixer%d\n", | ||
1048 | dev->name,dev->dmasound.minor_mixer >> 4); | ||
1049 | } | ||
1050 | break; | ||
1051 | } | ||
1052 | |||
1053 | /* everything worked */ | 1005 | /* everything worked */ |
1054 | pci_set_drvdata(pci_dev,dev); | 1006 | pci_set_drvdata(pci_dev,dev); |
1055 | saa7134_devcount++; | 1007 | saa7134_devcount++; |
@@ -1064,17 +1016,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
1064 | 1016 | ||
1065 | /* check for signal */ | 1017 | /* check for signal */ |
1066 | saa7134_irq_video_intl(dev); | 1018 | saa7134_irq_video_intl(dev); |
1019 | |||
1067 | return 0; | 1020 | return 0; |
1068 | 1021 | ||
1069 | fail5: | ||
1070 | switch (dev->pci->device) { | ||
1071 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
1072 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
1073 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
1074 | if (oss) | ||
1075 | unregister_sound_dsp(dev->dmasound.minor_dsp); | ||
1076 | break; | ||
1077 | } | ||
1078 | fail4: | 1022 | fail4: |
1079 | saa7134_unregister_video(dev); | 1023 | saa7134_unregister_video(dev); |
1080 | saa7134_i2c_unregister(dev); | 1024 | saa7134_i2c_unregister(dev); |
@@ -1125,19 +1069,16 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) | |||
1125 | saa7134_devcount--; | 1069 | saa7134_devcount--; |
1126 | 1070 | ||
1127 | saa7134_i2c_unregister(dev); | 1071 | saa7134_i2c_unregister(dev); |
1128 | switch (dev->pci->device) { | ||
1129 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
1130 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
1131 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
1132 | if (oss) { | ||
1133 | unregister_sound_mixer(dev->dmasound.minor_mixer); | ||
1134 | unregister_sound_dsp(dev->dmasound.minor_dsp); | ||
1135 | } | ||
1136 | break; | ||
1137 | } | ||
1138 | saa7134_unregister_video(dev); | 1072 | saa7134_unregister_video(dev); |
1139 | 1073 | ||
1140 | /* release ressources */ | 1074 | /* the DMA sound modules should be unloaded before reaching |
1075 | this, but just in case they are still present... */ | ||
1076 | if (dev->dmasound.priv_data != NULL) { | ||
1077 | free_irq(pci_dev->irq, &dev->dmasound); | ||
1078 | dev->dmasound.priv_data = NULL; | ||
1079 | } | ||
1080 | |||
1081 | /* release resources */ | ||
1141 | free_irq(pci_dev->irq, dev); | 1082 | free_irq(pci_dev->irq, dev); |
1142 | iounmap(dev->lmmio); | 1083 | iounmap(dev->lmmio); |
1143 | release_mem_region(pci_resource_start(pci_dev,0), | 1084 | release_mem_region(pci_resource_start(pci_dev,0), |
@@ -1225,7 +1166,7 @@ EXPORT_SYMBOL(saa7134_i2c_call_clients); | |||
1225 | EXPORT_SYMBOL(saa7134_devlist); | 1166 | EXPORT_SYMBOL(saa7134_devlist); |
1226 | EXPORT_SYMBOL(saa7134_boards); | 1167 | EXPORT_SYMBOL(saa7134_boards); |
1227 | 1168 | ||
1228 | /* ----------------- For ALSA -------------------------------- */ | 1169 | /* ----------------- for the DMA sound modules --------------- */ |
1229 | 1170 | ||
1230 | EXPORT_SYMBOL(saa7134_pgtable_free); | 1171 | EXPORT_SYMBOL(saa7134_pgtable_free); |
1231 | EXPORT_SYMBOL(saa7134_pgtable_build); | 1172 | EXPORT_SYMBOL(saa7134_pgtable_build); |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 329accda6d45..e648cc3bc96d 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -485,64 +485,6 @@ static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { | |||
485 | 485 | ||
486 | }; | 486 | }; |
487 | 487 | ||
488 | static IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { | ||
489 | [ 0x59 ] = KEY_MUTE, | ||
490 | [ 0x4a ] = KEY_POWER, | ||
491 | |||
492 | [ 0x18 ] = KEY_TEXT, | ||
493 | [ 0x26 ] = KEY_TV, | ||
494 | [ 0x3d ] = KEY_PRINT, | ||
495 | |||
496 | [ 0x48 ] = KEY_RED, | ||
497 | [ 0x04 ] = KEY_GREEN, | ||
498 | [ 0x11 ] = KEY_YELLOW, | ||
499 | [ 0x00 ] = KEY_BLUE, | ||
500 | |||
501 | [ 0x2d ] = KEY_VOLUMEUP, | ||
502 | [ 0x1e ] = KEY_VOLUMEDOWN, | ||
503 | |||
504 | [ 0x49 ] = KEY_MENU, | ||
505 | |||
506 | [ 0x16 ] = KEY_CHANNELUP, | ||
507 | [ 0x17 ] = KEY_CHANNELDOWN, | ||
508 | |||
509 | [ 0x20 ] = KEY_UP, | ||
510 | [ 0x21 ] = KEY_DOWN, | ||
511 | [ 0x22 ] = KEY_LEFT, | ||
512 | [ 0x23 ] = KEY_RIGHT, | ||
513 | [ 0x0d ] = KEY_SELECT, | ||
514 | |||
515 | |||
516 | |||
517 | [ 0x08 ] = KEY_BACK, | ||
518 | [ 0x07 ] = KEY_REFRESH, | ||
519 | |||
520 | [ 0x2f ] = KEY_ZOOM, | ||
521 | [ 0x29 ] = KEY_RECORD, | ||
522 | |||
523 | [ 0x4b ] = KEY_PAUSE, | ||
524 | [ 0x4d ] = KEY_REWIND, | ||
525 | [ 0x2e ] = KEY_PLAY, | ||
526 | [ 0x4e ] = KEY_FORWARD, | ||
527 | [ 0x53 ] = KEY_PREVIOUS, | ||
528 | [ 0x4c ] = KEY_STOP, | ||
529 | [ 0x54 ] = KEY_NEXT, | ||
530 | |||
531 | [ 0x69 ] = KEY_KP0, | ||
532 | [ 0x6a ] = KEY_KP1, | ||
533 | [ 0x6b ] = KEY_KP2, | ||
534 | [ 0x6c ] = KEY_KP3, | ||
535 | [ 0x6d ] = KEY_KP4, | ||
536 | [ 0x6e ] = KEY_KP5, | ||
537 | [ 0x6f ] = KEY_KP6, | ||
538 | [ 0x70 ] = KEY_KP7, | ||
539 | [ 0x71 ] = KEY_KP8, | ||
540 | [ 0x72 ] = KEY_KP9, | ||
541 | |||
542 | [ 0x74 ] = KEY_CHANNEL, | ||
543 | [ 0x0a ] = KEY_BACKSPACE, | ||
544 | }; | ||
545 | |||
546 | /* Mapping for the 28 key remote control as seen at | 488 | /* Mapping for the 28 key remote control as seen at |
547 | http://www.sednacomputer.com/photo/cardbus-tv.jpg | 489 | http://www.sednacomputer.com/photo/cardbus-tv.jpg |
548 | Pavel Mihaylov <bin@bash.info> */ | 490 | Pavel Mihaylov <bin@bash.info> */ |
@@ -635,57 +577,6 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
635 | return 1; | 577 | return 1; |
636 | } | 578 | } |
637 | 579 | ||
638 | /* The new pinnacle PCTV remote (with the colored buttons) | ||
639 | * | ||
640 | * Ricardo Cerqueira <v4l@cerqueira.org> | ||
641 | */ | ||
642 | |||
643 | static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
644 | { | ||
645 | unsigned char b[4]; | ||
646 | unsigned int start = 0,parity = 0,code = 0; | ||
647 | |||
648 | /* poll IR chip */ | ||
649 | if (4 != i2c_master_recv(&ir->c,b,4)) { | ||
650 | i2cdprintk("read error\n"); | ||
651 | return -EIO; | ||
652 | } | ||
653 | |||
654 | for (start = 0; start<4; start++) { | ||
655 | if (b[start] == 0x80) { | ||
656 | code=b[(start+3)%4]; | ||
657 | parity=b[(start+2)%4]; | ||
658 | } | ||
659 | } | ||
660 | |||
661 | /* Empty Request */ | ||
662 | if (parity==0) | ||
663 | return 0; | ||
664 | |||
665 | /* Repeating... */ | ||
666 | if (ir->old == parity) | ||
667 | return 0; | ||
668 | |||
669 | |||
670 | ir->old = parity; | ||
671 | |||
672 | /* Reduce code value to fit inside IR_KEYTAB_SIZE | ||
673 | * | ||
674 | * this is the only value that results in 42 unique | ||
675 | * codes < 128 | ||
676 | */ | ||
677 | |||
678 | code %= 0x88; | ||
679 | |||
680 | *ir_raw = code; | ||
681 | *ir_key = code; | ||
682 | |||
683 | i2cdprintk("Pinnacle PCTV key %02x\n", code); | ||
684 | |||
685 | return 1; | ||
686 | } | ||
687 | |||
688 | |||
689 | void saa7134_input_irq(struct saa7134_dev *dev) | 580 | void saa7134_input_irq(struct saa7134_dev *dev) |
690 | { | 581 | { |
691 | struct saa7134_ir *ir = dev->remote; | 582 | struct saa7134_ir *ir = dev->remote; |
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index fd53dfcc1644..fd9ed11ab1e2 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c | |||
@@ -4,6 +4,8 @@ | |||
4 | * oss dsp interface | 4 | * oss dsp interface |
5 | * | 5 | * |
6 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] | 6 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] |
7 | * 2005 conversion to standalone module: | ||
8 | * Ricardo Cerqueira <v4l@cerqueira.org> | ||
7 | * | 9 | * |
8 | * This program is free software; you can redistribute it and/or modify | 10 | * 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 | 11 | * it under the terms of the GNU General Public License as published by |
@@ -25,7 +27,9 @@ | |||
25 | #include <linux/module.h> | 27 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
27 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/interrupt.h> | ||
28 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/sound.h> | ||
29 | #include <linux/soundcard.h> | 33 | #include <linux/soundcard.h> |
30 | 34 | ||
31 | #include "saa7134-reg.h" | 35 | #include "saa7134-reg.h" |
@@ -33,15 +37,23 @@ | |||
33 | 37 | ||
34 | /* ------------------------------------------------------------------ */ | 38 | /* ------------------------------------------------------------------ */ |
35 | 39 | ||
36 | static unsigned int oss_debug = 0; | 40 | static unsigned int debug = 0; |
37 | module_param(oss_debug, int, 0644); | 41 | module_param(debug, int, 0644); |
38 | MODULE_PARM_DESC(oss_debug,"enable debug messages [oss]"); | 42 | MODULE_PARM_DESC(debug,"enable debug messages [oss]"); |
39 | 43 | ||
40 | static unsigned int oss_rate = 0; | 44 | static unsigned int rate = 0; |
41 | module_param(oss_rate, int, 0444); | 45 | module_param(rate, int, 0444); |
42 | MODULE_PARM_DESC(oss_rate,"sample rate (valid are: 32000,48000)"); | 46 | MODULE_PARM_DESC(rate,"sample rate (valid are: 32000,48000)"); |
43 | 47 | ||
44 | #define dprintk(fmt, arg...) if (oss_debug) \ | 48 | static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
49 | MODULE_PARM_DESC(dsp_nr, "device numbers for SAA7134 capture interface(s)."); | ||
50 | module_param_array(dsp_nr, int, NULL, 0444); | ||
51 | |||
52 | static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | ||
53 | MODULE_PARM_DESC(mixer_nr, "mixer numbers for SAA7134 capture interface(s)."); | ||
54 | module_param_array(mixer_nr, int, NULL, 0444); | ||
55 | |||
56 | #define dprintk(fmt, arg...) if (debug) \ | ||
45 | printk(KERN_DEBUG "%s/oss: " fmt, dev->name , ## arg) | 57 | printk(KERN_DEBUG "%s/oss: " fmt, dev->name , ## arg) |
46 | 58 | ||
47 | 59 | ||
@@ -369,7 +381,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, | |||
369 | int __user *p = argp; | 381 | int __user *p = argp; |
370 | int val = 0; | 382 | int val = 0; |
371 | 383 | ||
372 | if (oss_debug > 1) | 384 | if (debug > 1) |
373 | saa7134_print_ioctl(dev->name,cmd); | 385 | saa7134_print_ioctl(dev->name,cmd); |
374 | switch (cmd) { | 386 | switch (cmd) { |
375 | case OSS_GETVERSION: | 387 | case OSS_GETVERSION: |
@@ -665,7 +677,7 @@ static int mixer_ioctl(struct inode *inode, struct file *file, | |||
665 | void __user *argp = (void __user *) arg; | 677 | void __user *argp = (void __user *) arg; |
666 | int __user *p = argp; | 678 | int __user *p = argp; |
667 | 679 | ||
668 | if (oss_debug > 1) | 680 | if (debug > 1) |
669 | saa7134_print_ioctl(dev->name,cmd); | 681 | saa7134_print_ioctl(dev->name,cmd); |
670 | switch (cmd) { | 682 | switch (cmd) { |
671 | case OSS_GETVERSION: | 683 | case OSS_GETVERSION: |
@@ -768,8 +780,41 @@ struct file_operations saa7134_mixer_fops = { | |||
768 | 780 | ||
769 | /* ------------------------------------------------------------------ */ | 781 | /* ------------------------------------------------------------------ */ |
770 | 782 | ||
783 | static irqreturn_t saa7134_oss_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
784 | { | ||
785 | struct saa7134_dmasound *dmasound = dev_id; | ||
786 | struct saa7134_dev *dev = dmasound->priv_data; | ||
787 | unsigned long report, status; | ||
788 | int loop, handled = 0; | ||
789 | |||
790 | for (loop = 0; loop < 10; loop++) { | ||
791 | report = saa_readl(SAA7134_IRQ_REPORT); | ||
792 | status = saa_readl(SAA7134_IRQ_STATUS); | ||
793 | |||
794 | if (report & SAA7134_IRQ_REPORT_DONE_RA3) { | ||
795 | handled = 1; | ||
796 | saa_writel(SAA7134_IRQ_REPORT,report); | ||
797 | saa7134_irq_oss_done(dev, status); | ||
798 | } else { | ||
799 | goto out; | ||
800 | } | ||
801 | } | ||
802 | |||
803 | if (loop == 10) { | ||
804 | dprintk("error! looping IRQ!"); | ||
805 | } | ||
806 | out: | ||
807 | return IRQ_RETVAL(handled); | ||
808 | } | ||
809 | |||
771 | int saa7134_oss_init1(struct saa7134_dev *dev) | 810 | int saa7134_oss_init1(struct saa7134_dev *dev) |
772 | { | 811 | { |
812 | |||
813 | if ((request_irq(dev->pci->irq, saa7134_oss_irq, | ||
814 | SA_SHIRQ | SA_INTERRUPT, dev->name, | ||
815 | (void*) &dev->dmasound)) < 0) | ||
816 | return -1; | ||
817 | |||
773 | /* general */ | 818 | /* general */ |
774 | init_MUTEX(&dev->dmasound.lock); | 819 | init_MUTEX(&dev->dmasound.lock); |
775 | init_waitqueue_head(&dev->dmasound.wq); | 820 | init_waitqueue_head(&dev->dmasound.wq); |
@@ -785,8 +830,8 @@ int saa7134_oss_init1(struct saa7134_dev *dev) | |||
785 | 830 | ||
786 | /* dsp */ | 831 | /* dsp */ |
787 | dev->dmasound.rate = 32000; | 832 | dev->dmasound.rate = 32000; |
788 | if (oss_rate) | 833 | if (rate) |
789 | dev->dmasound.rate = oss_rate; | 834 | dev->dmasound.rate = rate; |
790 | dev->dmasound.rate = (dev->dmasound.rate > 40000) ? 48000 : 32000; | 835 | dev->dmasound.rate = (dev->dmasound.rate > 40000) ? 48000 : 32000; |
791 | 836 | ||
792 | /* mixer */ | 837 | /* mixer */ |
@@ -840,7 +885,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status) | |||
840 | /* next block addr */ | 885 | /* next block addr */ |
841 | next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks; | 886 | next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks; |
842 | saa_writel(reg,next_blk * dev->dmasound.blksize); | 887 | saa_writel(reg,next_blk * dev->dmasound.blksize); |
843 | if (oss_debug > 2) | 888 | if (debug > 2) |
844 | dprintk("irq: ok, %s, next_blk=%d, addr=%x\n", | 889 | dprintk("irq: ok, %s, next_blk=%d, addr=%x\n", |
845 | (status & 0x10000000) ? "even" : "odd ", next_blk, | 890 | (status & 0x10000000) ? "even" : "odd ", next_blk, |
846 | next_blk * dev->dmasound.blksize); | 891 | next_blk * dev->dmasound.blksize); |
@@ -854,6 +899,98 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status) | |||
854 | spin_unlock(&dev->slock); | 899 | spin_unlock(&dev->slock); |
855 | } | 900 | } |
856 | 901 | ||
902 | int saa7134_dsp_create(struct saa7134_dev *dev) | ||
903 | { | ||
904 | int err; | ||
905 | |||
906 | err = dev->dmasound.minor_dsp = | ||
907 | register_sound_dsp(&saa7134_dsp_fops, | ||
908 | dsp_nr[dev->nr]); | ||
909 | if (err < 0) { | ||
910 | goto fail; | ||
911 | } | ||
912 | printk(KERN_INFO "%s: registered device dsp%d\n", | ||
913 | dev->name,dev->dmasound.minor_dsp >> 4); | ||
914 | |||
915 | err = dev->dmasound.minor_mixer = | ||
916 | register_sound_mixer(&saa7134_mixer_fops, | ||
917 | mixer_nr[dev->nr]); | ||
918 | if (err < 0) | ||
919 | goto fail; | ||
920 | printk(KERN_INFO "%s: registered device mixer%d\n", | ||
921 | dev->name,dev->dmasound.minor_mixer >> 4); | ||
922 | |||
923 | return 0; | ||
924 | |||
925 | fail: | ||
926 | unregister_sound_dsp(dev->dmasound.minor_dsp); | ||
927 | return 0; | ||
928 | |||
929 | |||
930 | } | ||
931 | |||
932 | static int saa7134_oss_init(void) | ||
933 | { | ||
934 | struct saa7134_dev *dev = NULL; | ||
935 | struct list_head *list; | ||
936 | |||
937 | printk(KERN_INFO "saa7134 OSS driver for DMA sound loaded\n"); | ||
938 | |||
939 | list_for_each(list,&saa7134_devlist) { | ||
940 | dev = list_entry(list, struct saa7134_dev, devlist); | ||
941 | if (dev->dmasound.priv_data == NULL) { | ||
942 | dev->dmasound.priv_data = dev; | ||
943 | saa7134_oss_init1(dev); | ||
944 | saa7134_dsp_create(dev); | ||
945 | } else { | ||
946 | printk(KERN_ERR "saa7134 OSS: DMA sound is being handled by ALSA, ignoring %s\n",dev->name); | ||
947 | return -EBUSY; | ||
948 | } | ||
949 | } | ||
950 | |||
951 | if (dev == NULL) | ||
952 | printk(KERN_INFO "saa7134 OSS: no saa7134 cards found\n"); | ||
953 | |||
954 | return 0; | ||
955 | |||
956 | } | ||
957 | |||
958 | void saa7134_oss_exit(void) | ||
959 | { | ||
960 | struct saa7134_dev *dev = NULL; | ||
961 | struct list_head *list; | ||
962 | |||
963 | list_for_each(list,&saa7134_devlist) { | ||
964 | dev = list_entry(list, struct saa7134_dev, devlist); | ||
965 | |||
966 | /* Device isn't registered by OSS, probably ALSA's */ | ||
967 | if (!dev->dmasound.minor_dsp) | ||
968 | continue; | ||
969 | |||
970 | unregister_sound_mixer(dev->dmasound.minor_mixer); | ||
971 | unregister_sound_dsp(dev->dmasound.minor_dsp); | ||
972 | |||
973 | saa7134_oss_fini(dev); | ||
974 | |||
975 | if (dev->pci->irq > 0) { | ||
976 | synchronize_irq(dev->pci->irq); | ||
977 | free_irq(dev->pci->irq,&dev->dmasound); | ||
978 | } | ||
979 | |||
980 | dev->dmasound.priv_data = NULL; | ||
981 | |||
982 | } | ||
983 | |||
984 | printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n"); | ||
985 | |||
986 | return; | ||
987 | } | ||
988 | |||
989 | module_init(saa7134_oss_init); | ||
990 | module_exit(saa7134_oss_exit); | ||
991 | MODULE_LICENSE("GPL"); | ||
992 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | ||
993 | |||
857 | /* ----------------------------------------------------------- */ | 994 | /* ----------------------------------------------------------- */ |
858 | /* | 995 | /* |
859 | * Local variables: | 996 | * Local variables: |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index fb9727471661..244e1973081c 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -208,6 +208,7 @@ struct saa7134_format { | |||
208 | #define SAA7134_BOARD_SEDNA_PC_TV_CARDBUS 79 | 208 | #define SAA7134_BOARD_SEDNA_PC_TV_CARDBUS 79 |
209 | #define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80 | 209 | #define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80 |
210 | #define SAA7134_BOARD_PHILIPS_TIGER 81 | 210 | #define SAA7134_BOARD_PHILIPS_TIGER 81 |
211 | #define SAA7134_BOARD_MSI_TVATANYWHERE_PLUS 82 | ||
211 | 212 | ||
212 | #define SAA7134_MAXBOARDS 8 | 213 | #define SAA7134_MAXBOARDS 8 |
213 | #define SAA7134_INPUT_MAX 8 | 214 | #define SAA7134_INPUT_MAX 8 |
@@ -383,6 +384,7 @@ struct saa7134_dmasound { | |||
383 | unsigned int dma_blk; | 384 | unsigned int dma_blk; |
384 | unsigned int read_offset; | 385 | unsigned int read_offset; |
385 | unsigned int read_count; | 386 | unsigned int read_count; |
387 | void * priv_data; | ||
386 | snd_pcm_substream_t *substream; | 388 | snd_pcm_substream_t *substream; |
387 | }; | 389 | }; |
388 | 390 | ||
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index b2dfe07e9f9d..61d94ddaff41 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c | |||
@@ -437,6 +437,10 @@ static void set_audio(struct tuner *t) | |||
437 | t->sgIF = 124; | 437 | t->sgIF = 124; |
438 | t->tda8290_easy_mode = 0x20; | 438 | t->tda8290_easy_mode = 0x20; |
439 | mode = "L"; | 439 | mode = "L"; |
440 | } else if (t->std & V4L2_STD_SECAM_LC) { | ||
441 | t->sgIF = 20; | ||
442 | t->tda8290_easy_mode = 0x40; | ||
443 | mode = "LC"; | ||
440 | } | 444 | } |
441 | tuner_dbg("setting tda8290 to system %s\n", mode); | 445 | tuner_dbg("setting tda8290 to system %s\n", mode); |
442 | } | 446 | } |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 73c4041c35d7..e58abdfcaab8 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -251,7 +251,7 @@ static inline int check_mode(struct tuner *t, char *cmd) | |||
251 | 251 | ||
252 | static char pal[] = "-"; | 252 | static char pal[] = "-"; |
253 | module_param_string(pal, pal, sizeof(pal), 0644); | 253 | module_param_string(pal, pal, sizeof(pal), 0644); |
254 | static char secam[] = "-"; | 254 | static char secam[] = "--"; |
255 | module_param_string(secam, secam, sizeof(secam), 0644); | 255 | module_param_string(secam, secam, sizeof(secam), 0644); |
256 | 256 | ||
257 | /* get more precise norm info from insmod option */ | 257 | /* get more precise norm info from insmod option */ |
@@ -307,8 +307,13 @@ static int tuner_fixup_std(struct tuner *t) | |||
307 | break; | 307 | break; |
308 | case 'l': | 308 | case 'l': |
309 | case 'L': | 309 | case 'L': |
310 | tuner_dbg ("insmod fixup: SECAM => SECAM-L\n"); | 310 | if ((secam[1]=='C')||(secam[1]=='c')) { |
311 | t->std = V4L2_STD_SECAM_L; | 311 | tuner_dbg ("insmod fixup: SECAM => SECAM-L'\n"); |
312 | t->std = V4L2_STD_SECAM_LC; | ||
313 | } else { | ||
314 | tuner_dbg ("insmod fixup: SECAM => SECAM-L\n"); | ||
315 | t->std = V4L2_STD_SECAM_L; | ||
316 | } | ||
312 | break; | 317 | break; |
313 | case '-': | 318 | case '-': |
314 | /* default parameter, do nothing */ | 319 | /* default parameter, do nothing */ |
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index d832205818f2..e0c9fdb9914a 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c | |||
@@ -233,7 +233,7 @@ static struct tunertype tuners[] = { | |||
233 | { "Ymec TVision TVF-5533MF", Philips, NTSC, | 233 | { "Ymec TVision TVF-5533MF", Philips, NTSC, |
234 | 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732}, | 234 | 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732}, |
235 | 235 | ||
236 | /* 60-68 */ | 236 | /* 60-69 */ |
237 | { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, | 237 | { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, |
238 | 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, | 238 | 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, |
239 | { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, | 239 | { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, |
@@ -252,6 +252,8 @@ static struct tunertype tuners[] = { | |||
252 | 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, | 252 | 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, |
253 | { "Philips TUV1236D ATSC/NTSC dual in", Philips, ATSC, | 253 | { "Philips TUV1236D ATSC/NTSC dual in", Philips, ATSC, |
254 | 16*157.25,16*454.00,0x01,0x02,0x04,0xce,732 }, | 254 | 16*157.25,16*454.00,0x01,0x02,0x04,0xce,732 }, |
255 | { "Tena TNF 5335 MF", Philips, NTSC, | ||
256 | 16*157.25,16*454.00,0x01,0x02,0x04,0x8e,732 }, | ||
255 | }; | 257 | }; |
256 | 258 | ||
257 | unsigned const int tuner_count = ARRAY_SIZE(tuners); | 259 | unsigned const int tuner_count = ARRAY_SIZE(tuners); |
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 22f286222004..a6936ad74fcf 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c | |||
@@ -5,6 +5,11 @@ | |||
5 | * | 5 | * |
6 | * Based on saa7115 driver | 6 | * Based on saa7115 driver |
7 | * | 7 | * |
8 | * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl> | ||
9 | * - Cleanup | ||
10 | * - V4L2 API update | ||
11 | * - sound fixes | ||
12 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | 13 | * 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 | 14 | * 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 | 15 | * the Free Software Foundation; either version 2 of the License, or |
@@ -31,7 +36,7 @@ | |||
31 | #include <media/audiochip.h> | 36 | #include <media/audiochip.h> |
32 | 37 | ||
33 | MODULE_DESCRIPTION("wm8775 driver"); | 38 | MODULE_DESCRIPTION("wm8775 driver"); |
34 | MODULE_AUTHOR("Ulf Eklund"); | 39 | MODULE_AUTHOR("Ulf Eklund, Hans Verkuil"); |
35 | MODULE_LICENSE("GPL"); | 40 | MODULE_LICENSE("GPL"); |
36 | 41 | ||
37 | #define wm8775_err(fmt, arg...) do { \ | 42 | #define wm8775_err(fmt, arg...) do { \ |
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 1e6bdba26756..166c9b0ad04e 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include <asm/div64.h> | 23 | #include <asm/div64.h> |
24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
25 | #include <asm/irq.h> | ||
26 | #include <asm/scatterlist.h> | 25 | #include <asm/scatterlist.h> |
27 | #include <asm/sizes.h> | 26 | #include <asm/sizes.h> |
28 | #include <asm/hardware/amba.h> | 27 | #include <asm/hardware/amba.h> |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 48638c8097a5..846a533323a8 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -94,7 +94,7 @@ config MTD_NETSC520 | |||
94 | 94 | ||
95 | config MTD_TS5500 | 95 | config MTD_TS5500 |
96 | tristate "JEDEC Flash device mapped on Technologic Systems TS-5500" | 96 | tristate "JEDEC Flash device mapped on Technologic Systems TS-5500" |
97 | depends on ELAN | 97 | depends on X86 |
98 | select MTD_PARTITIONS | 98 | select MTD_PARTITIONS |
99 | select MTD_JEDECPROBE | 99 | select MTD_JEDECPROBE |
100 | select MTD_CFI_AMDSTD | 100 | select MTD_CFI_AMDSTD |
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 977935a3d898..824e430486c2 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c | |||
@@ -84,6 +84,7 @@ static int max_interrupt_work = 10; | |||
84 | #include <linux/netdevice.h> | 84 | #include <linux/netdevice.h> |
85 | #include <linux/etherdevice.h> | 85 | #include <linux/etherdevice.h> |
86 | #include <linux/pm.h> | 86 | #include <linux/pm.h> |
87 | #include <linux/pm_legacy.h> | ||
87 | #include <linux/skbuff.h> | 88 | #include <linux/skbuff.h> |
88 | #include <linux/delay.h> /* for udelay() */ | 89 | #include <linux/delay.h> /* for udelay() */ |
89 | #include <linux/spinlock.h> | 90 | #include <linux/spinlock.h> |
@@ -173,7 +174,7 @@ struct el3_private { | |||
173 | /* skb send-queue */ | 174 | /* skb send-queue */ |
174 | int head, size; | 175 | int head, size; |
175 | struct sk_buff *queue[SKB_QUEUE_SIZE]; | 176 | struct sk_buff *queue[SKB_QUEUE_SIZE]; |
176 | #ifdef CONFIG_PM | 177 | #ifdef CONFIG_PM_LEGACY |
177 | struct pm_dev *pmdev; | 178 | struct pm_dev *pmdev; |
178 | #endif | 179 | #endif |
179 | enum { | 180 | enum { |
@@ -200,7 +201,7 @@ static void el3_tx_timeout (struct net_device *dev); | |||
200 | static void el3_down(struct net_device *dev); | 201 | static void el3_down(struct net_device *dev); |
201 | static void el3_up(struct net_device *dev); | 202 | static void el3_up(struct net_device *dev); |
202 | static struct ethtool_ops ethtool_ops; | 203 | static struct ethtool_ops ethtool_ops; |
203 | #ifdef CONFIG_PM | 204 | #ifdef CONFIG_PM_LEGACY |
204 | static int el3_suspend(struct pm_dev *pdev); | 205 | static int el3_suspend(struct pm_dev *pdev); |
205 | static int el3_resume(struct pm_dev *pdev); | 206 | static int el3_resume(struct pm_dev *pdev); |
206 | static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data); | 207 | static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data); |
@@ -361,7 +362,7 @@ static void el3_common_remove (struct net_device *dev) | |||
361 | struct el3_private *lp = netdev_priv(dev); | 362 | struct el3_private *lp = netdev_priv(dev); |
362 | 363 | ||
363 | (void) lp; /* Keep gcc quiet... */ | 364 | (void) lp; /* Keep gcc quiet... */ |
364 | #ifdef CONFIG_PM | 365 | #ifdef CONFIG_PM_LEGACY |
365 | if (lp->pmdev) | 366 | if (lp->pmdev) |
366 | pm_unregister(lp->pmdev); | 367 | pm_unregister(lp->pmdev); |
367 | #endif | 368 | #endif |
@@ -571,7 +572,7 @@ no_pnp: | |||
571 | if (err) | 572 | if (err) |
572 | goto out1; | 573 | goto out1; |
573 | 574 | ||
574 | #ifdef CONFIG_PM | 575 | #ifdef CONFIG_PM_LEGACY |
575 | /* register power management */ | 576 | /* register power management */ |
576 | lp->pmdev = pm_register(PM_ISA_DEV, card_idx, el3_pm_callback); | 577 | lp->pmdev = pm_register(PM_ISA_DEV, card_idx, el3_pm_callback); |
577 | if (lp->pmdev) { | 578 | if (lp->pmdev) { |
@@ -1479,7 +1480,7 @@ el3_up(struct net_device *dev) | |||
1479 | } | 1480 | } |
1480 | 1481 | ||
1481 | /* Power Management support functions */ | 1482 | /* Power Management support functions */ |
1482 | #ifdef CONFIG_PM | 1483 | #ifdef CONFIG_PM_LEGACY |
1483 | 1484 | ||
1484 | static int | 1485 | static int |
1485 | el3_suspend(struct pm_dev *pdev) | 1486 | el3_suspend(struct pm_dev *pdev) |
@@ -1548,7 +1549,7 @@ el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data) | |||
1548 | return 0; | 1549 | return 0; |
1549 | } | 1550 | } |
1550 | 1551 | ||
1551 | #endif /* CONFIG_PM */ | 1552 | #endif /* CONFIG_PM_LEGACY */ |
1552 | 1553 | ||
1553 | /* Parameters that may be passed into the module. */ | 1554 | /* Parameters that may be passed into the module. */ |
1554 | static int debug = -1; | 1555 | static int debug = -1; |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index e3a329539f1c..0f030b73cbb3 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Based on 8260_io/fcc_enet.c | 6 | * Based on 8260_io/fcc_enet.c |
7 | * | 7 | * |
8 | * Author: Andy Fleming | 8 | * Author: Andy Fleming |
9 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 9 | * Maintainer: Kumar Gala |
10 | * | 10 | * |
11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | 11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. |
12 | * | 12 | * |
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 220084e53341..5065ba82cb76 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * Based on 8260_io/fcc_enet.c | 6 | * Based on 8260_io/fcc_enet.c |
7 | * | 7 | * |
8 | * Author: Andy Fleming | 8 | * Author: Andy Fleming |
9 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 9 | * Maintainer: Kumar Gala |
10 | * | 10 | * |
11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | 11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. |
12 | * | 12 | * |
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 5a2d810ce575..cfa3cd7c91a0 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Based on e1000 ethtool support | 6 | * Based on e1000 ethtool support |
7 | * | 7 | * |
8 | * Author: Andy Fleming | 8 | * Author: Andy Fleming |
9 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 9 | * Maintainer: Kumar Gala |
10 | * | 10 | * |
11 | * Copyright (c) 2003,2004 Freescale Semiconductor, Inc. | 11 | * Copyright (c) 2003,2004 Freescale Semiconductor, Inc. |
12 | * | 12 | * |
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 9544279e8bcd..04a462c2a5b7 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * Provides Bus interface for MIIM regs | 5 | * Provides Bus interface for MIIM regs |
6 | * | 6 | * |
7 | * Author: Andy Fleming | 7 | * Author: Andy Fleming |
8 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 8 | * Maintainer: Kumar Gala |
9 | * | 9 | * |
10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | 10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. |
11 | * | 11 | * |
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h index 56e5665d5c9b..e85eb216fb5b 100644 --- a/drivers/net/gianfar_mii.h +++ b/drivers/net/gianfar_mii.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * Driver for the MDIO bus controller in the Gianfar register space | 5 | * Driver for the MDIO bus controller in the Gianfar register space |
6 | * | 6 | * |
7 | * Author: Andy Fleming | 7 | * Author: Andy Fleming |
8 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 8 | * Maintainer: Kumar Gala |
9 | * | 9 | * |
10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | 10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. |
11 | * | 11 | * |
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c index 9bf34681d3df..2e7882eb7d6f 100644 --- a/drivers/net/irda/ali-ircc.c +++ b/drivers/net/irda/ali-ircc.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <asm/byteorder.h> | 40 | #include <asm/byteorder.h> |
41 | 41 | ||
42 | #include <linux/pm.h> | 42 | #include <linux/pm.h> |
43 | #include <linux/pm_legacy.h> | ||
43 | 44 | ||
44 | #include <net/irda/wrapper.h> | 45 | #include <net/irda/wrapper.h> |
45 | #include <net/irda/irda.h> | 46 | #include <net/irda/irda.h> |
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index 805714ec9a8a..ee717d0e939e 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <asm/byteorder.h> | 59 | #include <asm/byteorder.h> |
60 | 60 | ||
61 | #include <linux/pm.h> | 61 | #include <linux/pm.h> |
62 | #include <linux/pm_legacy.h> | ||
62 | 63 | ||
63 | #include <net/irda/wrapper.h> | 64 | #include <net/irda/wrapper.h> |
64 | #include <net/irda/irda.h> | 65 | #include <net/irda/irda.h> |
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index a10cd184d597..5c2824be4ee6 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h | |||
@@ -100,14 +100,14 @@ | |||
100 | #define SMC_IO_SHIFT 0 | 100 | #define SMC_IO_SHIFT 0 |
101 | #define SMC_NOWAIT 1 | 101 | #define SMC_NOWAIT 1 |
102 | 102 | ||
103 | #define SMC_inb(a, r) inb((a) + (r)) | 103 | #define SMC_inb(a, r) readb((a) + (r)) |
104 | #define SMC_insb(a, r, p, l) insb((a) + (r), p, (l)) | 104 | #define SMC_insb(a, r, p, l) readsb((a) + (r), p, (l)) |
105 | #define SMC_inw(a, r) inw((a) + (r)) | 105 | #define SMC_inw(a, r) readw((a) + (r)) |
106 | #define SMC_insw(a, r, p, l) insw((a) + (r), p, l) | 106 | #define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) |
107 | #define SMC_outb(v, a, r) outb(v, (a) + (r)) | 107 | #define SMC_outb(v, a, r) writeb(v, (a) + (r)) |
108 | #define SMC_outsb(a, r, p, l) outsb((a) + (r), p, (l)) | 108 | #define SMC_outsb(a, r, p, l) writesb((a) + (r), p, (l)) |
109 | #define SMC_outw(v, a, r) outw(v, (a) + (r)) | 109 | #define SMC_outw(v, a, r) writew(v, (a) + (r)) |
110 | #define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l) | 110 | #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) |
111 | 111 | ||
112 | #define set_irq_type(irq, type) do {} while (0) | 112 | #define set_irq_type(irq, type) do {} while (0) |
113 | 113 | ||
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index de399563a9db..081717d01374 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c | |||
@@ -128,6 +128,8 @@ static struct pci_device_id gem_pci_tbl[] = { | |||
128 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | 128 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, |
129 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_SUNGEM, | 129 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_SUNGEM, |
130 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | 130 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, |
131 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_GMAC, | ||
132 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | ||
131 | {0, } | 133 | {0, } |
132 | }; | 134 | }; |
133 | 135 | ||
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 4a3cecca012c..2387e75da0fe 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/interrupt.h> | ||
35 | |||
34 | #include "../pci.h" | 36 | #include "../pci.h" |
35 | #include "pciehp.h" | 37 | #include "pciehp.h" |
36 | 38 | ||
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index a7859a84d1ae..4b35097b3d9f 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c | |||
@@ -253,7 +253,7 @@ rpaphp_pci_config_slot(struct pci_bus *bus) | |||
253 | if (!dn || !dn->child) | 253 | if (!dn || !dn->child) |
254 | return NULL; | 254 | return NULL; |
255 | 255 | ||
256 | if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { | 256 | if (_machine == PLATFORM_PSERIES_LPAR) { |
257 | of_scan_bus(dn, bus); | 257 | of_scan_bus(dn, bus); |
258 | if (list_empty(&bus->devices)) { | 258 | if (list_empty(&bus->devices)) { |
259 | err("%s: No new device found\n", __FUNCTION__); | 259 | err("%s: No new device found\n", __FUNCTION__); |
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 40905a6c8094..9987a6fd65b8 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/interrupt.h> | ||
35 | |||
34 | #include "shpchp.h" | 36 | #include "shpchp.h" |
35 | 37 | ||
36 | #ifdef DEBUG | 38 | #ifdef DEBUG |
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 234cdca6fe13..a30aa74304a2 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -513,6 +513,11 @@ static int socket_insert(struct pcmcia_socket *skt) | |||
513 | ret = socket_setup(skt, setup_delay); | 513 | ret = socket_setup(skt, setup_delay); |
514 | if (ret == CS_SUCCESS) { | 514 | if (ret == CS_SUCCESS) { |
515 | skt->state |= SOCKET_PRESENT; | 515 | skt->state |= SOCKET_PRESENT; |
516 | |||
517 | printk(KERN_NOTICE "pccard: %s card inserted into slot %d\n", | ||
518 | (skt->state & SOCKET_CARDBUS) ? "CardBus" : "PCMCIA", | ||
519 | skt->sock); | ||
520 | |||
516 | #ifdef CONFIG_CARDBUS | 521 | #ifdef CONFIG_CARDBUS |
517 | if (skt->state & SOCKET_CARDBUS) { | 522 | if (skt->state & SOCKET_CARDBUS) { |
518 | cb_alloc(skt); | 523 | cb_alloc(skt); |
@@ -598,6 +603,7 @@ static int socket_resume(struct pcmcia_socket *skt) | |||
598 | 603 | ||
599 | static void socket_remove(struct pcmcia_socket *skt) | 604 | static void socket_remove(struct pcmcia_socket *skt) |
600 | { | 605 | { |
606 | printk(KERN_NOTICE "pccard: card ejected from slot %d\n", skt->sock); | ||
601 | socket_shutdown(skt); | 607 | socket_shutdown(skt); |
602 | cs_socket_put(skt); | 608 | cs_socket_put(skt); |
603 | } | 609 | } |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 39d096b52926..7f8219f3fd9e 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -544,6 +544,9 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
544 | list_add_tail(&p_dev->socket_device_list, &s->devices_list); | 544 | list_add_tail(&p_dev->socket_device_list, &s->devices_list); |
545 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 545 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
546 | 546 | ||
547 | printk(KERN_NOTICE "pcmcia: registering new device %s\n", | ||
548 | p_dev->devname); | ||
549 | |||
547 | pcmcia_device_query(p_dev); | 550 | pcmcia_device_query(p_dev); |
548 | 551 | ||
549 | if (device_register(&p_dev->dev)) { | 552 | if (device_register(&p_dev->dev)) { |
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 4ddd76239b34..4d56bc9926d6 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c | |||
@@ -1339,10 +1339,7 @@ static struct device_driver i82365_driver = { | |||
1339 | .resume = pcmcia_socket_dev_resume, | 1339 | .resume = pcmcia_socket_dev_resume, |
1340 | }; | 1340 | }; |
1341 | 1341 | ||
1342 | static struct platform_device i82365_device = { | 1342 | static struct platform_device *i82365_device; |
1343 | .name = "i82365", | ||
1344 | .id = 0, | ||
1345 | }; | ||
1346 | 1343 | ||
1347 | static int __init init_i82365(void) | 1344 | static int __init init_i82365(void) |
1348 | { | 1345 | { |
@@ -1352,7 +1349,14 @@ static int __init init_i82365(void) | |||
1352 | if (ret) | 1349 | if (ret) |
1353 | return ret; | 1350 | return ret; |
1354 | 1351 | ||
1355 | ret = platform_device_register(&i82365_device); | 1352 | i82365_device = platform_device_alloc("i82365", 0); |
1353 | if (i82365_device) { | ||
1354 | ret = platform_device_add(i82365_device); | ||
1355 | if (ret) | ||
1356 | platform_device_put(i82365_device); | ||
1357 | } else | ||
1358 | ret = -ENOMEM; | ||
1359 | |||
1356 | if (ret) { | 1360 | if (ret) { |
1357 | driver_unregister(&i82365_driver); | 1361 | driver_unregister(&i82365_driver); |
1358 | return ret; | 1362 | return ret; |
@@ -1365,7 +1369,7 @@ static int __init init_i82365(void) | |||
1365 | 1369 | ||
1366 | if (sockets == 0) { | 1370 | if (sockets == 0) { |
1367 | printk("not found.\n"); | 1371 | printk("not found.\n"); |
1368 | platform_device_unregister(&i82365_device); | 1372 | platform_device_unregister(i82365_device); |
1369 | release_region(i365_base, 2); | 1373 | release_region(i365_base, 2); |
1370 | driver_unregister(&i82365_driver); | 1374 | driver_unregister(&i82365_driver); |
1371 | return -ENODEV; | 1375 | return -ENODEV; |
@@ -1377,7 +1381,7 @@ static int __init init_i82365(void) | |||
1377 | 1381 | ||
1378 | /* register sockets with the pcmcia core */ | 1382 | /* register sockets with the pcmcia core */ |
1379 | for (i = 0; i < sockets; i++) { | 1383 | for (i = 0; i < sockets; i++) { |
1380 | socket[i].socket.dev.dev = &i82365_device.dev; | 1384 | socket[i].socket.dev.dev = &i82365_device->dev; |
1381 | socket[i].socket.ops = &pcic_operations; | 1385 | socket[i].socket.ops = &pcic_operations; |
1382 | socket[i].socket.resource_ops = &pccard_nonstatic_ops; | 1386 | socket[i].socket.resource_ops = &pccard_nonstatic_ops; |
1383 | socket[i].socket.owner = THIS_MODULE; | 1387 | socket[i].socket.owner = THIS_MODULE; |
@@ -1415,7 +1419,7 @@ static void __exit exit_i82365(void) | |||
1415 | if (socket[i].flags & IS_REGISTERED) | 1419 | if (socket[i].flags & IS_REGISTERED) |
1416 | pcmcia_unregister_socket(&socket[i].socket); | 1420 | pcmcia_unregister_socket(&socket[i].socket); |
1417 | } | 1421 | } |
1418 | platform_device_unregister(&i82365_device); | 1422 | platform_device_unregister(i82365_device); |
1419 | if (poll_interval != 0) | 1423 | if (poll_interval != 0) |
1420 | del_timer_sync(&poll_timer); | 1424 | del_timer_sync(&poll_timer); |
1421 | if (grab_irq != 0) | 1425 | if (grab_irq != 0) |
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index e51d9a8a2796..d81db3a3d4b9 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -532,8 +532,7 @@ void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp) | |||
532 | * @fis: Buffer from which data will be input | 532 | * @fis: Buffer from which data will be input |
533 | * @tf: Taskfile to output | 533 | * @tf: Taskfile to output |
534 | * | 534 | * |
535 | * Converts a standard ATA taskfile to a Serial ATA | 535 | * Converts a serial ATA FIS structure to a standard ATA taskfile. |
536 | * FIS structure (Register - Host to Device). | ||
537 | * | 536 | * |
538 | * LOCKING: | 537 | * LOCKING: |
539 | * Inherited from caller. | 538 | * Inherited from caller. |
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 261be24e1df3..0df4b682965d 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -2276,6 +2276,12 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) | |||
2276 | tf->device = scsicmd[8]; | 2276 | tf->device = scsicmd[8]; |
2277 | tf->command = scsicmd[9]; | 2277 | tf->command = scsicmd[9]; |
2278 | } | 2278 | } |
2279 | /* | ||
2280 | * If slave is possible, enforce correct master/slave bit | ||
2281 | */ | ||
2282 | if (qc->ap->flags & ATA_FLAG_SLAVE_POSS) | ||
2283 | tf->device = qc->dev->devno ? | ||
2284 | tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1; | ||
2279 | 2285 | ||
2280 | /* | 2286 | /* |
2281 | * Filter SET_FEATURES - XFER MODE command -- otherwise, | 2287 | * Filter SET_FEATURES - XFER MODE command -- otherwise, |
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index d3198d9a72c1..55e744d6db88 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c | |||
@@ -687,6 +687,7 @@ static void sil24_port_stop(struct ata_port *ap) | |||
687 | struct sil24_port_priv *pp = ap->private_data; | 687 | struct sil24_port_priv *pp = ap->private_data; |
688 | 688 | ||
689 | sil24_cblk_free(pp, dev); | 689 | sil24_cblk_free(pp, dev); |
690 | ata_pad_free(ap, dev); | ||
690 | kfree(pp); | 691 | kfree(pp); |
691 | } | 692 | } |
692 | 693 | ||
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 2efb317153ce..67e9afa000c1 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/keyboard.h> | 34 | #include <linux/keyboard.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/pm.h> | 36 | #include <linux/pm.h> |
37 | #include <linux/pm_legacy.h> | ||
37 | #include <linux/bitops.h> | 38 | #include <linux/bitops.h> |
38 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
39 | 40 | ||
@@ -1343,7 +1344,7 @@ static void show_serial_version(void) | |||
1343 | printk("MC68328 serial driver version 1.00\n"); | 1344 | printk("MC68328 serial driver version 1.00\n"); |
1344 | } | 1345 | } |
1345 | 1346 | ||
1346 | #ifdef CONFIG_PM | 1347 | #ifdef CONFIG_PM_LEGACY |
1347 | /* Serial Power management | 1348 | /* Serial Power management |
1348 | * The console (currently fixed at line 0) is a special case for power | 1349 | * The console (currently fixed at line 0) is a special case for power |
1349 | * management because the kernel is so chatty. The console will be | 1350 | * management because the kernel is so chatty. The console will be |
@@ -1393,7 +1394,7 @@ void startup_console(void) | |||
1393 | struct m68k_serial *info = &m68k_soft[0]; | 1394 | struct m68k_serial *info = &m68k_soft[0]; |
1394 | startup(info); | 1395 | startup(info); |
1395 | } | 1396 | } |
1396 | #endif | 1397 | #endif /* CONFIG_PM_LEGACY */ |
1397 | 1398 | ||
1398 | 1399 | ||
1399 | static struct tty_operations rs_ops = { | 1400 | static struct tty_operations rs_ops = { |
@@ -1486,7 +1487,7 @@ rs68328_init(void) | |||
1486 | IRQ_FLG_STD, | 1487 | IRQ_FLG_STD, |
1487 | "M68328_UART", NULL)) | 1488 | "M68328_UART", NULL)) |
1488 | panic("Unable to attach 68328 serial interrupt\n"); | 1489 | panic("Unable to attach 68328 serial interrupt\n"); |
1489 | #ifdef CONFIG_PM | 1490 | #ifdef CONFIG_PM_LEGACY |
1490 | serial_pm[i] = pm_register(PM_SYS_DEV, PM_SYS_COM, serial_pm_callback); | 1491 | serial_pm[i] = pm_register(PM_SYS_DEV, PM_SYS_COM, serial_pm_callback); |
1491 | if (serial_pm[i]) | 1492 | if (serial_pm[i]) |
1492 | serial_pm[i]->data = info; | 1493 | serial_pm[i]->data = info; |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 3742753241ee..e08510d09ff6 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -999,7 +999,10 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) | |||
999 | serial_outp(up, UART_MCR, save_mcr); | 999 | serial_outp(up, UART_MCR, save_mcr); |
1000 | serial8250_clear_fifos(up); | 1000 | serial8250_clear_fifos(up); |
1001 | (void)serial_in(up, UART_RX); | 1001 | (void)serial_in(up, UART_RX); |
1002 | serial_outp(up, UART_IER, 0); | 1002 | if (up->capabilities & UART_CAP_UUE) |
1003 | serial_outp(up, UART_IER, UART_IER_UUE); | ||
1004 | else | ||
1005 | serial_outp(up, UART_IER, 0); | ||
1003 | 1006 | ||
1004 | out: | 1007 | out: |
1005 | spin_unlock_irqrestore(&up->port.lock, flags); | 1008 | spin_unlock_irqrestore(&up->port.lock, flags); |
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 5d8660a42b77..b79ed0665d51 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c | |||
@@ -323,6 +323,8 @@ static const struct pnp_device_id pnp_dev_table[] = { | |||
323 | { "USR9180", 0 }, | 323 | { "USR9180", 0 }, |
324 | /* U.S. Robotics 56K Voice INT PnP*/ | 324 | /* U.S. Robotics 56K Voice INT PnP*/ |
325 | { "USR9190", 0 }, | 325 | { "USR9190", 0 }, |
326 | /* HP Compaq Tablet PC tc1100 Wacom tablet */ | ||
327 | { "WACF005", 0 }, | ||
326 | /* Rockwell's (PORALiNK) 33600 INT PNP */ | 328 | /* Rockwell's (PORALiNK) 33600 INT PNP */ |
327 | { "WCI0003", 0 }, | 329 | { "WCI0003", 0 }, |
328 | /* Unkown PnP modems */ | 330 | /* Unkown PnP modems */ |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 25825f2aba22..987d22b53c22 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Based on ppc8xx.c by Thomas Gleixner | 7 | * Based on ppc8xx.c by Thomas Gleixner |
8 | * Based on drivers/serial/amba.c by Russell King | 8 | * Based on drivers/serial/amba.c by Russell King |
9 | * | 9 | * |
10 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) | 10 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) |
11 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) | 11 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) |
12 | * | 12 | * |
13 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 13 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index 4b0786e7eb7f..d789ee55cbb7 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Driver for CPM (SCC/SMC) serial ports; CPM1 definitions | 4 | * Driver for CPM (SCC/SMC) serial ports; CPM1 definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) | 6 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) |
7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) | 7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) |
8 | * | 8 | * |
9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index 15ad58d94889..fd9e53ed3feb 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Driver for CPM (SCC/SMC) serial ports; CPM2 definitions | 4 | * Driver for CPM (SCC/SMC) serial ports; CPM2 definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) | 6 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) |
7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) | 7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) |
8 | * | 8 | * |
9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index e63b9dffc8d7..4d8516d1bb71 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * dz.c: Serial port driver for DECStations equiped | 2 | * dz.c: Serial port driver for DECStations equiped |
3 | * with the DZ chipset. | 3 | * with the DZ chipset. |
4 | * | 4 | * |
5 | * Copyright (C) 1998 Olivier A. D. Lebaillif | 5 | * Copyright (C) 1998 Olivier A. D. Lebaillif |
6 | * | 6 | * |
7 | * Email: olivier.lebaillif@ifrsys.com | 7 | * Email: olivier.lebaillif@ifrsys.com |
8 | * | 8 | * |
9 | * [31-AUG-98] triemer | 9 | * [31-AUG-98] triemer |
@@ -11,14 +11,14 @@ | |||
11 | * removed base_addr code - moving address assignment to setup.c | 11 | * removed base_addr code - moving address assignment to setup.c |
12 | * Changed name of dz_init to rs_init to be consistent with tc code | 12 | * Changed name of dz_init to rs_init to be consistent with tc code |
13 | * [13-NOV-98] triemer fixed code to receive characters | 13 | * [13-NOV-98] triemer fixed code to receive characters |
14 | * after patches by harald to irq code. | 14 | * after patches by harald to irq code. |
15 | * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout | 15 | * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout |
16 | * field from "current" - somewhere between 2.1.121 and 2.1.131 | 16 | * field from "current" - somewhere between 2.1.121 and 2.1.131 |
17 | Qua Jun 27 15:02:26 BRT 2001 | 17 | Qua Jun 27 15:02:26 BRT 2001 |
18 | * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups | 18 | * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups |
19 | * | 19 | * |
20 | * Parts (C) 1999 David Airlie, airlied@linux.ie | 20 | * Parts (C) 1999 David Airlie, airlied@linux.ie |
21 | * [07-SEP-99] Bugfixes | 21 | * [07-SEP-99] Bugfixes |
22 | * | 22 | * |
23 | * [06-Jan-2002] Russell King <rmk@arm.linux.org.uk> | 23 | * [06-Jan-2002] Russell King <rmk@arm.linux.org.uk> |
24 | * Converted to new serial core | 24 | * Converted to new serial core |
@@ -64,7 +64,7 @@ static struct dz_port dz_ports[DZ_NB_PORT]; | |||
64 | 64 | ||
65 | #ifdef DEBUG_DZ | 65 | #ifdef DEBUG_DZ |
66 | /* | 66 | /* |
67 | * debugging code to send out chars via prom | 67 | * debugging code to send out chars via prom |
68 | */ | 68 | */ |
69 | static void debug_console(const char *s, int count) | 69 | static void debug_console(const char *s, int count) |
70 | { | 70 | { |
@@ -82,7 +82,7 @@ static void debug_console(const char *s, int count) | |||
82 | * ------------------------------------------------------------ | 82 | * ------------------------------------------------------------ |
83 | * dz_in () and dz_out () | 83 | * dz_in () and dz_out () |
84 | * | 84 | * |
85 | * These routines are used to access the registers of the DZ | 85 | * These routines are used to access the registers of the DZ |
86 | * chip, hiding relocation differences between implementation. | 86 | * chip, hiding relocation differences between implementation. |
87 | * ------------------------------------------------------------ | 87 | * ------------------------------------------------------------ |
88 | */ | 88 | */ |
@@ -106,8 +106,8 @@ static inline void dz_out(struct dz_port *dport, unsigned offset, | |||
106 | * ------------------------------------------------------------ | 106 | * ------------------------------------------------------------ |
107 | * rs_stop () and rs_start () | 107 | * rs_stop () and rs_start () |
108 | * | 108 | * |
109 | * These routines are called before setting or resetting | 109 | * These routines are called before setting or resetting |
110 | * tty->stopped. They enable or disable transmitter interrupts, | 110 | * tty->stopped. They enable or disable transmitter interrupts, |
111 | * as necessary. | 111 | * as necessary. |
112 | * ------------------------------------------------------------ | 112 | * ------------------------------------------------------------ |
113 | */ | 113 | */ |
@@ -156,17 +156,17 @@ static void dz_enable_ms(struct uart_port *port) | |||
156 | 156 | ||
157 | /* | 157 | /* |
158 | * ------------------------------------------------------------ | 158 | * ------------------------------------------------------------ |
159 | * Here starts the interrupt handling routines. All of the | 159 | * Here starts the interrupt handling routines. All of the |
160 | * following subroutines are declared as inline and are folded | 160 | * following subroutines are declared as inline and are folded |
161 | * into dz_interrupt. They were separated out for readability's | 161 | * into dz_interrupt. They were separated out for readability's |
162 | * sake. | 162 | * sake. |
163 | * | 163 | * |
164 | * Note: rs_interrupt() is a "fast" interrupt, which means that it | 164 | * Note: rs_interrupt() is a "fast" interrupt, which means that it |
165 | * runs with interrupts turned off. People who may want to modify | 165 | * runs with interrupts turned off. People who may want to modify |
166 | * rs_interrupt() should try to keep the interrupt handler as fast as | 166 | * rs_interrupt() should try to keep the interrupt handler as fast as |
167 | * possible. After you are done making modifications, it is not a bad | 167 | * possible. After you are done making modifications, it is not a bad |
168 | * idea to do: | 168 | * idea to do: |
169 | * | 169 | * |
170 | * make drivers/serial/dz.s | 170 | * make drivers/serial/dz.s |
171 | * | 171 | * |
172 | * and look at the resulting assemble code in dz.s. | 172 | * and look at the resulting assemble code in dz.s. |
@@ -403,7 +403,7 @@ static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl) | |||
403 | * startup () | 403 | * startup () |
404 | * | 404 | * |
405 | * various initialization tasks | 405 | * various initialization tasks |
406 | * ------------------------------------------------------------------- | 406 | * ------------------------------------------------------------------- |
407 | */ | 407 | */ |
408 | static int dz_startup(struct uart_port *uport) | 408 | static int dz_startup(struct uart_port *uport) |
409 | { | 409 | { |
@@ -430,13 +430,13 @@ static int dz_startup(struct uart_port *uport) | |||
430 | return 0; | 430 | return 0; |
431 | } | 431 | } |
432 | 432 | ||
433 | /* | 433 | /* |
434 | * ------------------------------------------------------------------- | 434 | * ------------------------------------------------------------------- |
435 | * shutdown () | 435 | * shutdown () |
436 | * | 436 | * |
437 | * This routine will shutdown a serial port; interrupts are disabled, and | 437 | * This routine will shutdown a serial port; interrupts are disabled, and |
438 | * DTR is dropped if the hangup on close termio flag is on. | 438 | * DTR is dropped if the hangup on close termio flag is on. |
439 | * ------------------------------------------------------------------- | 439 | * ------------------------------------------------------------------- |
440 | */ | 440 | */ |
441 | static void dz_shutdown(struct uart_port *uport) | 441 | static void dz_shutdown(struct uart_port *uport) |
442 | { | 442 | { |
@@ -451,7 +451,7 @@ static void dz_shutdown(struct uart_port *uport) | |||
451 | * release the bus after transmitting. This must be done when | 451 | * release the bus after transmitting. This must be done when |
452 | * the transmit shift register is empty, not be done when the | 452 | * the transmit shift register is empty, not be done when the |
453 | * transmit holding register is empty. This functionality | 453 | * transmit holding register is empty. This functionality |
454 | * allows an RS485 driver to be written in user space. | 454 | * allows an RS485 driver to be written in user space. |
455 | */ | 455 | */ |
456 | static unsigned int dz_tx_empty(struct uart_port *uport) | 456 | static unsigned int dz_tx_empty(struct uart_port *uport) |
457 | { | 457 | { |
@@ -645,9 +645,9 @@ static void __init dz_init_ports(void) | |||
645 | 645 | ||
646 | if (mips_machtype == MACH_DS23100 || | 646 | if (mips_machtype == MACH_DS23100 || |
647 | mips_machtype == MACH_DS5100) | 647 | mips_machtype == MACH_DS5100) |
648 | base = (unsigned long) KN01_DZ11_BASE; | 648 | base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_DZ11); |
649 | else | 649 | else |
650 | base = (unsigned long) KN02_DZ11_BASE; | 650 | base = CKSEG1ADDR(KN02_SLOT_BASE + KN02_DZ11); |
651 | 651 | ||
652 | for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { | 652 | for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { |
653 | spin_lock_init(&dport->port.lock); | 653 | spin_lock_init(&dport->port.lock); |
@@ -695,13 +695,13 @@ static void dz_console_put_char(struct dz_port *dport, unsigned char ch) | |||
695 | 695 | ||
696 | spin_unlock_irqrestore(&dport->port.lock, flags); | 696 | spin_unlock_irqrestore(&dport->port.lock, flags); |
697 | } | 697 | } |
698 | /* | 698 | /* |
699 | * ------------------------------------------------------------------- | 699 | * ------------------------------------------------------------------- |
700 | * dz_console_print () | 700 | * dz_console_print () |
701 | * | 701 | * |
702 | * dz_console_print is registered for printk. | 702 | * dz_console_print is registered for printk. |
703 | * The console must be locked when we get here. | 703 | * The console must be locked when we get here. |
704 | * ------------------------------------------------------------------- | 704 | * ------------------------------------------------------------------- |
705 | */ | 705 | */ |
706 | static void dz_console_print(struct console *cons, | 706 | static void dz_console_print(struct console *cons, |
707 | const char *str, | 707 | const char *str, |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 5d3cb8486447..b8727d9bf690 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -725,7 +725,7 @@ mpc52xx_uart_probe(struct platform_device *dev) | |||
725 | int i, idx, ret; | 725 | int i, idx, ret; |
726 | 726 | ||
727 | /* Check validity & presence */ | 727 | /* Check validity & presence */ |
728 | idx = pdev->id; | 728 | idx = dev->id; |
729 | if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM) | 729 | if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM) |
730 | return -EINVAL; | 730 | return -EINVAL; |
731 | 731 | ||
@@ -748,7 +748,7 @@ mpc52xx_uart_probe(struct platform_device *dev) | |||
748 | port->ops = &mpc52xx_uart_ops; | 748 | port->ops = &mpc52xx_uart_ops; |
749 | 749 | ||
750 | /* Search for IRQ and mapbase */ | 750 | /* Search for IRQ and mapbase */ |
751 | for (i=0 ; i<pdev->num_resources ; i++, res++) { | 751 | for (i=0 ; i<dev->num_resources ; i++, res++) { |
752 | if (res->flags & IORESOURCE_MEM) | 752 | if (res->flags & IORESOURCE_MEM) |
753 | port->mapbase = res->start; | 753 | port->mapbase = res->start; |
754 | else if (res->flags & IORESOURCE_IRQ) | 754 | else if (res->flags & IORESOURCE_IRQ) |
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index fd9deee20e05..0e3daf6d7b50 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c | |||
@@ -156,7 +156,7 @@ static void sa1100_stop_tx(struct uart_port *port) | |||
156 | } | 156 | } |
157 | 157 | ||
158 | /* | 158 | /* |
159 | * interrupts may not be disabled on entry | 159 | * port locked and interrupts disabled |
160 | */ | 160 | */ |
161 | static void sa1100_start_tx(struct uart_port *port) | 161 | static void sa1100_start_tx(struct uart_port *port) |
162 | { | 162 | { |
@@ -164,11 +164,9 @@ static void sa1100_start_tx(struct uart_port *port) | |||
164 | unsigned long flags; | 164 | unsigned long flags; |
165 | u32 utcr3; | 165 | u32 utcr3; |
166 | 166 | ||
167 | spin_lock_irqsave(&sport->port.lock, flags); | ||
168 | utcr3 = UART_GET_UTCR3(sport); | 167 | utcr3 = UART_GET_UTCR3(sport); |
169 | sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS); | 168 | sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS); |
170 | UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE); | 169 | UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE); |
171 | spin_unlock_irqrestore(&sport->port.lock, flags); | ||
172 | } | 170 | } |
173 | 171 | ||
174 | /* | 172 | /* |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 427a23858076..2331296e1e17 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -209,33 +209,45 @@ static void uart_shutdown(struct uart_state *state) | |||
209 | struct uart_info *info = state->info; | 209 | struct uart_info *info = state->info; |
210 | struct uart_port *port = state->port; | 210 | struct uart_port *port = state->port; |
211 | 211 | ||
212 | if (!(info->flags & UIF_INITIALIZED)) | ||
213 | return; | ||
214 | |||
215 | /* | 212 | /* |
216 | * Turn off DTR and RTS early. | 213 | * Set the TTY IO error marker |
217 | */ | 214 | */ |
218 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) | 215 | if (info->tty) |
219 | uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | 216 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
220 | 217 | ||
221 | /* | 218 | if (info->flags & UIF_INITIALIZED) { |
222 | * clear delta_msr_wait queue to avoid mem leaks: we may free | 219 | info->flags &= ~UIF_INITIALIZED; |
223 | * the irq here so the queue might never be woken up. Note | ||
224 | * that we won't end up waiting on delta_msr_wait again since | ||
225 | * any outstanding file descriptors should be pointing at | ||
226 | * hung_up_tty_fops now. | ||
227 | */ | ||
228 | wake_up_interruptible(&info->delta_msr_wait); | ||
229 | 220 | ||
230 | /* | 221 | /* |
231 | * Free the IRQ and disable the port. | 222 | * Turn off DTR and RTS early. |
232 | */ | 223 | */ |
233 | port->ops->shutdown(port); | 224 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) |
225 | uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
226 | |||
227 | /* | ||
228 | * clear delta_msr_wait queue to avoid mem leaks: we may free | ||
229 | * the irq here so the queue might never be woken up. Note | ||
230 | * that we won't end up waiting on delta_msr_wait again since | ||
231 | * any outstanding file descriptors should be pointing at | ||
232 | * hung_up_tty_fops now. | ||
233 | */ | ||
234 | wake_up_interruptible(&info->delta_msr_wait); | ||
235 | |||
236 | /* | ||
237 | * Free the IRQ and disable the port. | ||
238 | */ | ||
239 | port->ops->shutdown(port); | ||
240 | |||
241 | /* | ||
242 | * Ensure that the IRQ handler isn't running on another CPU. | ||
243 | */ | ||
244 | synchronize_irq(port->irq); | ||
245 | } | ||
234 | 246 | ||
235 | /* | 247 | /* |
236 | * Ensure that the IRQ handler isn't running on another CPU. | 248 | * kill off our tasklet |
237 | */ | 249 | */ |
238 | synchronize_irq(port->irq); | 250 | tasklet_kill(&info->tlet); |
239 | 251 | ||
240 | /* | 252 | /* |
241 | * Free the transmit buffer page. | 253 | * Free the transmit buffer page. |
@@ -244,15 +256,6 @@ static void uart_shutdown(struct uart_state *state) | |||
244 | free_page((unsigned long)info->xmit.buf); | 256 | free_page((unsigned long)info->xmit.buf); |
245 | info->xmit.buf = NULL; | 257 | info->xmit.buf = NULL; |
246 | } | 258 | } |
247 | |||
248 | /* | ||
249 | * kill off our tasklet | ||
250 | */ | ||
251 | tasklet_kill(&info->tlet); | ||
252 | if (info->tty) | ||
253 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
254 | |||
255 | info->flags &= ~UIF_INITIALIZED; | ||
256 | } | 259 | } |
257 | 260 | ||
258 | /** | 261 | /** |
@@ -1928,14 +1931,25 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
1928 | 1931 | ||
1929 | if (state->info && state->info->flags & UIF_INITIALIZED) { | 1932 | if (state->info && state->info->flags & UIF_INITIALIZED) { |
1930 | struct uart_ops *ops = port->ops; | 1933 | struct uart_ops *ops = port->ops; |
1934 | int ret; | ||
1931 | 1935 | ||
1932 | ops->set_mctrl(port, 0); | 1936 | ops->set_mctrl(port, 0); |
1933 | ops->startup(port); | 1937 | ret = ops->startup(port); |
1934 | uart_change_speed(state, NULL); | 1938 | if (ret == 0) { |
1935 | spin_lock_irq(&port->lock); | 1939 | uart_change_speed(state, NULL); |
1936 | ops->set_mctrl(port, port->mctrl); | 1940 | spin_lock_irq(&port->lock); |
1937 | ops->start_tx(port); | 1941 | ops->set_mctrl(port, port->mctrl); |
1938 | spin_unlock_irq(&port->lock); | 1942 | ops->start_tx(port); |
1943 | spin_unlock_irq(&port->lock); | ||
1944 | } else { | ||
1945 | /* | ||
1946 | * Failed to resume - maybe hardware went away? | ||
1947 | * Clear the "initialized" flag so we won't try | ||
1948 | * to call the low level drivers shutdown method. | ||
1949 | */ | ||
1950 | state->info->flags &= ~UIF_INITIALIZED; | ||
1951 | uart_shutdown(state); | ||
1952 | } | ||
1939 | } | 1953 | } |
1940 | 1954 | ||
1941 | up(&state->sem); | 1955 | up(&state->sem); |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index e7802ffe549a..bcea87c3cc06 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -106,8 +106,7 @@ enum { | |||
106 | FBCON_LOGO_DONTSHOW = -3 /* do not show the logo */ | 106 | FBCON_LOGO_DONTSHOW = -3 /* do not show the logo */ |
107 | }; | 107 | }; |
108 | 108 | ||
109 | struct display fb_display[MAX_NR_CONSOLES]; | 109 | static struct display fb_display[MAX_NR_CONSOLES]; |
110 | EXPORT_SYMBOL(fb_display); | ||
111 | 110 | ||
112 | static signed char con2fb_map[MAX_NR_CONSOLES]; | 111 | static signed char con2fb_map[MAX_NR_CONSOLES]; |
113 | static signed char con2fb_map_boot[MAX_NR_CONSOLES]; | 112 | static signed char con2fb_map_boot[MAX_NR_CONSOLES]; |
@@ -653,13 +652,12 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info, | |||
653 | { | 652 | { |
654 | struct fbcon_ops *ops = info->fbcon_par; | 653 | struct fbcon_ops *ops = info->fbcon_par; |
655 | 654 | ||
655 | ops->p = (p) ? p : &fb_display[vc->vc_num]; | ||
656 | |||
656 | if ((info->flags & FBINFO_MISC_TILEBLITTING)) | 657 | if ((info->flags & FBINFO_MISC_TILEBLITTING)) |
657 | fbcon_set_tileops(vc, info, p, ops); | 658 | fbcon_set_tileops(vc, info, p, ops); |
658 | else { | 659 | else { |
659 | struct display *disp; | 660 | fbcon_set_rotation(info, ops->p); |
660 | |||
661 | disp = (p) ? p : &fb_display[vc->vc_num]; | ||
662 | fbcon_set_rotation(info, disp); | ||
663 | fbcon_set_bitops(ops); | 661 | fbcon_set_bitops(ops); |
664 | } | 662 | } |
665 | } | 663 | } |
@@ -668,11 +666,10 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info, | |||
668 | struct display *p) | 666 | struct display *p) |
669 | { | 667 | { |
670 | struct fbcon_ops *ops = info->fbcon_par; | 668 | struct fbcon_ops *ops = info->fbcon_par; |
671 | struct display *disp; | ||
672 | 669 | ||
673 | info->flags &= ~FBINFO_MISC_TILEBLITTING; | 670 | info->flags &= ~FBINFO_MISC_TILEBLITTING; |
674 | disp = (p) ? p : &fb_display[vc->vc_num]; | 671 | ops->p = (p) ? p : &fb_display[vc->vc_num]; |
675 | fbcon_set_rotation(info, disp); | 672 | fbcon_set_rotation(info, ops->p); |
676 | fbcon_set_bitops(ops); | 673 | fbcon_set_bitops(ops); |
677 | } | 674 | } |
678 | #endif /* CONFIG_MISC_TILEBLITTING */ | 675 | #endif /* CONFIG_MISC_TILEBLITTING */ |
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index accfd7bd8e93..6892e7ff34de 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h | |||
@@ -52,8 +52,6 @@ struct display { | |||
52 | struct fb_videomode *mode; | 52 | struct fb_videomode *mode; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | extern struct display fb_display[]; | ||
56 | |||
57 | struct fbcon_ops { | 55 | struct fbcon_ops { |
58 | void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, | 56 | void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, |
59 | int sx, int dy, int dx, int height, int width); | 57 | int sx, int dy, int dx, int height, int width); |
@@ -73,6 +71,7 @@ struct fbcon_ops { | |||
73 | struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ | 71 | struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ |
74 | struct timer_list cursor_timer; /* Cursor timer */ | 72 | struct timer_list cursor_timer; /* Cursor timer */ |
75 | struct fb_cursor cursor_state; | 73 | struct fb_cursor cursor_state; |
74 | struct display *p; | ||
76 | int currcon; /* Current VC. */ | 75 | int currcon; /* Current VC. */ |
77 | int cursor_flash; | 76 | int cursor_flash; |
78 | int cursor_reset; | 77 | int cursor_reset; |
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c index 680aabab73c5..3afd1eeb1ade 100644 --- a/drivers/video/console/fbcon_ccw.c +++ b/drivers/video/console/fbcon_ccw.c | |||
@@ -63,9 +63,9 @@ static inline void ccw_update_attr(u8 *dst, u8 *src, int attribute, | |||
63 | static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | 63 | static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, |
64 | int sx, int dy, int dx, int height, int width) | 64 | int sx, int dy, int dx, int height, int width) |
65 | { | 65 | { |
66 | struct display *p = &fb_display[vc->vc_num]; | 66 | struct fbcon_ops *ops = info->fbcon_par; |
67 | struct fb_copyarea area; | 67 | struct fb_copyarea area; |
68 | u32 vyres = GETVYRES(p->scrollmode, info); | 68 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
69 | 69 | ||
70 | area.sx = sy * vc->vc_font.height; | 70 | area.sx = sy * vc->vc_font.height; |
71 | area.sy = vyres - ((sx + width) * vc->vc_font.width); | 71 | area.sy = vyres - ((sx + width) * vc->vc_font.width); |
@@ -80,10 +80,10 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |||
80 | static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, | 80 | static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, |
81 | int sx, int height, int width) | 81 | int sx, int height, int width) |
82 | { | 82 | { |
83 | struct display *p = &fb_display[vc->vc_num]; | 83 | struct fbcon_ops *ops = info->fbcon_par; |
84 | struct fb_fillrect region; | 84 | struct fb_fillrect region; |
85 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 85 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
86 | u32 vyres = GETVYRES(p->scrollmode, info); | 86 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
87 | 87 | ||
88 | region.color = attr_bgcol_ec(bgshift,vc); | 88 | region.color = attr_bgcol_ec(bgshift,vc); |
89 | region.dx = sy * vc->vc_font.height; | 89 | region.dx = sy * vc->vc_font.height; |
@@ -131,7 +131,6 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info, | |||
131 | int fg, int bg) | 131 | int fg, int bg) |
132 | { | 132 | { |
133 | struct fb_image image; | 133 | struct fb_image image; |
134 | struct display *p = &fb_display[vc->vc_num]; | ||
135 | struct fbcon_ops *ops = info->fbcon_par; | 134 | struct fbcon_ops *ops = info->fbcon_par; |
136 | u32 width = (vc->vc_font.height + 7)/8; | 135 | u32 width = (vc->vc_font.height + 7)/8; |
137 | u32 cellsize = width * vc->vc_font.width; | 136 | u32 cellsize = width * vc->vc_font.width; |
@@ -141,7 +140,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info, | |||
141 | u32 cnt, pitch, size; | 140 | u32 cnt, pitch, size; |
142 | u32 attribute = get_attribute(info, scr_readw(s)); | 141 | u32 attribute = get_attribute(info, scr_readw(s)); |
143 | u8 *dst, *buf = NULL; | 142 | u8 *dst, *buf = NULL; |
144 | u32 vyres = GETVYRES(p->scrollmode, info); | 143 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
145 | 144 | ||
146 | if (!ops->fontbuffer) | 145 | if (!ops->fontbuffer) |
147 | return; | 146 | return; |
@@ -397,9 +396,8 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, | |||
397 | int ccw_update_start(struct fb_info *info) | 396 | int ccw_update_start(struct fb_info *info) |
398 | { | 397 | { |
399 | struct fbcon_ops *ops = info->fbcon_par; | 398 | struct fbcon_ops *ops = info->fbcon_par; |
400 | struct display *p = &fb_display[ops->currcon]; | ||
401 | u32 yoffset; | 399 | u32 yoffset; |
402 | u32 vyres = GETVYRES(p->scrollmode, info); | 400 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
403 | int err; | 401 | int err; |
404 | 402 | ||
405 | yoffset = (vyres - info->var.yres) - ops->var.xoffset; | 403 | yoffset = (vyres - info->var.yres) - ops->var.xoffset; |
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c index 6c6f3b6dd175..6d92b8456206 100644 --- a/drivers/video/console/fbcon_cw.c +++ b/drivers/video/console/fbcon_cw.c | |||
@@ -49,9 +49,9 @@ static inline void cw_update_attr(u8 *dst, u8 *src, int attribute, | |||
49 | static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | 49 | static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, |
50 | int sx, int dy, int dx, int height, int width) | 50 | int sx, int dy, int dx, int height, int width) |
51 | { | 51 | { |
52 | struct display *p = &fb_display[vc->vc_num]; | 52 | struct fbcon_ops *ops = info->fbcon_par; |
53 | struct fb_copyarea area; | 53 | struct fb_copyarea area; |
54 | u32 vxres = GETVXRES(p->scrollmode, info); | 54 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
55 | 55 | ||
56 | area.sx = vxres - ((sy + height) * vc->vc_font.height); | 56 | area.sx = vxres - ((sy + height) * vc->vc_font.height); |
57 | area.sy = sx * vc->vc_font.width; | 57 | area.sy = sx * vc->vc_font.width; |
@@ -66,10 +66,10 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |||
66 | static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, | 66 | static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, |
67 | int sx, int height, int width) | 67 | int sx, int height, int width) |
68 | { | 68 | { |
69 | struct display *p = &fb_display[vc->vc_num]; | 69 | struct fbcon_ops *ops = info->fbcon_par; |
70 | struct fb_fillrect region; | 70 | struct fb_fillrect region; |
71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
72 | u32 vxres = GETVXRES(p->scrollmode, info); | 72 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
73 | 73 | ||
74 | region.color = attr_bgcol_ec(bgshift,vc); | 74 | region.color = attr_bgcol_ec(bgshift,vc); |
75 | region.dx = vxres - ((sy + height) * vc->vc_font.height); | 75 | region.dx = vxres - ((sy + height) * vc->vc_font.height); |
@@ -117,7 +117,6 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info, | |||
117 | int fg, int bg) | 117 | int fg, int bg) |
118 | { | 118 | { |
119 | struct fb_image image; | 119 | struct fb_image image; |
120 | struct display *p = &fb_display[vc->vc_num]; | ||
121 | struct fbcon_ops *ops = info->fbcon_par; | 120 | struct fbcon_ops *ops = info->fbcon_par; |
122 | u32 width = (vc->vc_font.height + 7)/8; | 121 | u32 width = (vc->vc_font.height + 7)/8; |
123 | u32 cellsize = width * vc->vc_font.width; | 122 | u32 cellsize = width * vc->vc_font.width; |
@@ -127,7 +126,7 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info, | |||
127 | u32 cnt, pitch, size; | 126 | u32 cnt, pitch, size; |
128 | u32 attribute = get_attribute(info, scr_readw(s)); | 127 | u32 attribute = get_attribute(info, scr_readw(s)); |
129 | u8 *dst, *buf = NULL; | 128 | u8 *dst, *buf = NULL; |
130 | u32 vxres = GETVXRES(p->scrollmode, info); | 129 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
131 | 130 | ||
132 | if (!ops->fontbuffer) | 131 | if (!ops->fontbuffer) |
133 | return; | 132 | return; |
@@ -381,8 +380,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, | |||
381 | int cw_update_start(struct fb_info *info) | 380 | int cw_update_start(struct fb_info *info) |
382 | { | 381 | { |
383 | struct fbcon_ops *ops = info->fbcon_par; | 382 | struct fbcon_ops *ops = info->fbcon_par; |
384 | struct display *p = &fb_display[ops->currcon]; | 383 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
385 | u32 vxres = GETVXRES(p->scrollmode, info); | ||
386 | u32 xoffset; | 384 | u32 xoffset; |
387 | int err; | 385 | int err; |
388 | 386 | ||
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c index 2e1d9d4249cd..c4d7c89212b4 100644 --- a/drivers/video/console/fbcon_ud.c +++ b/drivers/video/console/fbcon_ud.c | |||
@@ -48,10 +48,10 @@ static inline void ud_update_attr(u8 *dst, u8 *src, int attribute, | |||
48 | static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, | 48 | static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, |
49 | int sx, int dy, int dx, int height, int width) | 49 | int sx, int dy, int dx, int height, int width) |
50 | { | 50 | { |
51 | struct display *p = &fb_display[vc->vc_num]; | 51 | struct fbcon_ops *ops = info->fbcon_par; |
52 | struct fb_copyarea area; | 52 | struct fb_copyarea area; |
53 | u32 vyres = GETVYRES(p->scrollmode, info); | 53 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
54 | u32 vxres = GETVXRES(p->scrollmode, info); | 54 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
55 | 55 | ||
56 | area.sy = vyres - ((sy + height) * vc->vc_font.height); | 56 | area.sy = vyres - ((sy + height) * vc->vc_font.height); |
57 | area.sx = vxres - ((sx + width) * vc->vc_font.width); | 57 | area.sx = vxres - ((sx + width) * vc->vc_font.width); |
@@ -66,11 +66,11 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |||
66 | static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, | 66 | static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, |
67 | int sx, int height, int width) | 67 | int sx, int height, int width) |
68 | { | 68 | { |
69 | struct display *p = &fb_display[vc->vc_num]; | 69 | struct fbcon_ops *ops = info->fbcon_par; |
70 | struct fb_fillrect region; | 70 | struct fb_fillrect region; |
71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
72 | u32 vyres = GETVYRES(p->scrollmode, info); | 72 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
73 | u32 vxres = GETVXRES(p->scrollmode, info); | 73 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
74 | 74 | ||
75 | region.color = attr_bgcol_ec(bgshift,vc); | 75 | region.color = attr_bgcol_ec(bgshift,vc); |
76 | region.dy = vyres - ((sy + height) * vc->vc_font.height); | 76 | region.dy = vyres - ((sy + height) * vc->vc_font.height); |
@@ -153,7 +153,6 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info, | |||
153 | int fg, int bg) | 153 | int fg, int bg) |
154 | { | 154 | { |
155 | struct fb_image image; | 155 | struct fb_image image; |
156 | struct display *p = &fb_display[vc->vc_num]; | ||
157 | struct fbcon_ops *ops = info->fbcon_par; | 156 | struct fbcon_ops *ops = info->fbcon_par; |
158 | u32 width = (vc->vc_font.width + 7)/8; | 157 | u32 width = (vc->vc_font.width + 7)/8; |
159 | u32 cellsize = width * vc->vc_font.height; | 158 | u32 cellsize = width * vc->vc_font.height; |
@@ -163,8 +162,8 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info, | |||
163 | u32 mod = vc->vc_font.width % 8, cnt, pitch, size; | 162 | u32 mod = vc->vc_font.width % 8, cnt, pitch, size; |
164 | u32 attribute = get_attribute(info, scr_readw(s)); | 163 | u32 attribute = get_attribute(info, scr_readw(s)); |
165 | u8 *dst, *buf = NULL; | 164 | u8 *dst, *buf = NULL; |
166 | u32 vyres = GETVYRES(p->scrollmode, info); | 165 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
167 | u32 vxres = GETVXRES(p->scrollmode, info); | 166 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
168 | 167 | ||
169 | if (!ops->fontbuffer) | 168 | if (!ops->fontbuffer) |
170 | return; | 169 | return; |
@@ -421,10 +420,9 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, | |||
421 | int ud_update_start(struct fb_info *info) | 420 | int ud_update_start(struct fb_info *info) |
422 | { | 421 | { |
423 | struct fbcon_ops *ops = info->fbcon_par; | 422 | struct fbcon_ops *ops = info->fbcon_par; |
424 | struct display *p = &fb_display[ops->currcon]; | ||
425 | u32 xoffset, yoffset; | 423 | u32 xoffset, yoffset; |
426 | u32 vyres = GETVYRES(p->scrollmode, info); | 424 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
427 | u32 vxres = GETVXRES(p->scrollmode, info); | 425 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
428 | int err; | 426 | int err; |
429 | 427 | ||
430 | xoffset = (vxres - info->var.xres) - ops->var.xoffset; | 428 | xoffset = (vxres - info->var.xres) - ops->var.xoffset; |
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h index f60b1f432270..3353103e8b0b 100644 --- a/drivers/video/nvidia/nv_proto.h +++ b/drivers/video/nvidia/nv_proto.h | |||
@@ -42,7 +42,7 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, | |||
42 | #define nvidia_probe_i2c_connector(p, c, edid) (-1) | 42 | #define nvidia_probe_i2c_connector(p, c, edid) (-1) |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | #ifdef CONFIG_FB_OF | 45 | #ifdef CONFIG_PPC_OF |
46 | int nvidia_probe_of_connector(struct fb_info *info, int conn, | 46 | int nvidia_probe_of_connector(struct fb_info *info, int conn, |
47 | u8 ** out_edid); | 47 | u8 ** out_edid); |
48 | #else | 48 | #else |
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 0b40a2a721c1..bee09c6e48f6 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
@@ -1301,7 +1301,7 @@ static int nvidiafb_pan_display(struct fb_var_screeninfo *var, | |||
1301 | struct nvidia_par *par = info->par; | 1301 | struct nvidia_par *par = info->par; |
1302 | u32 total; | 1302 | u32 total; |
1303 | 1303 | ||
1304 | total = info->var.yoffset * info->fix.line_length + info->var.xoffset; | 1304 | total = var->yoffset * info->fix.line_length + var->xoffset; |
1305 | 1305 | ||
1306 | NVSetStartAddress(par, total); | 1306 | NVSetStartAddress(par, total); |
1307 | 1307 | ||
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 2c3aa2fcfd91..3e58ddc2bc38 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c | |||
@@ -413,6 +413,7 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
413 | * region already (FIXME) */ | 413 | * region already (FIXME) */ |
414 | request_region(0x3c0, 32, "vesafb"); | 414 | request_region(0x3c0, 32, "vesafb"); |
415 | 415 | ||
416 | #ifdef CONFIG_MTRR | ||
416 | if (mtrr) { | 417 | if (mtrr) { |
417 | unsigned int temp_size = size_total; | 418 | unsigned int temp_size = size_total; |
418 | unsigned int type = 0; | 419 | unsigned int type = 0; |
@@ -450,6 +451,7 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
450 | } while (temp_size >= PAGE_SIZE && rc == -EINVAL); | 451 | } while (temp_size >= PAGE_SIZE && rc == -EINVAL); |
451 | } | 452 | } |
452 | } | 453 | } |
454 | #endif | ||
453 | 455 | ||
454 | info->fbops = &vesafb_ops; | 456 | info->fbops = &vesafb_ops; |
455 | info->var = vesafb_defined; | 457 | info->var = vesafb_defined; |
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index daa46051f55d..f6e24ee85f07 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c | |||
@@ -514,7 +514,7 @@ int __init w100fb_probe(struct platform_device *pdev) | |||
514 | if (remapped_fbuf == NULL) | 514 | if (remapped_fbuf == NULL) |
515 | goto out; | 515 | goto out; |
516 | 516 | ||
517 | info=framebuffer_alloc(sizeof(struct w100fb_par), dev); | 517 | info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev); |
518 | if (!info) { | 518 | if (!info) { |
519 | err = -ENOMEM; | 519 | err = -ENOMEM; |
520 | goto out; | 520 | goto out; |
@@ -457,6 +457,8 @@ static inline struct kiocb *aio_get_req(struct kioctx *ctx) | |||
457 | 457 | ||
458 | static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) | 458 | static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) |
459 | { | 459 | { |
460 | assert_spin_locked(&ctx->ctx_lock); | ||
461 | |||
460 | if (req->ki_dtor) | 462 | if (req->ki_dtor) |
461 | req->ki_dtor(req); | 463 | req->ki_dtor(req); |
462 | kmem_cache_free(kiocb_cachep, req); | 464 | kmem_cache_free(kiocb_cachep, req); |
@@ -498,6 +500,8 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req) | |||
498 | dprintk(KERN_DEBUG "aio_put(%p): f_count=%d\n", | 500 | dprintk(KERN_DEBUG "aio_put(%p): f_count=%d\n", |
499 | req, atomic_read(&req->ki_filp->f_count)); | 501 | req, atomic_read(&req->ki_filp->f_count)); |
500 | 502 | ||
503 | assert_spin_locked(&ctx->ctx_lock); | ||
504 | |||
501 | req->ki_users --; | 505 | req->ki_users --; |
502 | if (unlikely(req->ki_users < 0)) | 506 | if (unlikely(req->ki_users < 0)) |
503 | BUG(); | 507 | BUG(); |
@@ -619,14 +623,13 @@ static void unuse_mm(struct mm_struct *mm) | |||
619 | * the kiocb (to tell the caller to activate the work | 623 | * the kiocb (to tell the caller to activate the work |
620 | * queue to process it), or 0, if it found that it was | 624 | * queue to process it), or 0, if it found that it was |
621 | * already queued. | 625 | * already queued. |
622 | * | ||
623 | * Should be called with the spin lock iocb->ki_ctx->ctx_lock | ||
624 | * held | ||
625 | */ | 626 | */ |
626 | static inline int __queue_kicked_iocb(struct kiocb *iocb) | 627 | static inline int __queue_kicked_iocb(struct kiocb *iocb) |
627 | { | 628 | { |
628 | struct kioctx *ctx = iocb->ki_ctx; | 629 | struct kioctx *ctx = iocb->ki_ctx; |
629 | 630 | ||
631 | assert_spin_locked(&ctx->ctx_lock); | ||
632 | |||
630 | if (list_empty(&iocb->ki_run_list)) { | 633 | if (list_empty(&iocb->ki_run_list)) { |
631 | list_add_tail(&iocb->ki_run_list, | 634 | list_add_tail(&iocb->ki_run_list, |
632 | &ctx->run_list); | 635 | &ctx->run_list); |
@@ -771,13 +774,15 @@ out: | |||
771 | * Process all pending retries queued on the ioctx | 774 | * Process all pending retries queued on the ioctx |
772 | * run list. | 775 | * run list. |
773 | * Assumes it is operating within the aio issuer's mm | 776 | * Assumes it is operating within the aio issuer's mm |
774 | * context. Expects to be called with ctx->ctx_lock held | 777 | * context. |
775 | */ | 778 | */ |
776 | static int __aio_run_iocbs(struct kioctx *ctx) | 779 | static int __aio_run_iocbs(struct kioctx *ctx) |
777 | { | 780 | { |
778 | struct kiocb *iocb; | 781 | struct kiocb *iocb; |
779 | LIST_HEAD(run_list); | 782 | LIST_HEAD(run_list); |
780 | 783 | ||
784 | assert_spin_locked(&ctx->ctx_lock); | ||
785 | |||
781 | list_splice_init(&ctx->run_list, &run_list); | 786 | list_splice_init(&ctx->run_list, &run_list); |
782 | while (!list_empty(&run_list)) { | 787 | while (!list_empty(&run_list)) { |
783 | iocb = list_entry(run_list.next, struct kiocb, | 788 | iocb = list_entry(run_list.next, struct kiocb, |
@@ -937,28 +942,19 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2) | |||
937 | unsigned long tail; | 942 | unsigned long tail; |
938 | int ret; | 943 | int ret; |
939 | 944 | ||
940 | /* Special case handling for sync iocbs: events go directly | 945 | /* |
941 | * into the iocb for fast handling. Note that this will not | 946 | * Special case handling for sync iocbs: |
942 | * work if we allow sync kiocbs to be cancelled. in which | 947 | * - events go directly into the iocb for fast handling |
943 | * case the usage count checks will have to move under ctx_lock | 948 | * - the sync task with the iocb in its stack holds the single iocb |
944 | * for all cases. | 949 | * ref, no other paths have a way to get another ref |
950 | * - the sync task helpfully left a reference to itself in the iocb | ||
945 | */ | 951 | */ |
946 | if (is_sync_kiocb(iocb)) { | 952 | if (is_sync_kiocb(iocb)) { |
947 | int ret; | 953 | BUG_ON(iocb->ki_users != 1); |
948 | |||
949 | iocb->ki_user_data = res; | 954 | iocb->ki_user_data = res; |
950 | if (iocb->ki_users == 1) { | 955 | iocb->ki_users = 0; |
951 | iocb->ki_users = 0; | ||
952 | ret = 1; | ||
953 | } else { | ||
954 | spin_lock_irq(&ctx->ctx_lock); | ||
955 | iocb->ki_users--; | ||
956 | ret = (0 == iocb->ki_users); | ||
957 | spin_unlock_irq(&ctx->ctx_lock); | ||
958 | } | ||
959 | /* sync iocbs put the task here for us */ | ||
960 | wake_up_process(iocb->ki_obj.tsk); | 956 | wake_up_process(iocb->ki_obj.tsk); |
961 | return ret; | 957 | return 1; |
962 | } | 958 | } |
963 | 959 | ||
964 | info = &ctx->ring_info; | 960 | info = &ctx->ring_info; |
@@ -1613,12 +1609,14 @@ asmlinkage long sys_io_submit(aio_context_t ctx_id, long nr, | |||
1613 | 1609 | ||
1614 | /* lookup_kiocb | 1610 | /* lookup_kiocb |
1615 | * Finds a given iocb for cancellation. | 1611 | * Finds a given iocb for cancellation. |
1616 | * MUST be called with ctx->ctx_lock held. | ||
1617 | */ | 1612 | */ |
1618 | static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb, | 1613 | static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb, |
1619 | u32 key) | 1614 | u32 key) |
1620 | { | 1615 | { |
1621 | struct list_head *pos; | 1616 | struct list_head *pos; |
1617 | |||
1618 | assert_spin_locked(&ctx->ctx_lock); | ||
1619 | |||
1622 | /* TODO: use a hash or array, this sucks. */ | 1620 | /* TODO: use a hash or array, this sucks. */ |
1623 | list_for_each(pos, &ctx->active_reqs) { | 1621 | list_for_each(pos, &ctx->active_reqs) { |
1624 | struct kiocb *kiocb = list_kiocb(pos); | 1622 | struct kiocb *kiocb = list_kiocb(pos); |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index e4ed4b31a433..522fa70dd8ea 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -881,7 +881,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
881 | } | 881 | } |
882 | if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) | 882 | if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) |
883 | ext2_warning(sb, __FUNCTION__, | 883 | ext2_warning(sb, __FUNCTION__, |
884 | "mounting ext3 filesystem as ext2\n"); | 884 | "mounting ext3 filesystem as ext2"); |
885 | ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); | 885 | ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); |
886 | percpu_counter_mod(&sbi->s_freeblocks_counter, | 886 | percpu_counter_mod(&sbi->s_freeblocks_counter, |
887 | ext2_count_free_blocks(sb)); | 887 | ext2_count_free_blocks(sb)); |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 5d9b00e28837..8824e84f8a56 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -1384,8 +1384,10 @@ static int ext3_journalled_writepage(struct page *page, | |||
1384 | ClearPageChecked(page); | 1384 | ClearPageChecked(page); |
1385 | ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE, | 1385 | ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE, |
1386 | ext3_get_block); | 1386 | ext3_get_block); |
1387 | if (ret != 0) | 1387 | if (ret != 0) { |
1388 | ext3_journal_stop(handle); | ||
1388 | goto out_unlock; | 1389 | goto out_unlock; |
1390 | } | ||
1389 | ret = walk_page_buffers(handle, page_buffers(page), 0, | 1391 | ret = walk_page_buffers(handle, page_buffers(page), 0, |
1390 | PAGE_CACHE_SIZE, NULL, do_journal_get_write_access); | 1392 | PAGE_CACHE_SIZE, NULL, do_journal_get_write_access); |
1391 | 1393 | ||
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 0e7456ec99fd..3e51dd1da8aa 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c | |||
@@ -284,9 +284,6 @@ int jffs2_fill_scan_buf (struct jffs2_sb_info *c, void *buf, | |||
284 | D1(printk(KERN_WARNING "Read at 0x%x gave only 0x%zx bytes\n", ofs, retlen)); | 284 | D1(printk(KERN_WARNING "Read at 0x%x gave only 0x%zx bytes\n", ofs, retlen)); |
285 | return -EIO; | 285 | return -EIO; |
286 | } | 286 | } |
287 | D2(printk(KERN_DEBUG "Read 0x%x bytes from 0x%08x into buf\n", len, ofs)); | ||
288 | D2(printk(KERN_DEBUG "000: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
289 | buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15])); | ||
290 | return 0; | 287 | return 0; |
291 | } | 288 | } |
292 | 289 | ||
diff --git a/fs/locks.c b/fs/locks.c index a1e8b2248014..250ef53d25ef 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -1105,7 +1105,6 @@ static void time_out_leases(struct inode *inode) | |||
1105 | before = &fl->fl_next; | 1105 | before = &fl->fl_next; |
1106 | continue; | 1106 | continue; |
1107 | } | 1107 | } |
1108 | printk(KERN_INFO "lease broken - owner pid = %d\n", fl->fl_pid); | ||
1109 | lease_modify(before, fl->fl_type & ~F_INPROGRESS); | 1108 | lease_modify(before, fl->fl_type & ~F_INPROGRESS); |
1110 | if (fl == *before) /* lease_modify may have freed fl */ | 1109 | if (fl == *before) /* lease_modify may have freed fl */ |
1111 | before = &fl->fl_next; | 1110 | before = &fl->fl_next; |
@@ -1430,7 +1429,7 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg) | |||
1430 | lock_kernel(); | 1429 | lock_kernel(); |
1431 | 1430 | ||
1432 | error = __setlease(filp, arg, &flp); | 1431 | error = __setlease(filp, arg, &flp); |
1433 | if (error) | 1432 | if (error || arg == F_UNLCK) |
1434 | goto out_unlock; | 1433 | goto out_unlock; |
1435 | 1434 | ||
1436 | error = fasync_helper(fd, filp, 1, &flp->fl_fasync); | 1435 | error = fasync_helper(fd, filp, 1, &flp->fl_fasync); |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index d2fa42006d8f..9ab97cef0daa 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -195,7 +195,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats | |||
195 | 195 | ||
196 | static int show_map(struct seq_file *m, void *v) | 196 | static int show_map(struct seq_file *m, void *v) |
197 | { | 197 | { |
198 | return show_map_internal(m, v, 0); | 198 | return show_map_internal(m, v, NULL); |
199 | } | 199 | } |
200 | 200 | ||
201 | static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd, | 201 | static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd, |
diff --git a/include/asm-alpha/atomic.h b/include/asm-alpha/atomic.h index 20ac3d95ecd9..36505bb4e8cb 100644 --- a/include/asm-alpha/atomic.h +++ b/include/asm-alpha/atomic.h | |||
@@ -177,6 +177,18 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v) | |||
177 | return result; | 177 | return result; |
178 | } | 178 | } |
179 | 179 | ||
180 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
181 | |||
182 | #define atomic_add_unless(v, a, u) \ | ||
183 | ({ \ | ||
184 | int c, old; \ | ||
185 | c = atomic_read(v); \ | ||
186 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
187 | c = old; \ | ||
188 | c != (u); \ | ||
189 | }) | ||
190 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
191 | |||
180 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) | 192 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) |
181 | #define atomic64_dec_return(v) atomic64_sub_return(1,(v)) | 193 | #define atomic64_dec_return(v) atomic64_sub_return(1,(v)) |
182 | 194 | ||
diff --git a/include/asm-arm/arch-pxa/akita.h b/include/asm-arm/arch-pxa/akita.h index 4a1fbcfccc39..5d8cc1d9cb10 100644 --- a/include/asm-arm/arch-pxa/akita.h +++ b/include/asm-arm/arch-pxa/akita.h | |||
@@ -25,6 +25,8 @@ | |||
25 | /* Default Values */ | 25 | /* Default Values */ |
26 | #define AKITA_IOEXP_IO_OUT (AKITA_IOEXP_IR_ON | AKITA_IOEXP_AKIN_PULLUP) | 26 | #define AKITA_IOEXP_IO_OUT (AKITA_IOEXP_IR_ON | AKITA_IOEXP_AKIN_PULLUP) |
27 | 27 | ||
28 | extern struct platform_device akitaioexp_device; | ||
29 | |||
28 | void akita_set_ioexp(struct device *dev, unsigned char bitmask); | 30 | void akita_set_ioexp(struct device *dev, unsigned char bitmask); |
29 | void akita_reset_ioexp(struct device *dev, unsigned char bitmask); | 31 | void akita_reset_ioexp(struct device *dev, unsigned char bitmask); |
30 | 32 | ||
diff --git a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h index 2885972b0855..75b802719723 100644 --- a/include/asm-arm/atomic.h +++ b/include/asm-arm/atomic.h | |||
@@ -80,6 +80,23 @@ static inline int atomic_sub_return(int i, atomic_t *v) | |||
80 | return result; | 80 | return result; |
81 | } | 81 | } |
82 | 82 | ||
83 | static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new) | ||
84 | { | ||
85 | u32 oldval, res; | ||
86 | |||
87 | do { | ||
88 | __asm__ __volatile__("@ atomic_cmpxchg\n" | ||
89 | "ldrex %1, [%2]\n" | ||
90 | "teq %1, %3\n" | ||
91 | "strexeq %0, %4, [%2]\n" | ||
92 | : "=&r" (res), "=&r" (oldval) | ||
93 | : "r" (&ptr->counter), "Ir" (old), "r" (new) | ||
94 | : "cc"); | ||
95 | } while (res); | ||
96 | |||
97 | return oldval; | ||
98 | } | ||
99 | |||
83 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) | 100 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) |
84 | { | 101 | { |
85 | unsigned long tmp, tmp2; | 102 | unsigned long tmp, tmp2; |
@@ -131,6 +148,20 @@ static inline int atomic_sub_return(int i, atomic_t *v) | |||
131 | return val; | 148 | return val; |
132 | } | 149 | } |
133 | 150 | ||
151 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
152 | { | ||
153 | int ret; | ||
154 | unsigned long flags; | ||
155 | |||
156 | local_irq_save(flags); | ||
157 | ret = v->counter; | ||
158 | if (likely(ret == old)) | ||
159 | v->counter = new; | ||
160 | local_irq_restore(flags); | ||
161 | |||
162 | return ret; | ||
163 | } | ||
164 | |||
134 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) | 165 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) |
135 | { | 166 | { |
136 | unsigned long flags; | 167 | unsigned long flags; |
@@ -142,6 +173,17 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) | |||
142 | 173 | ||
143 | #endif /* __LINUX_ARM_ARCH__ */ | 174 | #endif /* __LINUX_ARM_ARCH__ */ |
144 | 175 | ||
176 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
177 | { | ||
178 | int c, old; | ||
179 | |||
180 | c = atomic_read(v); | ||
181 | while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c) | ||
182 | c = old; | ||
183 | return c != u; | ||
184 | } | ||
185 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
186 | |||
145 | #define atomic_add(i, v) (void) atomic_add_return(i, v) | 187 | #define atomic_add(i, v) (void) atomic_add_return(i, v) |
146 | #define atomic_inc(v) (void) atomic_add_return(1, v) | 188 | #define atomic_inc(v) (void) atomic_add_return(1, v) |
147 | #define atomic_sub(i, v) (void) atomic_sub_return(i, v) | 189 | #define atomic_sub(i, v) (void) atomic_sub_return(i, v) |
diff --git a/include/asm-arm26/atomic.h b/include/asm-arm26/atomic.h index 4a88235c0e76..a47cadc59686 100644 --- a/include/asm-arm26/atomic.h +++ b/include/asm-arm26/atomic.h | |||
@@ -62,6 +62,35 @@ static inline int atomic_sub_return(int i, atomic_t *v) | |||
62 | return val; | 62 | return val; |
63 | } | 63 | } |
64 | 64 | ||
65 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
66 | { | ||
67 | int ret; | ||
68 | unsigned long flags; | ||
69 | |||
70 | local_irq_save(flags); | ||
71 | ret = v->counter; | ||
72 | if (likely(ret == old)) | ||
73 | v->counter = new; | ||
74 | local_irq_restore(flags); | ||
75 | |||
76 | return ret; | ||
77 | } | ||
78 | |||
79 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
80 | { | ||
81 | int ret; | ||
82 | unsigned long flags; | ||
83 | |||
84 | local_irq_save(flags); | ||
85 | ret = v->counter; | ||
86 | if (ret != u) | ||
87 | v->counter += a; | ||
88 | local_irq_restore(flags); | ||
89 | |||
90 | return ret != u; | ||
91 | } | ||
92 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
93 | |||
65 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) | 94 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) |
66 | { | 95 | { |
67 | unsigned long flags; | 96 | unsigned long flags; |
diff --git a/include/asm-cris/atomic.h b/include/asm-cris/atomic.h index 8c2e78304523..683b05a57d88 100644 --- a/include/asm-cris/atomic.h +++ b/include/asm-cris/atomic.h | |||
@@ -123,6 +123,33 @@ static inline int atomic_inc_and_test(volatile atomic_t *v) | |||
123 | return retval; | 123 | return retval; |
124 | } | 124 | } |
125 | 125 | ||
126 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
127 | { | ||
128 | int ret; | ||
129 | unsigned long flags; | ||
130 | |||
131 | cris_atomic_save(v, flags); | ||
132 | ret = v->counter; | ||
133 | if (likely(ret == old)) | ||
134 | v->counter = new; | ||
135 | cris_atomic_restore(v, flags); | ||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
140 | { | ||
141 | int ret; | ||
142 | unsigned long flags; | ||
143 | |||
144 | cris_atomic_save(v, flags); | ||
145 | ret = v->counter; | ||
146 | if (ret != u) | ||
147 | v->counter += a; | ||
148 | cris_atomic_restore(v, flags); | ||
149 | return ret != u; | ||
150 | } | ||
151 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
152 | |||
126 | /* Atomic operations are already serializing */ | 153 | /* Atomic operations are already serializing */ |
127 | #define smp_mb__before_atomic_dec() barrier() | 154 | #define smp_mb__before_atomic_dec() barrier() |
128 | #define smp_mb__after_atomic_dec() barrier() | 155 | #define smp_mb__after_atomic_dec() barrier() |
diff --git a/include/asm-frv/atomic.h b/include/asm-frv/atomic.h index e75968463428..f6539ff569c5 100644 --- a/include/asm-frv/atomic.h +++ b/include/asm-frv/atomic.h | |||
@@ -414,4 +414,16 @@ extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new); | |||
414 | 414 | ||
415 | #endif | 415 | #endif |
416 | 416 | ||
417 | #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) | ||
418 | |||
419 | #define atomic_add_unless(v, a, u) \ | ||
420 | ({ \ | ||
421 | int c, old; \ | ||
422 | c = atomic_read(v); \ | ||
423 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
424 | c = old; \ | ||
425 | c != (u); \ | ||
426 | }) | ||
427 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
428 | |||
417 | #endif /* _ASM_ATOMIC_H */ | 429 | #endif /* _ASM_ATOMIC_H */ |
diff --git a/include/asm-h8300/atomic.h b/include/asm-h8300/atomic.h index 7230f6507995..f23d86819ea8 100644 --- a/include/asm-h8300/atomic.h +++ b/include/asm-h8300/atomic.h | |||
@@ -82,6 +82,33 @@ static __inline__ int atomic_dec_and_test(atomic_t *v) | |||
82 | return ret == 0; | 82 | return ret == 0; |
83 | } | 83 | } |
84 | 84 | ||
85 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
86 | { | ||
87 | int ret; | ||
88 | unsigned long flags; | ||
89 | |||
90 | local_irq_save(flags); | ||
91 | ret = v->counter; | ||
92 | if (likely(ret == old)) | ||
93 | v->counter = new; | ||
94 | local_irq_restore(flags); | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
99 | { | ||
100 | int ret; | ||
101 | unsigned long flags; | ||
102 | |||
103 | local_irq_save(flags); | ||
104 | ret = v->counter; | ||
105 | if (ret != u) | ||
106 | v->counter += a; | ||
107 | local_irq_restore(flags); | ||
108 | return ret != u; | ||
109 | } | ||
110 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
111 | |||
85 | static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v) | 112 | static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v) |
86 | { | 113 | { |
87 | __asm__ __volatile__("stc ccr,r1l\n\t" | 114 | __asm__ __volatile__("stc ccr,r1l\n\t" |
diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h index 509720be772a..c68557aa04b2 100644 --- a/include/asm-i386/atomic.h +++ b/include/asm-i386/atomic.h | |||
@@ -215,6 +215,27 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v) | |||
215 | return atomic_add_return(-i,v); | 215 | return atomic_add_return(-i,v); |
216 | } | 216 | } |
217 | 217 | ||
218 | #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) | ||
219 | |||
220 | /** | ||
221 | * atomic_add_unless - add unless the number is a given value | ||
222 | * @v: pointer of type atomic_t | ||
223 | * @a: the amount to add to v... | ||
224 | * @u: ...unless v is equal to u. | ||
225 | * | ||
226 | * Atomically adds @a to @v, so long as it was not @u. | ||
227 | * Returns non-zero if @v was not @u, and zero otherwise. | ||
228 | */ | ||
229 | #define atomic_add_unless(v, a, u) \ | ||
230 | ({ \ | ||
231 | int c, old; \ | ||
232 | c = atomic_read(v); \ | ||
233 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
234 | c = old; \ | ||
235 | c != (u); \ | ||
236 | }) | ||
237 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
238 | |||
218 | #define atomic_inc_return(v) (atomic_add_return(1,v)) | 239 | #define atomic_inc_return(v) (atomic_add_return(1,v)) |
219 | #define atomic_dec_return(v) (atomic_sub_return(1,v)) | 240 | #define atomic_dec_return(v) (atomic_sub_return(1,v)) |
220 | 241 | ||
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h index 97d52ac49e46..772f85da1206 100644 --- a/include/asm-i386/system.h +++ b/include/asm-i386/system.h | |||
@@ -263,6 +263,10 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz | |||
263 | 263 | ||
264 | #ifdef CONFIG_X86_CMPXCHG | 264 | #ifdef CONFIG_X86_CMPXCHG |
265 | #define __HAVE_ARCH_CMPXCHG 1 | 265 | #define __HAVE_ARCH_CMPXCHG 1 |
266 | #define cmpxchg(ptr,o,n)\ | ||
267 | ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ | ||
268 | (unsigned long)(n),sizeof(*(ptr)))) | ||
269 | #endif | ||
266 | 270 | ||
267 | static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, | 271 | static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, |
268 | unsigned long new, int size) | 272 | unsigned long new, int size) |
@@ -291,10 +295,42 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, | |||
291 | return old; | 295 | return old; |
292 | } | 296 | } |
293 | 297 | ||
294 | #define cmpxchg(ptr,o,n)\ | 298 | #ifndef CONFIG_X86_CMPXCHG |
295 | ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ | 299 | /* |
296 | (unsigned long)(n),sizeof(*(ptr)))) | 300 | * Building a kernel capable running on 80386. It may be necessary to |
301 | * simulate the cmpxchg on the 80386 CPU. For that purpose we define | ||
302 | * a function for each of the sizes we support. | ||
303 | */ | ||
297 | 304 | ||
305 | extern unsigned long cmpxchg_386_u8(volatile void *, u8, u8); | ||
306 | extern unsigned long cmpxchg_386_u16(volatile void *, u16, u16); | ||
307 | extern unsigned long cmpxchg_386_u32(volatile void *, u32, u32); | ||
308 | |||
309 | static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old, | ||
310 | unsigned long new, int size) | ||
311 | { | ||
312 | switch (size) { | ||
313 | case 1: | ||
314 | return cmpxchg_386_u8(ptr, old, new); | ||
315 | case 2: | ||
316 | return cmpxchg_386_u16(ptr, old, new); | ||
317 | case 4: | ||
318 | return cmpxchg_386_u32(ptr, old, new); | ||
319 | } | ||
320 | return old; | ||
321 | } | ||
322 | |||
323 | #define cmpxchg(ptr,o,n) \ | ||
324 | ({ \ | ||
325 | __typeof__(*(ptr)) __ret; \ | ||
326 | if (likely(boot_cpu_data.x86 > 3)) \ | ||
327 | __ret = __cmpxchg((ptr), (unsigned long)(o), \ | ||
328 | (unsigned long)(n), sizeof(*(ptr))); \ | ||
329 | else \ | ||
330 | __ret = cmpxchg_386((ptr), (unsigned long)(o), \ | ||
331 | (unsigned long)(n), sizeof(*(ptr))); \ | ||
332 | __ret; \ | ||
333 | }) | ||
298 | #endif | 334 | #endif |
299 | 335 | ||
300 | #ifdef CONFIG_X86_CMPXCHG64 | 336 | #ifdef CONFIG_X86_CMPXCHG64 |
diff --git a/include/asm-ia64/atomic.h b/include/asm-ia64/atomic.h index 874a6f890e75..2fbebf85c31d 100644 --- a/include/asm-ia64/atomic.h +++ b/include/asm-ia64/atomic.h | |||
@@ -88,6 +88,18 @@ ia64_atomic64_sub (__s64 i, atomic64_t *v) | |||
88 | return new; | 88 | return new; |
89 | } | 89 | } |
90 | 90 | ||
91 | #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) | ||
92 | |||
93 | #define atomic_add_unless(v, a, u) \ | ||
94 | ({ \ | ||
95 | int c, old; \ | ||
96 | c = atomic_read(v); \ | ||
97 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
98 | c = old; \ | ||
99 | c != (u); \ | ||
100 | }) | ||
101 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
102 | |||
91 | #define atomic_add_return(i,v) \ | 103 | #define atomic_add_return(i,v) \ |
92 | ({ \ | 104 | ({ \ |
93 | int __ia64_aar_i = (i); \ | 105 | int __ia64_aar_i = (i); \ |
diff --git a/include/asm-m68k/atomic.h b/include/asm-m68k/atomic.h index 38f3043e7fe1..e3c962eeabf3 100644 --- a/include/asm-m68k/atomic.h +++ b/include/asm-m68k/atomic.h | |||
@@ -139,6 +139,18 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *v) | |||
139 | __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask)); | 139 | __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask)); |
140 | } | 140 | } |
141 | 141 | ||
142 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
143 | |||
144 | #define atomic_add_unless(v, a, u) \ | ||
145 | ({ \ | ||
146 | int c, old; \ | ||
147 | c = atomic_read(v); \ | ||
148 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
149 | c = old; \ | ||
150 | c != (u); \ | ||
151 | }) | ||
152 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
153 | |||
142 | /* Atomic operations are already serializing */ | 154 | /* Atomic operations are already serializing */ |
143 | #define smp_mb__before_atomic_dec() barrier() | 155 | #define smp_mb__before_atomic_dec() barrier() |
144 | #define smp_mb__after_atomic_dec() barrier() | 156 | #define smp_mb__after_atomic_dec() barrier() |
diff --git a/include/asm-m68k/processor.h b/include/asm-m68k/processor.h index df1575db32af..7982285e84ed 100644 --- a/include/asm-m68k/processor.h +++ b/include/asm-m68k/processor.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #define current_text_addr() ({ __label__ _l; _l: &&_l;}) | 14 | #define current_text_addr() ({ __label__ _l; _l: &&_l;}) |
15 | 15 | ||
16 | #include <linux/config.h> | 16 | #include <linux/config.h> |
17 | #include <linux/thread_info.h> | ||
17 | #include <asm/segment.h> | 18 | #include <asm/segment.h> |
18 | #include <asm/fpu.h> | 19 | #include <asm/fpu.h> |
19 | #include <asm/ptrace.h> | 20 | #include <asm/ptrace.h> |
@@ -55,17 +56,6 @@ static inline void wrusp(unsigned long usp) | |||
55 | #endif | 56 | #endif |
56 | #define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) | 57 | #define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) |
57 | 58 | ||
58 | struct task_work { | ||
59 | unsigned char sigpending; | ||
60 | unsigned char notify_resume; /* request for notification on | ||
61 | userspace execution resumption */ | ||
62 | char need_resched; | ||
63 | unsigned char delayed_trace; /* single step a syscall */ | ||
64 | unsigned char syscall_trace; /* count of syscall interceptors */ | ||
65 | unsigned char memdie; /* task was selected to be killed */ | ||
66 | unsigned char pad[2]; | ||
67 | }; | ||
68 | |||
69 | struct thread_struct { | 59 | struct thread_struct { |
70 | unsigned long ksp; /* kernel stack pointer */ | 60 | unsigned long ksp; /* kernel stack pointer */ |
71 | unsigned long usp; /* user stack pointer */ | 61 | unsigned long usp; /* user stack pointer */ |
@@ -78,7 +68,7 @@ struct thread_struct { | |||
78 | unsigned long fp[8*3]; | 68 | unsigned long fp[8*3]; |
79 | unsigned long fpcntl[3]; /* fp control regs */ | 69 | unsigned long fpcntl[3]; /* fp control regs */ |
80 | unsigned char fpstate[FPSTATESIZE]; /* floating point state */ | 70 | unsigned char fpstate[FPSTATESIZE]; /* floating point state */ |
81 | struct task_work work; | 71 | struct thread_info info; |
82 | }; | 72 | }; |
83 | 73 | ||
84 | #define INIT_THREAD { \ | 74 | #define INIT_THREAD { \ |
diff --git a/include/asm-m68k/thread_info.h b/include/asm-m68k/thread_info.h index 2aed24f6fd2e..9532ca3c45cb 100644 --- a/include/asm-m68k/thread_info.h +++ b/include/asm-m68k/thread_info.h | |||
@@ -2,17 +2,15 @@ | |||
2 | #define _ASM_M68K_THREAD_INFO_H | 2 | #define _ASM_M68K_THREAD_INFO_H |
3 | 3 | ||
4 | #include <asm/types.h> | 4 | #include <asm/types.h> |
5 | #include <asm/processor.h> | ||
6 | #include <asm/page.h> | 5 | #include <asm/page.h> |
7 | 6 | ||
8 | struct thread_info { | 7 | struct thread_info { |
9 | struct task_struct *task; /* main task structure */ | 8 | struct task_struct *task; /* main task structure */ |
9 | unsigned long flags; | ||
10 | struct exec_domain *exec_domain; /* execution domain */ | 10 | struct exec_domain *exec_domain; /* execution domain */ |
11 | int preempt_count; /* 0 => preemptable, <0 => BUG */ | 11 | int preempt_count; /* 0 => preemptable, <0 => BUG */ |
12 | __u32 cpu; /* should always be 0 on m68k */ | 12 | __u32 cpu; /* should always be 0 on m68k */ |
13 | struct restart_block restart_block; | 13 | struct restart_block restart_block; |
14 | |||
15 | __u8 supervisor_stack[0]; | ||
16 | }; | 14 | }; |
17 | 15 | ||
18 | #define PREEMPT_ACTIVE 0x4000000 | 16 | #define PREEMPT_ACTIVE 0x4000000 |
@@ -35,84 +33,29 @@ struct thread_info { | |||
35 | #define free_thread_info(ti) free_pages((unsigned long)(ti),1) | 33 | #define free_thread_info(ti) free_pages((unsigned long)(ti),1) |
36 | #endif /* PAGE_SHIFT == 13 */ | 34 | #endif /* PAGE_SHIFT == 13 */ |
37 | 35 | ||
38 | //#define init_thread_info (init_task.thread.info) | 36 | #define init_thread_info (init_task.thread.info) |
39 | #define init_stack (init_thread_union.stack) | 37 | #define init_stack (init_thread_union.stack) |
40 | 38 | ||
41 | #define current_thread_info() (current->thread_info) | 39 | #define task_thread_info(tsk) (&(tsk)->thread.info) |
42 | 40 | #define current_thread_info() task_thread_info(current) | |
43 | 41 | ||
44 | #define __HAVE_THREAD_FUNCTIONS | 42 | #define __HAVE_THREAD_FUNCTIONS |
45 | 43 | ||
46 | #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ | 44 | #define setup_thread_stack(p, org) ({ \ |
47 | #define TIF_DELAYED_TRACE 1 /* single step a syscall */ | 45 | *(struct task_struct **)(p)->thread_info = (p); \ |
48 | #define TIF_NOTIFY_RESUME 2 /* resumption notification requested */ | 46 | task_thread_info(p)->task = (p); \ |
49 | #define TIF_SIGPENDING 3 /* signal pending */ | ||
50 | #define TIF_NEED_RESCHED 4 /* rescheduling necessary */ | ||
51 | #define TIF_MEMDIE 5 | ||
52 | |||
53 | extern int thread_flag_fixme(void); | ||
54 | |||
55 | /* | ||
56 | * flag set/clear/test wrappers | ||
57 | * - pass TIF_xxxx constants to these functions | ||
58 | */ | ||
59 | |||
60 | #define __set_tsk_thread_flag(tsk, flag, val) ({ \ | ||
61 | switch (flag) { \ | ||
62 | case TIF_SIGPENDING: \ | ||
63 | tsk->thread.work.sigpending = val; \ | ||
64 | break; \ | ||
65 | case TIF_NEED_RESCHED: \ | ||
66 | tsk->thread.work.need_resched = val; \ | ||
67 | break; \ | ||
68 | case TIF_SYSCALL_TRACE: \ | ||
69 | tsk->thread.work.syscall_trace = val; \ | ||
70 | break; \ | ||
71 | case TIF_MEMDIE: \ | ||
72 | tsk->thread.work.memdie = val; \ | ||
73 | break; \ | ||
74 | default: \ | ||
75 | thread_flag_fixme(); \ | ||
76 | } \ | ||
77 | }) | 47 | }) |
78 | 48 | ||
79 | #define __get_tsk_thread_flag(tsk, flag) ({ \ | 49 | #define end_of_stack(p) ((unsigned long *)(p)->thread_info + 1) |
80 | int ___res; \ | ||
81 | switch (flag) { \ | ||
82 | case TIF_SIGPENDING: \ | ||
83 | ___res = tsk->thread.work.sigpending; \ | ||
84 | break; \ | ||
85 | case TIF_NEED_RESCHED: \ | ||
86 | ___res = tsk->thread.work.need_resched; \ | ||
87 | break; \ | ||
88 | case TIF_SYSCALL_TRACE: \ | ||
89 | ___res = tsk->thread.work.syscall_trace;\ | ||
90 | break; \ | ||
91 | case TIF_MEMDIE: \ | ||
92 | ___res = tsk->thread.work.memdie;\ | ||
93 | break; \ | ||
94 | default: \ | ||
95 | ___res = thread_flag_fixme(); \ | ||
96 | } \ | ||
97 | ___res; \ | ||
98 | }) | ||
99 | |||
100 | #define __get_set_tsk_thread_flag(tsk, flag, val) ({ \ | ||
101 | int __res = __get_tsk_thread_flag(tsk, flag); \ | ||
102 | __set_tsk_thread_flag(tsk, flag, val); \ | ||
103 | __res; \ | ||
104 | }) | ||
105 | 50 | ||
106 | #define set_tsk_thread_flag(tsk, flag) __set_tsk_thread_flag(tsk, flag, ~0) | 51 | /* entry.S relies on these definitions! |
107 | #define clear_tsk_thread_flag(tsk, flag) __set_tsk_thread_flag(tsk, flag, 0) | 52 | * bits 0-7 are tested at every exception exit |
108 | #define test_and_set_tsk_thread_flag(tsk, flag) __get_set_tsk_thread_flag(tsk, flag, ~0) | 53 | * bits 8-15 are also tested at syscall exit |
109 | #define test_tsk_thread_flag(tsk, flag) __get_tsk_thread_flag(tsk, flag) | 54 | */ |
110 | 55 | #define TIF_SIGPENDING 6 /* signal pending */ | |
111 | #define set_thread_flag(flag) set_tsk_thread_flag(current, flag) | 56 | #define TIF_NEED_RESCHED 7 /* rescheduling necessary */ |
112 | #define clear_thread_flag(flag) clear_tsk_thread_flag(current, flag) | 57 | #define TIF_DELAYED_TRACE 14 /* single step a syscall */ |
113 | #define test_thread_flag(flag) test_tsk_thread_flag(current, flag) | 58 | #define TIF_SYSCALL_TRACE 15 /* syscall trace active */ |
114 | 59 | #define TIF_MEMDIE 16 | |
115 | #define set_need_resched() set_thread_flag(TIF_NEED_RESCHED) | ||
116 | #define clear_need_resched() clear_thread_flag(TIF_NEED_RESCHED) | ||
117 | 60 | ||
118 | #endif /* _ASM_M68K_THREAD_INFO_H */ | 61 | #endif /* _ASM_M68K_THREAD_INFO_H */ |
diff --git a/include/asm-m68knommu/atomic.h b/include/asm-m68knommu/atomic.h index a83631ed8c8f..3c1cc153c415 100644 --- a/include/asm-m68knommu/atomic.h +++ b/include/asm-m68knommu/atomic.h | |||
@@ -128,6 +128,18 @@ static inline int atomic_sub_return(int i, atomic_t * v) | |||
128 | return temp; | 128 | return temp; |
129 | } | 129 | } |
130 | 130 | ||
131 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
132 | |||
133 | #define atomic_add_unless(v, a, u) \ | ||
134 | ({ \ | ||
135 | int c, old; \ | ||
136 | c = atomic_read(v); \ | ||
137 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
138 | c = old; \ | ||
139 | c != (u); \ | ||
140 | }) | ||
141 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
142 | |||
131 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) | 143 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) |
132 | #define atomic_inc_return(v) atomic_add_return(1,(v)) | 144 | #define atomic_inc_return(v) atomic_add_return(1,(v)) |
133 | 145 | ||
diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h index 6202eb8a14b7..2c87b41e69ba 100644 --- a/include/asm-mips/atomic.h +++ b/include/asm-mips/atomic.h | |||
@@ -287,6 +287,27 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) | |||
287 | return result; | 287 | return result; |
288 | } | 288 | } |
289 | 289 | ||
290 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
291 | |||
292 | /** | ||
293 | * atomic_add_unless - add unless the number is a given value | ||
294 | * @v: pointer of type atomic_t | ||
295 | * @a: the amount to add to v... | ||
296 | * @u: ...unless v is equal to u. | ||
297 | * | ||
298 | * Atomically adds @a to @v, so long as it was not @u. | ||
299 | * Returns non-zero if @v was not @u, and zero otherwise. | ||
300 | */ | ||
301 | #define atomic_add_unless(v, a, u) \ | ||
302 | ({ \ | ||
303 | int c, old; \ | ||
304 | c = atomic_read(v); \ | ||
305 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
306 | c = old; \ | ||
307 | c != (u); \ | ||
308 | }) | ||
309 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
310 | |||
290 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) | 311 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) |
291 | #define atomic_inc_return(v) atomic_add_return(1,(v)) | 312 | #define atomic_inc_return(v) atomic_add_return(1,(v)) |
292 | 313 | ||
diff --git a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h index 048a2c7fd0c0..983e9a2b6042 100644 --- a/include/asm-parisc/atomic.h +++ b/include/asm-parisc/atomic.h | |||
@@ -164,6 +164,26 @@ static __inline__ int atomic_read(const atomic_t *v) | |||
164 | } | 164 | } |
165 | 165 | ||
166 | /* exported interface */ | 166 | /* exported interface */ |
167 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
168 | |||
169 | /** | ||
170 | * atomic_add_unless - add unless the number is a given value | ||
171 | * @v: pointer of type atomic_t | ||
172 | * @a: the amount to add to v... | ||
173 | * @u: ...unless v is equal to u. | ||
174 | * | ||
175 | * Atomically adds @a to @v, so long as it was not @u. | ||
176 | * Returns non-zero if @v was not @u, and zero otherwise. | ||
177 | */ | ||
178 | #define atomic_add_unless(v, a, u) \ | ||
179 | ({ \ | ||
180 | int c, old; \ | ||
181 | c = atomic_read(v); \ | ||
182 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
183 | c = old; \ | ||
184 | c != (u); \ | ||
185 | }) | ||
186 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
167 | 187 | ||
168 | #define atomic_add(i,v) ((void)(__atomic_add_return( ((int)i),(v)))) | 188 | #define atomic_add(i,v) ((void)(__atomic_add_return( ((int)i),(v)))) |
169 | #define atomic_sub(i,v) ((void)(__atomic_add_return(-((int)i),(v)))) | 189 | #define atomic_sub(i,v) ((void)(__atomic_add_return(-((int)i),(v)))) |
diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h index 9c0b372a46e1..ec4b14468959 100644 --- a/include/asm-powerpc/atomic.h +++ b/include/asm-powerpc/atomic.h | |||
@@ -164,6 +164,33 @@ static __inline__ int atomic_dec_return(atomic_t *v) | |||
164 | return t; | 164 | return t; |
165 | } | 165 | } |
166 | 166 | ||
167 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
168 | |||
169 | /** | ||
170 | * atomic_add_unless - add unless the number is a given value | ||
171 | * @v: pointer of type atomic_t | ||
172 | * @a: the amount to add to v... | ||
173 | * @u: ...unless v is equal to u. | ||
174 | * | ||
175 | * Atomically adds @a to @v, so long as it was not @u. | ||
176 | * Returns non-zero if @v was not @u, and zero otherwise. | ||
177 | */ | ||
178 | #define atomic_add_unless(v, a, u) \ | ||
179 | ({ \ | ||
180 | int c, old; \ | ||
181 | c = atomic_read(v); \ | ||
182 | for (;;) { \ | ||
183 | if (unlikely(c == (u))) \ | ||
184 | break; \ | ||
185 | old = atomic_cmpxchg((v), c, c + (a)); \ | ||
186 | if (likely(old == c)) \ | ||
187 | break; \ | ||
188 | c = old; \ | ||
189 | } \ | ||
190 | c != (u); \ | ||
191 | }) | ||
192 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
193 | |||
167 | #define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) | 194 | #define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) |
168 | #define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) | 195 | #define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) |
169 | 196 | ||
diff --git a/include/asm-ppc/immap_85xx.h b/include/asm-ppc/immap_85xx.h index 50fb5e47094a..9383d0c13ff8 100644 --- a/include/asm-ppc/immap_85xx.h +++ b/include/asm-ppc/immap_85xx.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx Internal Memory Map | 4 | * MPC85xx Internal Memory Map |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor, Inc | 8 | * Copyright 2004 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/include/asm-ppc/ipic.h b/include/asm-ppc/ipic.h index 9092b920997a..0fe396a2b666 100644 --- a/include/asm-ppc/ipic.h +++ b/include/asm-ppc/ipic.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * IPIC external definitions and structure. | 4 | * IPIC external definitions and structure. |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor, Inc | 8 | * Copyright 2005 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h index ce212201db2a..7cdf60fa69b6 100644 --- a/include/asm-ppc/mpc83xx.h +++ b/include/asm-ppc/mpc83xx.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83xx definitions | 4 | * MPC83xx definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor, Inc | 8 | * Copyright 2005 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h index d98db980cd49..9d14baea3d71 100644 --- a/include/asm-ppc/mpc85xx.h +++ b/include/asm-ppc/mpc85xx.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx definitions | 4 | * MPC85xx definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor, Inc | 8 | * Copyright 2004 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h index bba5305c29ed..83d8c77c124d 100644 --- a/include/asm-ppc/ppc_sys.h +++ b/include/asm-ppc/ppc_sys.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PPC system definitions and library functions | 4 | * PPC system definitions and library functions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor, Inc | 8 | * Copyright 2005 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h index 9d86ba6f12d0..b3bd4f679f72 100644 --- a/include/asm-s390/atomic.h +++ b/include/asm-s390/atomic.h | |||
@@ -198,6 +198,18 @@ atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t *v) | |||
198 | return retval; | 198 | return retval; |
199 | } | 199 | } |
200 | 200 | ||
201 | #define atomic_cmpxchg(v, o, n) (atomic_compare_and_swap((o), (n), &((v)->counter))) | ||
202 | |||
203 | #define atomic_add_unless(v, a, u) \ | ||
204 | ({ \ | ||
205 | int c, old; \ | ||
206 | c = atomic_read(v); \ | ||
207 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
208 | c = old; \ | ||
209 | c != (u); \ | ||
210 | }) | ||
211 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
212 | |||
201 | #define smp_mb__before_atomic_dec() smp_mb() | 213 | #define smp_mb__before_atomic_dec() smp_mb() |
202 | #define smp_mb__after_atomic_dec() smp_mb() | 214 | #define smp_mb__after_atomic_dec() smp_mb() |
203 | #define smp_mb__before_atomic_inc() smp_mb() | 215 | #define smp_mb__before_atomic_inc() smp_mb() |
diff --git a/include/asm-sh/atomic.h b/include/asm-sh/atomic.h index 3c4f805da1ac..aabfd334462c 100644 --- a/include/asm-sh/atomic.h +++ b/include/asm-sh/atomic.h | |||
@@ -87,6 +87,35 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v) | |||
87 | #define atomic_inc(v) atomic_add(1,(v)) | 87 | #define atomic_inc(v) atomic_add(1,(v)) |
88 | #define atomic_dec(v) atomic_sub(1,(v)) | 88 | #define atomic_dec(v) atomic_sub(1,(v)) |
89 | 89 | ||
90 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
91 | { | ||
92 | int ret; | ||
93 | unsigned long flags; | ||
94 | |||
95 | local_irq_save(flags); | ||
96 | ret = v->counter; | ||
97 | if (likely(ret == old)) | ||
98 | v->counter = new; | ||
99 | local_irq_restore(flags); | ||
100 | |||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
105 | { | ||
106 | int ret; | ||
107 | unsigned long flags; | ||
108 | |||
109 | local_irq_save(flags); | ||
110 | ret = v->counter; | ||
111 | if (ret != u) | ||
112 | v->counter += a; | ||
113 | local_irq_restore(flags); | ||
114 | |||
115 | return ret != u; | ||
116 | } | ||
117 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
118 | |||
90 | static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v) | 119 | static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v) |
91 | { | 120 | { |
92 | unsigned long flags; | 121 | unsigned long flags; |
diff --git a/include/asm-sh64/atomic.h b/include/asm-sh64/atomic.h index 8c3872d3e65f..927a2bc27b30 100644 --- a/include/asm-sh64/atomic.h +++ b/include/asm-sh64/atomic.h | |||
@@ -99,6 +99,35 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v) | |||
99 | #define atomic_inc(v) atomic_add(1,(v)) | 99 | #define atomic_inc(v) atomic_add(1,(v)) |
100 | #define atomic_dec(v) atomic_sub(1,(v)) | 100 | #define atomic_dec(v) atomic_sub(1,(v)) |
101 | 101 | ||
102 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
103 | { | ||
104 | int ret; | ||
105 | unsigned long flags; | ||
106 | |||
107 | local_irq_save(flags); | ||
108 | ret = v->counter; | ||
109 | if (likely(ret == old)) | ||
110 | v->counter = new; | ||
111 | local_irq_restore(flags); | ||
112 | |||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
117 | { | ||
118 | int ret; | ||
119 | unsigned long flags; | ||
120 | |||
121 | local_irq_save(flags); | ||
122 | ret = v->counter; | ||
123 | if (ret != u) | ||
124 | v->counter += a; | ||
125 | local_irq_restore(flags); | ||
126 | |||
127 | return ret != u; | ||
128 | } | ||
129 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
130 | |||
102 | static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v) | 131 | static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v) |
103 | { | 132 | { |
104 | unsigned long flags; | 133 | unsigned long flags; |
diff --git a/include/asm-sparc/atomic.h b/include/asm-sparc/atomic.h index 37f6ab601c3d..62bec7ad271c 100644 --- a/include/asm-sparc/atomic.h +++ b/include/asm-sparc/atomic.h | |||
@@ -19,6 +19,8 @@ typedef struct { volatile int counter; } atomic_t; | |||
19 | #define ATOMIC_INIT(i) { (i) } | 19 | #define ATOMIC_INIT(i) { (i) } |
20 | 20 | ||
21 | extern int __atomic_add_return(int, atomic_t *); | 21 | extern int __atomic_add_return(int, atomic_t *); |
22 | extern int atomic_cmpxchg(atomic_t *, int, int); | ||
23 | extern int atomic_add_unless(atomic_t *, int, int); | ||
22 | extern void atomic_set(atomic_t *, int); | 24 | extern void atomic_set(atomic_t *, int); |
23 | 25 | ||
24 | #define atomic_read(v) ((v)->counter) | 26 | #define atomic_read(v) ((v)->counter) |
@@ -48,6 +50,8 @@ extern void atomic_set(atomic_t *, int); | |||
48 | #define atomic_dec_and_test(v) (atomic_dec_return(v) == 0) | 50 | #define atomic_dec_and_test(v) (atomic_dec_return(v) == 0) |
49 | #define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) | 51 | #define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) |
50 | 52 | ||
53 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
54 | |||
51 | /* This is the old 24-bit implementation. It's still used internally | 55 | /* This is the old 24-bit implementation. It's still used internally |
52 | * by some sparc-specific code, notably the semaphore implementation. | 56 | * by some sparc-specific code, notably the semaphore implementation. |
53 | */ | 57 | */ |
diff --git a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h index e175afcf2cde..8198c3d0d007 100644 --- a/include/asm-sparc64/atomic.h +++ b/include/asm-sparc64/atomic.h | |||
@@ -70,6 +70,18 @@ extern int atomic64_sub_ret(int, atomic64_t *); | |||
70 | #define atomic_add_negative(i, v) (atomic_add_ret(i, v) < 0) | 70 | #define atomic_add_negative(i, v) (atomic_add_ret(i, v) < 0) |
71 | #define atomic64_add_negative(i, v) (atomic64_add_ret(i, v) < 0) | 71 | #define atomic64_add_negative(i, v) (atomic64_add_ret(i, v) < 0) |
72 | 72 | ||
73 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
74 | |||
75 | #define atomic_add_unless(v, a, u) \ | ||
76 | ({ \ | ||
77 | int c, old; \ | ||
78 | c = atomic_read(v); \ | ||
79 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
80 | c = old; \ | ||
81 | c != (u); \ | ||
82 | }) | ||
83 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
84 | |||
73 | /* Atomic operations are already serializing */ | 85 | /* Atomic operations are already serializing */ |
74 | #ifdef CONFIG_SMP | 86 | #ifdef CONFIG_SMP |
75 | #define smp_mb__before_atomic_dec() membar_storeload_loadload(); | 87 | #define smp_mb__before_atomic_dec() membar_storeload_loadload(); |
diff --git a/include/asm-v850/atomic.h b/include/asm-v850/atomic.h index 395268a8c0de..bede3172ce7f 100644 --- a/include/asm-v850/atomic.h +++ b/include/asm-v850/atomic.h | |||
@@ -90,6 +90,36 @@ static __inline__ void atomic_clear_mask (unsigned long mask, unsigned long *add | |||
90 | #define atomic_dec_and_test(v) (atomic_sub_return (1, (v)) == 0) | 90 | #define atomic_dec_and_test(v) (atomic_sub_return (1, (v)) == 0) |
91 | #define atomic_add_negative(i,v) (atomic_add_return ((i), (v)) < 0) | 91 | #define atomic_add_negative(i,v) (atomic_add_return ((i), (v)) < 0) |
92 | 92 | ||
93 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
94 | { | ||
95 | int ret; | ||
96 | unsigned long flags; | ||
97 | |||
98 | local_irq_save(flags); | ||
99 | ret = v->counter; | ||
100 | if (likely(ret == old)) | ||
101 | v->counter = new; | ||
102 | local_irq_restore(flags); | ||
103 | |||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
108 | { | ||
109 | int ret; | ||
110 | unsigned long flags; | ||
111 | |||
112 | local_irq_save(flags); | ||
113 | ret = v->counter; | ||
114 | if (ret != u) | ||
115 | v->counter += a; | ||
116 | local_irq_restore(flags); | ||
117 | |||
118 | return ret != u; | ||
119 | } | ||
120 | |||
121 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
122 | |||
93 | /* Atomic operations are already serializing on ARM */ | 123 | /* Atomic operations are already serializing on ARM */ |
94 | #define smp_mb__before_atomic_dec() barrier() | 124 | #define smp_mb__before_atomic_dec() barrier() |
95 | #define smp_mb__after_atomic_dec() barrier() | 125 | #define smp_mb__after_atomic_dec() barrier() |
diff --git a/include/asm-x86_64/atomic.h b/include/asm-x86_64/atomic.h index fc4c5956e1ea..0866ef67f198 100644 --- a/include/asm-x86_64/atomic.h +++ b/include/asm-x86_64/atomic.h | |||
@@ -360,6 +360,27 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v) | |||
360 | return atomic_add_return(-i,v); | 360 | return atomic_add_return(-i,v); |
361 | } | 361 | } |
362 | 362 | ||
363 | #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) | ||
364 | |||
365 | /** | ||
366 | * atomic_add_unless - add unless the number is a given value | ||
367 | * @v: pointer of type atomic_t | ||
368 | * @a: the amount to add to v... | ||
369 | * @u: ...unless v is equal to u. | ||
370 | * | ||
371 | * Atomically adds @a to @v, so long as it was not @u. | ||
372 | * Returns non-zero if @v was not @u, and zero otherwise. | ||
373 | */ | ||
374 | #define atomic_add_unless(v, a, u) \ | ||
375 | ({ \ | ||
376 | int c, old; \ | ||
377 | c = atomic_read(v); \ | ||
378 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
379 | c = old; \ | ||
380 | c != (u); \ | ||
381 | }) | ||
382 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
383 | |||
363 | #define atomic_inc_return(v) (atomic_add_return(1,v)) | 384 | #define atomic_inc_return(v) (atomic_add_return(1,v)) |
364 | #define atomic_dec_return(v) (atomic_sub_return(1,v)) | 385 | #define atomic_dec_return(v) (atomic_sub_return(1,v)) |
365 | 386 | ||
diff --git a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h index 68ac3c62fe3d..b837820c9073 100644 --- a/include/asm-x86_64/desc.h +++ b/include/asm-x86_64/desc.h | |||
@@ -129,9 +129,16 @@ static inline void set_tssldt_descriptor(void *ptr, unsigned long tss, unsigned | |||
129 | 129 | ||
130 | static inline void set_tss_desc(unsigned cpu, void *addr) | 130 | static inline void set_tss_desc(unsigned cpu, void *addr) |
131 | { | 131 | { |
132 | set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_TSS], (unsigned long)addr, | 132 | /* |
133 | DESC_TSS, | 133 | * sizeof(unsigned long) coming from an extra "long" at the end |
134 | sizeof(struct tss_struct) - 1); | 134 | * of the iobitmap. See tss_struct definition in processor.h |
135 | * | ||
136 | * -1? seg base+limit should be pointing to the address of the | ||
137 | * last valid byte | ||
138 | */ | ||
139 | set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_TSS], | ||
140 | (unsigned long)addr, DESC_TSS, | ||
141 | IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1); | ||
135 | } | 142 | } |
136 | 143 | ||
137 | static inline void set_ldt_desc(unsigned cpu, void *addr, int size) | 144 | static inline void set_ldt_desc(unsigned cpu, void *addr, int size) |
diff --git a/include/asm-xtensa/atomic.h b/include/asm-xtensa/atomic.h index 12b5732dc6e5..3670cc7695da 100644 --- a/include/asm-xtensa/atomic.h +++ b/include/asm-xtensa/atomic.h | |||
@@ -223,6 +223,26 @@ static inline int atomic_sub_return(int i, atomic_t * v) | |||
223 | */ | 223 | */ |
224 | #define atomic_add_negative(i,v) (atomic_add_return((i),(v)) < 0) | 224 | #define atomic_add_negative(i,v) (atomic_add_return((i),(v)) < 0) |
225 | 225 | ||
226 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
227 | |||
228 | /** | ||
229 | * atomic_add_unless - add unless the number is a given value | ||
230 | * @v: pointer of type atomic_t | ||
231 | * @a: the amount to add to v... | ||
232 | * @u: ...unless v is equal to u. | ||
233 | * | ||
234 | * Atomically adds @a to @v, so long as it was not @u. | ||
235 | * Returns non-zero if @v was not @u, and zero otherwise. | ||
236 | */ | ||
237 | #define atomic_add_unless(v, a, u) \ | ||
238 | ({ \ | ||
239 | int c, old; \ | ||
240 | c = atomic_read(v); \ | ||
241 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
242 | c = old; \ | ||
243 | c != (u); \ | ||
244 | }) | ||
245 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
226 | 246 | ||
227 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) | 247 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) |
228 | { | 248 | { |
diff --git a/include/linux/acct.h b/include/linux/acct.h index 93c5b3cdf951..9a66401073fc 100644 --- a/include/linux/acct.h +++ b/include/linux/acct.h | |||
@@ -16,6 +16,8 @@ | |||
16 | #define _LINUX_ACCT_H | 16 | #define _LINUX_ACCT_H |
17 | 17 | ||
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/jiffies.h> | ||
20 | |||
19 | #include <asm/param.h> | 21 | #include <asm/param.h> |
20 | #include <asm/byteorder.h> | 22 | #include <asm/byteorder.h> |
21 | 23 | ||
diff --git a/include/linux/aio.h b/include/linux/aio.h index 403d71dcb7c8..49fd37629ee4 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h | |||
@@ -124,7 +124,7 @@ struct kiocb { | |||
124 | (x)->ki_users = 1; \ | 124 | (x)->ki_users = 1; \ |
125 | (x)->ki_key = KIOCB_SYNC_KEY; \ | 125 | (x)->ki_key = KIOCB_SYNC_KEY; \ |
126 | (x)->ki_filp = (filp); \ | 126 | (x)->ki_filp = (filp); \ |
127 | (x)->ki_ctx = &tsk->active_mm->default_kioctx; \ | 127 | (x)->ki_ctx = NULL; \ |
128 | (x)->ki_cancel = NULL; \ | 128 | (x)->ki_cancel = NULL; \ |
129 | (x)->ki_dtor = NULL; \ | 129 | (x)->ki_dtor = NULL; \ |
130 | (x)->ki_obj.tsk = tsk; \ | 130 | (x)->ki_obj.tsk = tsk; \ |
@@ -210,8 +210,15 @@ struct kioctx *lookup_ioctx(unsigned long ctx_id); | |||
210 | int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, | 210 | int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, |
211 | struct iocb *iocb)); | 211 | struct iocb *iocb)); |
212 | 212 | ||
213 | #define get_ioctx(kioctx) do { if (unlikely(atomic_read(&(kioctx)->users) <= 0)) BUG(); atomic_inc(&(kioctx)->users); } while (0) | 213 | #define get_ioctx(kioctx) do { \ |
214 | #define put_ioctx(kioctx) do { if (unlikely(atomic_dec_and_test(&(kioctx)->users))) __put_ioctx(kioctx); else if (unlikely(atomic_read(&(kioctx)->users) < 0)) BUG(); } while (0) | 214 | BUG_ON(unlikely(atomic_read(&(kioctx)->users) <= 0)); \ |
215 | atomic_inc(&(kioctx)->users); \ | ||
216 | } while (0) | ||
217 | #define put_ioctx(kioctx) do { \ | ||
218 | BUG_ON(unlikely(atomic_read(&(kioctx)->users) <= 0)); \ | ||
219 | if (unlikely(atomic_dec_and_test(&(kioctx)->users))) \ | ||
220 | __put_ioctx(kioctx); \ | ||
221 | } while (0) | ||
215 | 222 | ||
216 | #define in_aio() !is_sync_wait(current->io_wait) | 223 | #define in_aio() !is_sync_wait(current->io_wait) |
217 | /* may be used for debugging */ | 224 | /* may be used for debugging */ |
diff --git a/include/linux/cm4000_cs.h b/include/linux/cm4000_cs.h new file mode 100644 index 000000000000..605ebe24bb2e --- /dev/null +++ b/include/linux/cm4000_cs.h | |||
@@ -0,0 +1,66 @@ | |||
1 | #ifndef _CM4000_H_ | ||
2 | #define _CM4000_H_ | ||
3 | |||
4 | #define MAX_ATR 33 | ||
5 | |||
6 | #define CM4000_MAX_DEV 4 | ||
7 | |||
8 | /* those two structures are passed via ioctl() from/to userspace. They are | ||
9 | * used by existing userspace programs, so I kepth the awkward "bIFSD" naming | ||
10 | * not to break compilation of userspace apps. -HW */ | ||
11 | |||
12 | typedef struct atreq { | ||
13 | int32_t atr_len; | ||
14 | unsigned char atr[64]; | ||
15 | int32_t power_act; | ||
16 | unsigned char bIFSD; | ||
17 | unsigned char bIFSC; | ||
18 | } atreq_t; | ||
19 | |||
20 | |||
21 | /* what is particularly stupid in the original driver is the arch-dependant | ||
22 | * member sizes. This leads to CONFIG_COMPAT breakage, since 32bit userspace | ||
23 | * will lay out the structure members differently than the 64bit kernel. | ||
24 | * | ||
25 | * I've changed "ptsreq.protocol" from "unsigned long" to "u_int32_t". | ||
26 | * On 32bit this will make no difference. With 64bit kernels, it will make | ||
27 | * 32bit apps work, too. | ||
28 | */ | ||
29 | |||
30 | typedef struct ptsreq { | ||
31 | u_int32_t protocol; /*T=0: 2^0, T=1: 2^1*/ | ||
32 | unsigned char flags; | ||
33 | unsigned char pts1; | ||
34 | unsigned char pts2; | ||
35 | unsigned char pts3; | ||
36 | } ptsreq_t; | ||
37 | |||
38 | #define CM_IOC_MAGIC 'c' | ||
39 | #define CM_IOC_MAXNR 255 | ||
40 | |||
41 | #define CM_IOCGSTATUS _IOR (CM_IOC_MAGIC, 0, unsigned char *) | ||
42 | #define CM_IOCGATR _IOWR(CM_IOC_MAGIC, 1, atreq_t *) | ||
43 | #define CM_IOCSPTS _IOW (CM_IOC_MAGIC, 2, ptsreq_t *) | ||
44 | #define CM_IOCSRDR _IO (CM_IOC_MAGIC, 3) | ||
45 | #define CM_IOCARDOFF _IO (CM_IOC_MAGIC, 4) | ||
46 | |||
47 | #define CM_IOSDBGLVL _IOW(CM_IOC_MAGIC, 250, int*) | ||
48 | |||
49 | /* card and device states */ | ||
50 | #define CM_CARD_INSERTED 0x01 | ||
51 | #define CM_CARD_POWERED 0x02 | ||
52 | #define CM_ATR_PRESENT 0x04 | ||
53 | #define CM_ATR_VALID 0x08 | ||
54 | #define CM_STATE_VALID 0x0f | ||
55 | /* extra info only from CM4000 */ | ||
56 | #define CM_NO_READER 0x10 | ||
57 | #define CM_BAD_CARD 0x20 | ||
58 | |||
59 | |||
60 | #ifdef __KERNEL__ | ||
61 | |||
62 | #define DEVICE_NAME "cmm" | ||
63 | #define MODULE_NAME "cm4000_cs" | ||
64 | |||
65 | #endif /* __KERNEL__ */ | ||
66 | #endif /* _CM4000_H_ */ | ||
diff --git a/include/linux/file.h b/include/linux/file.h index d3b1a15d5f21..418b6101b59a 100644 --- a/include/linux/file.h +++ b/include/linux/file.h | |||
@@ -33,13 +33,13 @@ struct fdtable { | |||
33 | * Open file table structure | 33 | * Open file table structure |
34 | */ | 34 | */ |
35 | struct files_struct { | 35 | struct files_struct { |
36 | atomic_t count; | 36 | atomic_t count; |
37 | spinlock_t file_lock; /* Protects all the below members. Nests inside tsk->alloc_lock */ | ||
38 | struct fdtable *fdt; | 37 | struct fdtable *fdt; |
39 | struct fdtable fdtab; | 38 | struct fdtable fdtab; |
40 | fd_set close_on_exec_init; | 39 | fd_set close_on_exec_init; |
41 | fd_set open_fds_init; | 40 | fd_set open_fds_init; |
42 | struct file * fd_array[NR_OPEN_DEFAULT]; | 41 | struct file * fd_array[NR_OPEN_DEFAULT]; |
42 | spinlock_t file_lock; /* Protects concurrent writers. Nests inside tsk->alloc_lock */ | ||
43 | }; | 43 | }; |
44 | 44 | ||
45 | #define files_fdtable(files) (rcu_dereference((files)->fdt)) | 45 | #define files_fdtable(files) (rcu_dereference((files)->fdt)) |
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index 114d5d59f695..934aa9bda481 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h | |||
@@ -4,7 +4,7 @@ | |||
4 | * Definitions for any platform device related flags or structures for | 4 | * Definitions for any platform device related flags or structures for |
5 | * Freescale processor devices | 5 | * Freescale processor devices |
6 | * | 6 | * |
7 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 7 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
8 | * | 8 | * |
9 | * Copyright 2004 Freescale Semiconductor, Inc | 9 | * Copyright 2004 Freescale Semiconductor, Inc |
10 | * | 10 | * |
diff --git a/include/linux/gfp.h b/include/linux/gfp.h index c3779432a723..23279d8f19b1 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h | |||
@@ -39,8 +39,7 @@ struct vm_area_struct; | |||
39 | #define __GFP_COMP ((__force gfp_t)0x4000u)/* Add compound page metadata */ | 39 | #define __GFP_COMP ((__force gfp_t)0x4000u)/* Add compound page metadata */ |
40 | #define __GFP_ZERO ((__force gfp_t)0x8000u)/* Return zeroed page on success */ | 40 | #define __GFP_ZERO ((__force gfp_t)0x8000u)/* Return zeroed page on success */ |
41 | #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */ | 41 | #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */ |
42 | #define __GFP_NORECLAIM ((__force gfp_t)0x20000u) /* No realy zone reclaim during allocation */ | 42 | #define __GFP_HARDWALL ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */ |
43 | #define __GFP_HARDWALL ((__force gfp_t)0x40000u) /* Enforce hardwall cpuset memory allocs */ | ||
44 | 43 | ||
45 | #define __GFP_BITS_SHIFT 20 /* Room for 20 __GFP_FOO bits */ | 44 | #define __GFP_BITS_SHIFT 20 /* Room for 20 __GFP_FOO bits */ |
46 | #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) | 45 | #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) |
@@ -49,7 +48,7 @@ struct vm_area_struct; | |||
49 | #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \ | 48 | #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \ |
50 | __GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \ | 49 | __GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \ |
51 | __GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \ | 50 | __GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \ |
52 | __GFP_NOMEMALLOC|__GFP_NORECLAIM|__GFP_HARDWALL) | 51 | __GFP_NOMEMALLOC|__GFP_HARDWALL) |
53 | 52 | ||
54 | #define GFP_ATOMIC (__GFP_HIGH) | 53 | #define GFP_ATOMIC (__GFP_HIGH) |
55 | #define GFP_NOIO (__GFP_WAIT) | 54 | #define GFP_NOIO (__GFP_WAIT) |
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index 5912874ca83c..71d2b8a723b9 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h | |||
@@ -90,6 +90,8 @@ extern void synchronize_irq(unsigned int irq); | |||
90 | #define nmi_enter() irq_enter() | 90 | #define nmi_enter() irq_enter() |
91 | #define nmi_exit() sub_preempt_count(HARDIRQ_OFFSET) | 91 | #define nmi_exit() sub_preempt_count(HARDIRQ_OFFSET) |
92 | 92 | ||
93 | struct task_struct; | ||
94 | |||
93 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING | 95 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING |
94 | static inline void account_user_vtime(struct task_struct *tsk) | 96 | static inline void account_user_vtime(struct task_struct *tsk) |
95 | { | 97 | { |
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 0cea162b08c0..1056717ee501 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h | |||
@@ -102,8 +102,8 @@ static inline unsigned long hugetlb_total_pages(void) | |||
102 | #define hugetlb_fault(mm, vma, addr, write) ({ BUG(); 0; }) | 102 | #define hugetlb_fault(mm, vma, addr, write) ({ BUG(); 0; }) |
103 | 103 | ||
104 | #ifndef HPAGE_MASK | 104 | #ifndef HPAGE_MASK |
105 | #define HPAGE_MASK 0 /* Keep the compiler happy */ | 105 | #define HPAGE_MASK PAGE_MASK /* Keep the compiler happy */ |
106 | #define HPAGE_SIZE 0 | 106 | #define HPAGE_SIZE PAGE_SIZE |
107 | #endif | 107 | #endif |
108 | 108 | ||
109 | #endif /* !CONFIG_HUGETLB_PAGE */ | 109 | #endif /* !CONFIG_HUGETLB_PAGE */ |
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 74abaecdb572..1543daaa9c5e 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h | |||
@@ -107,6 +107,7 @@ | |||
107 | #define I2C_DRIVERID_CX25840 71 /* cx2584x video encoder */ | 107 | #define I2C_DRIVERID_CX25840 71 /* cx2584x video encoder */ |
108 | #define I2C_DRIVERID_SAA7127 72 /* saa7124 video encoder */ | 108 | #define I2C_DRIVERID_SAA7127 72 /* saa7124 video encoder */ |
109 | #define I2C_DRIVERID_SAA711X 73 /* saa711x video encoders */ | 109 | #define I2C_DRIVERID_SAA711X 73 /* saa711x video encoders */ |
110 | #define I2C_DRIVERID_AKITAIOEXP 74 /* IO Expander on Sharp SL-C1000 */ | ||
110 | 111 | ||
111 | #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ | 112 | #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ |
112 | #define I2C_DRIVERID_EXP1 0xF1 | 113 | #define I2C_DRIVERID_EXP1 0xF1 |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 68ab5f2ab9cd..dcfd2ecccb5d 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -51,7 +51,6 @@ | |||
51 | .page_table_lock = SPIN_LOCK_UNLOCKED, \ | 51 | .page_table_lock = SPIN_LOCK_UNLOCKED, \ |
52 | .mmlist = LIST_HEAD_INIT(name.mmlist), \ | 52 | .mmlist = LIST_HEAD_INIT(name.mmlist), \ |
53 | .cpu_vm_mask = CPU_MASK_ALL, \ | 53 | .cpu_vm_mask = CPU_MASK_ALL, \ |
54 | .default_kioctx = INIT_KIOCTX(name.default_kioctx, name), \ | ||
55 | } | 54 | } |
56 | 55 | ||
57 | #define INIT_SIGNALS(sig) { \ | 56 | #define INIT_SIGNALS(sig) { \ |
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 0a90205184b0..41f150a3d2dd 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/preempt.h> | 9 | #include <linux/preempt.h> |
10 | #include <linux/cpumask.h> | 10 | #include <linux/cpumask.h> |
11 | #include <linux/hardirq.h> | 11 | #include <linux/hardirq.h> |
12 | #include <linux/sched.h> | ||
12 | #include <asm/atomic.h> | 13 | #include <asm/atomic.h> |
13 | #include <asm/ptrace.h> | 14 | #include <asm/ptrace.h> |
14 | #include <asm/system.h> | 15 | #include <asm/system.h> |
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index f5fa3082fd6a..6cfb114a0c34 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -329,7 +329,7 @@ void get_zone_counts(unsigned long *active, unsigned long *inactive, | |||
329 | void build_all_zonelists(void); | 329 | void build_all_zonelists(void); |
330 | void wakeup_kswapd(struct zone *zone, int order); | 330 | void wakeup_kswapd(struct zone *zone, int order); |
331 | int zone_watermark_ok(struct zone *z, int order, unsigned long mark, | 331 | int zone_watermark_ok(struct zone *z, int order, unsigned long mark, |
332 | int alloc_type, int can_try_harder, gfp_t gfp_high); | 332 | int classzone_idx, int alloc_flags); |
333 | 333 | ||
334 | #ifdef CONFIG_HAVE_MEMORY_PRESENT | 334 | #ifdef CONFIG_HAVE_MEMORY_PRESENT |
335 | void memory_present(int nid, unsigned long start, unsigned long end); | 335 | void memory_present(int nid, unsigned long start, unsigned long end); |
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index ba6c310a055f..ee700c6eb442 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h | |||
@@ -53,12 +53,12 @@ void release_pages(struct page **pages, int nr, int cold); | |||
53 | 53 | ||
54 | static inline struct page *page_cache_alloc(struct address_space *x) | 54 | static inline struct page *page_cache_alloc(struct address_space *x) |
55 | { | 55 | { |
56 | return alloc_pages(mapping_gfp_mask(x)|__GFP_NORECLAIM, 0); | 56 | return alloc_pages(mapping_gfp_mask(x), 0); |
57 | } | 57 | } |
58 | 58 | ||
59 | static inline struct page *page_cache_alloc_cold(struct address_space *x) | 59 | static inline struct page *page_cache_alloc_cold(struct address_space *x) |
60 | { | 60 | { |
61 | return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD|__GFP_NORECLAIM, 0); | 61 | return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD, 0); |
62 | } | 62 | } |
63 | 63 | ||
64 | typedef int filler_t(void *, struct page *); | 64 | typedef int filler_t(void *, struct page *); |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index d00f8ba7f22b..d4c1c8fd2925 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -805,6 +805,10 @@ | |||
805 | #define PCI_DEVICE_ID_APPLE_SH_SUNGEM 0x0051 | 805 | #define PCI_DEVICE_ID_APPLE_SH_SUNGEM 0x0051 |
806 | #define PCI_DEVICE_ID_APPLE_U3L_AGP 0x0058 | 806 | #define PCI_DEVICE_ID_APPLE_U3L_AGP 0x0058 |
807 | #define PCI_DEVICE_ID_APPLE_U3H_AGP 0x0059 | 807 | #define PCI_DEVICE_ID_APPLE_U3H_AGP 0x0059 |
808 | #define PCI_DEVICE_ID_APPLE_IPID2_AGP 0x0066 | ||
809 | #define PCI_DEVICE_ID_APPLE_IPID2_ATA 0x0069 | ||
810 | #define PCI_DEVICE_ID_APPLE_IPID2_FW 0x006a | ||
811 | #define PCI_DEVICE_ID_APPLE_IPID2_GMAC 0x006b | ||
808 | #define PCI_DEVICE_ID_APPLE_TIGON3 0x1645 | 812 | #define PCI_DEVICE_ID_APPLE_TIGON3 0x1645 |
809 | 813 | ||
810 | #define PCI_VENDOR_ID_YAMAHA 0x1073 | 814 | #define PCI_VENDOR_ID_YAMAHA 0x1073 |
diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 5451eb1e781d..fb8d2d24e4bb 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h | |||
@@ -38,7 +38,7 @@ extern void free_percpu(const void *); | |||
38 | 38 | ||
39 | #else /* CONFIG_SMP */ | 39 | #else /* CONFIG_SMP */ |
40 | 40 | ||
41 | #define per_cpu_ptr(ptr, cpu) (ptr) | 41 | #define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); }) |
42 | 42 | ||
43 | static inline void *__alloc_percpu(size_t size, size_t align) | 43 | static inline void *__alloc_percpu(size_t size, size_t align) |
44 | { | 44 | { |
diff --git a/include/linux/pm.h b/include/linux/pm.h index 1514098d156d..5be87ba3b7ac 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -94,55 +94,6 @@ struct pm_dev | |||
94 | struct list_head entry; | 94 | struct list_head entry; |
95 | }; | 95 | }; |
96 | 96 | ||
97 | #ifdef CONFIG_PM | ||
98 | |||
99 | extern int pm_active; | ||
100 | |||
101 | #define PM_IS_ACTIVE() (pm_active != 0) | ||
102 | |||
103 | /* | ||
104 | * Register a device with power management | ||
105 | */ | ||
106 | struct pm_dev __deprecated * | ||
107 | pm_register(pm_dev_t type, unsigned long id, pm_callback callback); | ||
108 | |||
109 | /* | ||
110 | * Unregister a device with power management | ||
111 | */ | ||
112 | void __deprecated pm_unregister(struct pm_dev *dev); | ||
113 | |||
114 | /* | ||
115 | * Unregister all devices with matching callback | ||
116 | */ | ||
117 | void __deprecated pm_unregister_all(pm_callback callback); | ||
118 | |||
119 | /* | ||
120 | * Send a request to all devices | ||
121 | */ | ||
122 | int __deprecated pm_send_all(pm_request_t rqst, void *data); | ||
123 | |||
124 | #else /* CONFIG_PM */ | ||
125 | |||
126 | #define PM_IS_ACTIVE() 0 | ||
127 | |||
128 | static inline struct pm_dev *pm_register(pm_dev_t type, | ||
129 | unsigned long id, | ||
130 | pm_callback callback) | ||
131 | { | ||
132 | return NULL; | ||
133 | } | ||
134 | |||
135 | static inline void pm_unregister(struct pm_dev *dev) {} | ||
136 | |||
137 | static inline void pm_unregister_all(pm_callback callback) {} | ||
138 | |||
139 | static inline int pm_send_all(pm_request_t rqst, void *data) | ||
140 | { | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | #endif /* CONFIG_PM */ | ||
145 | |||
146 | /* Functions above this comment are list-based old-style power | 97 | /* Functions above this comment are list-based old-style power |
147 | * managment. Please avoid using them. */ | 98 | * managment. Please avoid using them. */ |
148 | 99 | ||
diff --git a/include/linux/pm_legacy.h b/include/linux/pm_legacy.h new file mode 100644 index 000000000000..1252b45face1 --- /dev/null +++ b/include/linux/pm_legacy.h | |||
@@ -0,0 +1,56 @@ | |||
1 | #ifndef __LINUX_PM_LEGACY_H__ | ||
2 | #define __LINUX_PM_LEGACY_H__ | ||
3 | |||
4 | #include <linux/config.h> | ||
5 | |||
6 | #ifdef CONFIG_PM_LEGACY | ||
7 | |||
8 | extern int pm_active; | ||
9 | |||
10 | #define PM_IS_ACTIVE() (pm_active != 0) | ||
11 | |||
12 | /* | ||
13 | * Register a device with power management | ||
14 | */ | ||
15 | struct pm_dev __deprecated * | ||
16 | pm_register(pm_dev_t type, unsigned long id, pm_callback callback); | ||
17 | |||
18 | /* | ||
19 | * Unregister a device with power management | ||
20 | */ | ||
21 | void __deprecated pm_unregister(struct pm_dev *dev); | ||
22 | |||
23 | /* | ||
24 | * Unregister all devices with matching callback | ||
25 | */ | ||
26 | void __deprecated pm_unregister_all(pm_callback callback); | ||
27 | |||
28 | /* | ||
29 | * Send a request to all devices | ||
30 | */ | ||
31 | int __deprecated pm_send_all(pm_request_t rqst, void *data); | ||
32 | |||
33 | #else /* CONFIG_PM_LEGACY */ | ||
34 | |||
35 | #define PM_IS_ACTIVE() 0 | ||
36 | |||
37 | static inline struct pm_dev *pm_register(pm_dev_t type, | ||
38 | unsigned long id, | ||
39 | pm_callback callback) | ||
40 | { | ||
41 | return NULL; | ||
42 | } | ||
43 | |||
44 | static inline void pm_unregister(struct pm_dev *dev) {} | ||
45 | |||
46 | static inline void pm_unregister_all(pm_callback callback) {} | ||
47 | |||
48 | static inline int pm_send_all(pm_request_t rqst, void *data) | ||
49 | { | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | #endif /* CONFIG_PM_LEGACY */ | ||
54 | |||
55 | #endif /* __LINUX_PM_LEGACY_H__ */ | ||
56 | |||
diff --git a/include/linux/preempt.h b/include/linux/preempt.h index dd98c54a23b4..d9a2f5254a51 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h | |||
@@ -7,6 +7,7 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/config.h> | 9 | #include <linux/config.h> |
10 | #include <linux/thread_info.h> | ||
10 | #include <linux/linkage.h> | 11 | #include <linux/linkage.h> |
11 | 12 | ||
12 | #ifdef CONFIG_DEBUG_PREEMPT | 13 | #ifdef CONFIG_DEBUG_PREEMPT |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 2bbf968b23d9..2038bd27b041 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -357,7 +357,6 @@ struct mm_struct { | |||
357 | /* aio bits */ | 357 | /* aio bits */ |
358 | rwlock_t ioctx_list_lock; | 358 | rwlock_t ioctx_list_lock; |
359 | struct kioctx *ioctx_list; | 359 | struct kioctx *ioctx_list; |
360 | struct kioctx default_kioctx; | ||
361 | }; | 360 | }; |
362 | 361 | ||
363 | struct sighand_struct { | 362 | struct sighand_struct { |
@@ -1233,32 +1232,49 @@ static inline void task_unlock(struct task_struct *p) | |||
1233 | spin_unlock(&p->alloc_lock); | 1232 | spin_unlock(&p->alloc_lock); |
1234 | } | 1233 | } |
1235 | 1234 | ||
1235 | #ifndef __HAVE_THREAD_FUNCTIONS | ||
1236 | |||
1237 | #define task_thread_info(task) (task)->thread_info | ||
1238 | |||
1239 | static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) | ||
1240 | { | ||
1241 | *task_thread_info(p) = *task_thread_info(org); | ||
1242 | task_thread_info(p)->task = p; | ||
1243 | } | ||
1244 | |||
1245 | static inline unsigned long *end_of_stack(struct task_struct *p) | ||
1246 | { | ||
1247 | return (unsigned long *)(p->thread_info + 1); | ||
1248 | } | ||
1249 | |||
1250 | #endif | ||
1251 | |||
1236 | /* set thread flags in other task's structures | 1252 | /* set thread flags in other task's structures |
1237 | * - see asm/thread_info.h for TIF_xxxx flags available | 1253 | * - see asm/thread_info.h for TIF_xxxx flags available |
1238 | */ | 1254 | */ |
1239 | static inline void set_tsk_thread_flag(struct task_struct *tsk, int flag) | 1255 | static inline void set_tsk_thread_flag(struct task_struct *tsk, int flag) |
1240 | { | 1256 | { |
1241 | set_ti_thread_flag(tsk->thread_info,flag); | 1257 | set_ti_thread_flag(task_thread_info(tsk), flag); |
1242 | } | 1258 | } |
1243 | 1259 | ||
1244 | static inline void clear_tsk_thread_flag(struct task_struct *tsk, int flag) | 1260 | static inline void clear_tsk_thread_flag(struct task_struct *tsk, int flag) |
1245 | { | 1261 | { |
1246 | clear_ti_thread_flag(tsk->thread_info,flag); | 1262 | clear_ti_thread_flag(task_thread_info(tsk), flag); |
1247 | } | 1263 | } |
1248 | 1264 | ||
1249 | static inline int test_and_set_tsk_thread_flag(struct task_struct *tsk, int flag) | 1265 | static inline int test_and_set_tsk_thread_flag(struct task_struct *tsk, int flag) |
1250 | { | 1266 | { |
1251 | return test_and_set_ti_thread_flag(tsk->thread_info,flag); | 1267 | return test_and_set_ti_thread_flag(task_thread_info(tsk), flag); |
1252 | } | 1268 | } |
1253 | 1269 | ||
1254 | static inline int test_and_clear_tsk_thread_flag(struct task_struct *tsk, int flag) | 1270 | static inline int test_and_clear_tsk_thread_flag(struct task_struct *tsk, int flag) |
1255 | { | 1271 | { |
1256 | return test_and_clear_ti_thread_flag(tsk->thread_info,flag); | 1272 | return test_and_clear_ti_thread_flag(task_thread_info(tsk), flag); |
1257 | } | 1273 | } |
1258 | 1274 | ||
1259 | static inline int test_tsk_thread_flag(struct task_struct *tsk, int flag) | 1275 | static inline int test_tsk_thread_flag(struct task_struct *tsk, int flag) |
1260 | { | 1276 | { |
1261 | return test_ti_thread_flag(tsk->thread_info,flag); | 1277 | return test_ti_thread_flag(task_thread_info(tsk), flag); |
1262 | } | 1278 | } |
1263 | 1279 | ||
1264 | static inline void set_tsk_need_resched(struct task_struct *tsk) | 1280 | static inline void set_tsk_need_resched(struct task_struct *tsk) |
@@ -1329,12 +1345,12 @@ extern void signal_wake_up(struct task_struct *t, int resume_stopped); | |||
1329 | 1345 | ||
1330 | static inline unsigned int task_cpu(const struct task_struct *p) | 1346 | static inline unsigned int task_cpu(const struct task_struct *p) |
1331 | { | 1347 | { |
1332 | return p->thread_info->cpu; | 1348 | return task_thread_info(p)->cpu; |
1333 | } | 1349 | } |
1334 | 1350 | ||
1335 | static inline void set_task_cpu(struct task_struct *p, unsigned int cpu) | 1351 | static inline void set_task_cpu(struct task_struct *p, unsigned int cpu) |
1336 | { | 1352 | { |
1337 | p->thread_info->cpu = cpu; | 1353 | task_thread_info(p)->cpu = cpu; |
1338 | } | 1354 | } |
1339 | 1355 | ||
1340 | #else | 1356 | #else |
diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h index b63ce7014093..fa1ff3b165fe 100644 --- a/include/linux/smp_lock.h +++ b/include/linux/smp_lock.h | |||
@@ -2,11 +2,10 @@ | |||
2 | #define __LINUX_SMPLOCK_H | 2 | #define __LINUX_SMPLOCK_H |
3 | 3 | ||
4 | #include <linux/config.h> | 4 | #include <linux/config.h> |
5 | #ifdef CONFIG_LOCK_KERNEL | ||
5 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
6 | #include <linux/spinlock.h> | 7 | #include <linux/spinlock.h> |
7 | 8 | ||
8 | #ifdef CONFIG_LOCK_KERNEL | ||
9 | |||
10 | #define kernel_locked() (current->lock_depth >= 0) | 9 | #define kernel_locked() (current->lock_depth >= 0) |
11 | 10 | ||
12 | extern int __lockfunc __reacquire_kernel_lock(void); | 11 | extern int __lockfunc __reacquire_kernel_lock(void); |
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index d252f45a0f9b..1c4eb41dbd89 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h | |||
@@ -27,31 +27,6 @@ extern long do_no_restart_syscall(struct restart_block *parm); | |||
27 | * - pass TIF_xxxx constants to these functions | 27 | * - pass TIF_xxxx constants to these functions |
28 | */ | 28 | */ |
29 | 29 | ||
30 | static inline void set_thread_flag(int flag) | ||
31 | { | ||
32 | set_bit(flag,¤t_thread_info()->flags); | ||
33 | } | ||
34 | |||
35 | static inline void clear_thread_flag(int flag) | ||
36 | { | ||
37 | clear_bit(flag,¤t_thread_info()->flags); | ||
38 | } | ||
39 | |||
40 | static inline int test_and_set_thread_flag(int flag) | ||
41 | { | ||
42 | return test_and_set_bit(flag,¤t_thread_info()->flags); | ||
43 | } | ||
44 | |||
45 | static inline int test_and_clear_thread_flag(int flag) | ||
46 | { | ||
47 | return test_and_clear_bit(flag,¤t_thread_info()->flags); | ||
48 | } | ||
49 | |||
50 | static inline int test_thread_flag(int flag) | ||
51 | { | ||
52 | return test_bit(flag,¤t_thread_info()->flags); | ||
53 | } | ||
54 | |||
55 | static inline void set_ti_thread_flag(struct thread_info *ti, int flag) | 30 | static inline void set_ti_thread_flag(struct thread_info *ti, int flag) |
56 | { | 31 | { |
57 | set_bit(flag,&ti->flags); | 32 | set_bit(flag,&ti->flags); |
@@ -77,15 +52,19 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag) | |||
77 | return test_bit(flag,&ti->flags); | 52 | return test_bit(flag,&ti->flags); |
78 | } | 53 | } |
79 | 54 | ||
80 | static inline void set_need_resched(void) | 55 | #define set_thread_flag(flag) \ |
81 | { | 56 | set_ti_thread_flag(current_thread_info(), flag) |
82 | set_thread_flag(TIF_NEED_RESCHED); | 57 | #define clear_thread_flag(flag) \ |
83 | } | 58 | clear_ti_thread_flag(current_thread_info(), flag) |
84 | 59 | #define test_and_set_thread_flag(flag) \ | |
85 | static inline void clear_need_resched(void) | 60 | test_and_set_ti_thread_flag(current_thread_info(), flag) |
86 | { | 61 | #define test_and_clear_thread_flag(flag) \ |
87 | clear_thread_flag(TIF_NEED_RESCHED); | 62 | test_and_clear_ti_thread_flag(current_thread_info(), flag) |
88 | } | 63 | #define test_thread_flag(flag) \ |
64 | test_ti_thread_flag(current_thread_info(), flag) | ||
65 | |||
66 | #define set_need_resched() set_thread_flag(TIF_NEED_RESCHED) | ||
67 | #define clear_need_resched() clear_thread_flag(TIF_NEED_RESCHED) | ||
89 | 68 | ||
90 | #endif | 69 | #endif |
91 | 70 | ||
diff --git a/include/linux/time.h b/include/linux/time.h index 8e83f4e778bb..bfbe92d0767c 100644 --- a/include/linux/time.h +++ b/include/linux/time.h | |||
@@ -101,7 +101,7 @@ extern struct timespec timespec_trunc(struct timespec t, unsigned gran); | |||
101 | static inline void | 101 | static inline void |
102 | set_normalized_timespec (struct timespec *ts, time_t sec, long nsec) | 102 | set_normalized_timespec (struct timespec *ts, time_t sec, long nsec) |
103 | { | 103 | { |
104 | while (nsec > NSEC_PER_SEC) { | 104 | while (nsec >= NSEC_PER_SEC) { |
105 | nsec -= NSEC_PER_SEC; | 105 | nsec -= NSEC_PER_SEC; |
106 | ++sec; | 106 | ++sec; |
107 | } | 107 | } |
diff --git a/include/linux/usb.h b/include/linux/usb.h index 748d04385256..856d232c7562 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -819,7 +819,7 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *); | |||
819 | */ | 819 | */ |
820 | struct urb | 820 | struct urb |
821 | { | 821 | { |
822 | /* private, usb core and host controller only fields in the urb */ | 822 | /* private: usb core and host controller only fields in the urb */ |
823 | struct kref kref; /* reference count of the URB */ | 823 | struct kref kref; /* reference count of the URB */ |
824 | spinlock_t lock; /* lock for the URB */ | 824 | spinlock_t lock; /* lock for the URB */ |
825 | void *hcpriv; /* private data for host controller */ | 825 | void *hcpriv; /* private data for host controller */ |
@@ -827,7 +827,7 @@ struct urb | |||
827 | atomic_t use_count; /* concurrent submissions counter */ | 827 | atomic_t use_count; /* concurrent submissions counter */ |
828 | u8 reject; /* submissions will fail */ | 828 | u8 reject; /* submissions will fail */ |
829 | 829 | ||
830 | /* public, documented fields in the urb that can be used by drivers */ | 830 | /* public: documented fields in the urb that can be used by drivers */ |
831 | struct list_head urb_list; /* list head for use by the urb's | 831 | struct list_head urb_list; /* list head for use by the urb's |
832 | * current owner */ | 832 | * current owner */ |
833 | struct usb_device *dev; /* (in) pointer to associated device */ | 833 | struct usb_device *dev; /* (in) pointer to associated device */ |
@@ -1045,7 +1045,7 @@ struct usb_sg_request { | |||
1045 | size_t bytes; | 1045 | size_t bytes; |
1046 | 1046 | ||
1047 | /* | 1047 | /* |
1048 | * members below are private to usbcore, | 1048 | * members below are private: to usbcore, |
1049 | * and are not provided for driver access! | 1049 | * and are not provided for driver access! |
1050 | */ | 1050 | */ |
1051 | spinlock_t lock; | 1051 | spinlock_t lock; |
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index a114fff6568b..1cded681eb6d 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h | |||
@@ -636,6 +636,7 @@ typedef __u64 v4l2_std_id; | |||
636 | #define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000) | 636 | #define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000) |
637 | #define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000) | 637 | #define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000) |
638 | #define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000) | 638 | #define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000) |
639 | #define V4L2_STD_SECAM_LC ((v4l2_std_id)0x00800000) | ||
639 | 640 | ||
640 | /* ATSC/HDTV */ | 641 | /* ATSC/HDTV */ |
641 | #define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000) | 642 | #define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000) |
diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 0f1ba95ec8d6..ad3e9bb670c3 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h | |||
@@ -49,6 +49,7 @@ struct ir_input_state { | |||
49 | 49 | ||
50 | extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; | 50 | extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; |
51 | extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; | 51 | extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; |
52 | extern IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE]; | ||
52 | extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; | 53 | extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; |
53 | extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; | 54 | extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; |
54 | extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; | 55 | extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; |
diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h index 00fa57eb9fde..730f21ed91db 100644 --- a/include/media/ir-kbd-i2c.h +++ b/include/media/ir-kbd-i2c.h | |||
@@ -19,4 +19,6 @@ struct IR_i2c { | |||
19 | char phys[32]; | 19 | char phys[32]; |
20 | int (*get_key)(struct IR_i2c*, u32*, u32*); | 20 | int (*get_key)(struct IR_i2c*, u32*, u32*); |
21 | }; | 21 | }; |
22 | |||
23 | int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); | ||
22 | #endif | 24 | #endif |
diff --git a/include/media/tuner.h b/include/media/tuner.h index 9184e534b7ef..faa0f8e3091b 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h | |||
@@ -113,6 +113,7 @@ | |||
113 | #define TUNER_PHILIPS_TD1316 67 | 113 | #define TUNER_PHILIPS_TD1316 67 |
114 | 114 | ||
115 | #define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */ | 115 | #define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */ |
116 | #define TUNER_TNF_5335MF 69 /* Sabrent Bt848 */ | ||
116 | 117 | ||
117 | #define NOTUNER 0 | 118 | #define NOTUNER 0 |
118 | #define PAL 1 /* PAL_BG */ | 119 | #define PAL 1 /* PAL_BG */ |
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h new file mode 100644 index 000000000000..d3fd48157eb8 --- /dev/null +++ b/include/media/v4l2-common.h | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | v4l2 common internal API header | ||
3 | |||
4 | This header contains internal shared ioctl definitions for use by the | ||
5 | internal low-level v4l2 drivers. | ||
6 | Each ioctl begins with VIDIOC_INT_ to clearly mark that it is an internal | ||
7 | define, | ||
8 | |||
9 | Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl> | ||
10 | |||
11 | This program is free software; you can redistribute it and/or modify | ||
12 | it under the terms of the GNU General Public License as published by | ||
13 | the Free Software Foundation; either version 2 of the License, or | ||
14 | (at your option) any later version. | ||
15 | |||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | GNU General Public License for more details. | ||
20 | |||
21 | You should have received a copy of the GNU General Public License | ||
22 | along with this program; if not, write to the Free Software | ||
23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | */ | ||
25 | |||
26 | #ifndef V4L2_COMMON_H_ | ||
27 | #define V4L2_COMMON_H_ | ||
28 | |||
29 | /* VIDIOC_INT_AUDIO_CLOCK_FREQ */ | ||
30 | enum v4l2_audio_clock_freq { | ||
31 | V4L2_AUDCLK_32_KHZ = 32000, | ||
32 | V4L2_AUDCLK_441_KHZ = 44100, | ||
33 | V4L2_AUDCLK_48_KHZ = 48000, | ||
34 | }; | ||
35 | |||
36 | /* VIDIOC_INT_G_REGISTER and VIDIOC_INT_S_REGISTER */ | ||
37 | struct v4l2_register { | ||
38 | u32 i2c_id; /* I2C driver ID of the I2C chip. 0 for the I2C adapter. */ | ||
39 | unsigned long reg; | ||
40 | u32 val; | ||
41 | }; | ||
42 | |||
43 | /* VIDIOC_INT_DECODE_VBI_LINE */ | ||
44 | struct v4l2_decode_vbi_line { | ||
45 | u32 is_second_field; /* Set to 0 for the first (odd) field, | ||
46 | set to 1 for the second (even) field. */ | ||
47 | u8 *p; /* Pointer to the sliced VBI data from the decoder. | ||
48 | On exit points to the start of the payload. */ | ||
49 | u32 line; /* Line number of the sliced VBI data (1-23) */ | ||
50 | u32 type; /* VBI service type (V4L2_SLICED_*). 0 if no service found */ | ||
51 | }; | ||
52 | |||
53 | /* VIDIOC_INT_G_CHIP_IDENT: identifies the actual chip installed on the board */ | ||
54 | enum v4l2_chip_ident { | ||
55 | /* general idents: reserved range 0-49 */ | ||
56 | V4L2_IDENT_UNKNOWN = 0, | ||
57 | |||
58 | /* module saa7115: reserved range 100-149 */ | ||
59 | V4L2_IDENT_SAA7114 = 104, | ||
60 | V4L2_IDENT_SAA7115 = 105, | ||
61 | |||
62 | /* module saa7127: reserved range 150-199 */ | ||
63 | V4L2_IDENT_SAA7127 = 157, | ||
64 | V4L2_IDENT_SAA7129 = 159, | ||
65 | |||
66 | /* module cx25840: reserved range 200-249 */ | ||
67 | V4L2_IDENT_CX25840 = 240, | ||
68 | V4L2_IDENT_CX25841 = 241, | ||
69 | V4L2_IDENT_CX25842 = 242, | ||
70 | V4L2_IDENT_CX25843 = 243, | ||
71 | }; | ||
72 | |||
73 | /* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */ | ||
74 | #define VIDIOC_INT_S_REGISTER _IOR ('d', 100, struct v4l2_register) | ||
75 | #define VIDIOC_INT_G_REGISTER _IOWR('d', 101, struct v4l2_register) | ||
76 | |||
77 | /* Reset the I2C chip */ | ||
78 | #define VIDIOC_INT_RESET _IO ('d', 102) | ||
79 | |||
80 | /* Set the frequency of the audio clock output. | ||
81 | Used to slave an audio processor to the video decoder, ensuring that audio | ||
82 | and video remain synchronized. */ | ||
83 | #define VIDIOC_INT_AUDIO_CLOCK_FREQ _IOR ('d', 103, enum v4l2_audio_clock_freq) | ||
84 | |||
85 | /* Video decoders that support sliced VBI need to implement this ioctl. | ||
86 | Field p of the v4l2_sliced_vbi_line struct is set to the start of the VBI | ||
87 | data that was generated by the decoder. The driver then parses the sliced | ||
88 | VBI data and sets the other fields in the struct accordingly. The pointer p | ||
89 | is updated to point to the start of the payload which can be copied | ||
90 | verbatim into the data field of the v4l2_sliced_vbi_data struct. If no | ||
91 | valid VBI data was found, then the type field is set to 0 on return. */ | ||
92 | #define VIDIOC_INT_DECODE_VBI_LINE _IOWR('d', 104, struct v4l2_decode_vbi_line) | ||
93 | |||
94 | /* Used to generate VBI signals on a video signal. v4l2_sliced_vbi_data is | ||
95 | filled with the data packets that should be output. Note that if you set | ||
96 | the line field to 0, then that VBI signal is disabled. */ | ||
97 | #define VIDIOC_INT_S_VBI_DATA _IOW ('d', 105, struct v4l2_sliced_vbi_data) | ||
98 | |||
99 | /* Used to obtain the sliced VBI packet from a readback register. Not all | ||
100 | video decoders support this. If no data is available because the readback | ||
101 | register contains invalid or erroneous data -EIO is returned. Note that | ||
102 | you must fill in the 'id' member and the 'field' member (to determine | ||
103 | whether CC data from the first or second field should be obtained). */ | ||
104 | #define VIDIOC_INT_G_VBI_DATA _IOWR('d', 106, struct v4l2_sliced_vbi_data *) | ||
105 | |||
106 | /* Returns the chip identifier or V4L2_IDENT_UNKNOWN if no identification can | ||
107 | be made. */ | ||
108 | #define VIDIOC_INT_G_CHIP_IDENT _IOR ('d', 107, enum v4l2_chip_ident *) | ||
109 | |||
110 | #endif /* V4L2_COMMON_H_ */ | ||
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 5a737ed9dac7..7430640f9816 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -1809,11 +1809,12 @@ int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) | |||
1809 | if (gfp_mask & __GFP_HARDWALL) /* If hardwall request, stop here */ | 1809 | if (gfp_mask & __GFP_HARDWALL) /* If hardwall request, stop here */ |
1810 | return 0; | 1810 | return 0; |
1811 | 1811 | ||
1812 | if (current->flags & PF_EXITING) /* Let dying task have memory */ | ||
1813 | return 1; | ||
1814 | |||
1812 | /* Not hardwall and node outside mems_allowed: scan up cpusets */ | 1815 | /* Not hardwall and node outside mems_allowed: scan up cpusets */ |
1813 | down(&callback_sem); | 1816 | down(&callback_sem); |
1814 | 1817 | ||
1815 | if (current->flags & PF_EXITING) /* Let dying task have memory */ | ||
1816 | return 1; | ||
1817 | task_lock(current); | 1818 | task_lock(current); |
1818 | cs = nearest_exclusive_ancestor(current->cpuset); | 1819 | cs = nearest_exclusive_ancestor(current->cpuset); |
1819 | task_unlock(current); | 1820 | task_unlock(current); |
diff --git a/kernel/exit.c b/kernel/exit.c index 452a1d116178..ee515683b92d 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -859,7 +859,7 @@ fastcall NORET_TYPE void do_exit(long code) | |||
859 | if (group_dead && tsk->signal->leader) | 859 | if (group_dead && tsk->signal->leader) |
860 | disassociate_ctty(1); | 860 | disassociate_ctty(1); |
861 | 861 | ||
862 | module_put(tsk->thread_info->exec_domain->module); | 862 | module_put(task_thread_info(tsk)->exec_domain->module); |
863 | if (tsk->binfmt) | 863 | if (tsk->binfmt) |
864 | module_put(tsk->binfmt->module); | 864 | module_put(tsk->binfmt->module); |
865 | 865 | ||
diff --git a/kernel/fork.c b/kernel/fork.c index 158710d22566..e0d0b77343f8 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -171,10 +171,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
171 | return NULL; | 171 | return NULL; |
172 | } | 172 | } |
173 | 173 | ||
174 | *ti = *orig->thread_info; | ||
175 | *tsk = *orig; | 174 | *tsk = *orig; |
176 | tsk->thread_info = ti; | 175 | tsk->thread_info = ti; |
177 | ti->task = tsk; | 176 | setup_thread_stack(tsk, orig); |
178 | 177 | ||
179 | /* One for us, one for whoever does the "release_task()" (usually parent) */ | 178 | /* One for us, one for whoever does the "release_task()" (usually parent) */ |
180 | atomic_set(&tsk->usage,2); | 179 | atomic_set(&tsk->usage,2); |
@@ -324,7 +323,6 @@ static struct mm_struct * mm_init(struct mm_struct * mm) | |||
324 | spin_lock_init(&mm->page_table_lock); | 323 | spin_lock_init(&mm->page_table_lock); |
325 | rwlock_init(&mm->ioctx_list_lock); | 324 | rwlock_init(&mm->ioctx_list_lock); |
326 | mm->ioctx_list = NULL; | 325 | mm->ioctx_list = NULL; |
327 | mm->default_kioctx = (struct kioctx)INIT_KIOCTX(mm->default_kioctx, *mm); | ||
328 | mm->free_area_cache = TASK_UNMAPPED_BASE; | 326 | mm->free_area_cache = TASK_UNMAPPED_BASE; |
329 | mm->cached_hole_size = ~0UL; | 327 | mm->cached_hole_size = ~0UL; |
330 | 328 | ||
@@ -919,7 +917,7 @@ static task_t *copy_process(unsigned long clone_flags, | |||
919 | if (nr_threads >= max_threads) | 917 | if (nr_threads >= max_threads) |
920 | goto bad_fork_cleanup_count; | 918 | goto bad_fork_cleanup_count; |
921 | 919 | ||
922 | if (!try_module_get(p->thread_info->exec_domain->module)) | 920 | if (!try_module_get(task_thread_info(p)->exec_domain->module)) |
923 | goto bad_fork_cleanup_count; | 921 | goto bad_fork_cleanup_count; |
924 | 922 | ||
925 | if (p->binfmt && !try_module_get(p->binfmt->module)) | 923 | if (p->binfmt && !try_module_get(p->binfmt->module)) |
@@ -1180,7 +1178,7 @@ bad_fork_cleanup: | |||
1180 | if (p->binfmt) | 1178 | if (p->binfmt) |
1181 | module_put(p->binfmt->module); | 1179 | module_put(p->binfmt->module); |
1182 | bad_fork_cleanup_put_domain: | 1180 | bad_fork_cleanup_put_domain: |
1183 | module_put(p->thread_info->exec_domain->module); | 1181 | module_put(task_thread_info(p)->exec_domain->module); |
1184 | bad_fork_cleanup_count: | 1182 | bad_fork_cleanup_count: |
1185 | put_group_info(p->group_info); | 1183 | put_group_info(p->group_info); |
1186 | atomic_dec(&p->user->processes); | 1184 | atomic_dec(&p->user->processes); |
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index ea55c7a1cd75..5870efb3e200 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c | |||
@@ -270,7 +270,7 @@ static void tstojiffie(struct timespec *tp, int res, u64 *jiff) | |||
270 | long sec = tp->tv_sec; | 270 | long sec = tp->tv_sec; |
271 | long nsec = tp->tv_nsec + res - 1; | 271 | long nsec = tp->tv_nsec + res - 1; |
272 | 272 | ||
273 | if (nsec > NSEC_PER_SEC) { | 273 | if (nsec >= NSEC_PER_SEC) { |
274 | sec++; | 274 | sec++; |
275 | nsec -= NSEC_PER_SEC; | 275 | nsec -= NSEC_PER_SEC; |
276 | } | 276 | } |
@@ -1209,13 +1209,9 @@ static int do_posix_clock_monotonic_get(clockid_t clock, struct timespec *tp) | |||
1209 | 1209 | ||
1210 | do_posix_clock_monotonic_gettime_parts(tp, &wall_to_mono); | 1210 | do_posix_clock_monotonic_gettime_parts(tp, &wall_to_mono); |
1211 | 1211 | ||
1212 | tp->tv_sec += wall_to_mono.tv_sec; | 1212 | set_normalized_timespec(tp, tp->tv_sec + wall_to_mono.tv_sec, |
1213 | tp->tv_nsec += wall_to_mono.tv_nsec; | 1213 | tp->tv_nsec + wall_to_mono.tv_nsec); |
1214 | 1214 | ||
1215 | if ((tp->tv_nsec - NSEC_PER_SEC) > 0) { | ||
1216 | tp->tv_nsec -= NSEC_PER_SEC; | ||
1217 | tp->tv_sec++; | ||
1218 | } | ||
1219 | return 0; | 1215 | return 0; |
1220 | } | 1216 | } |
1221 | 1217 | ||
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 46a5e5acff97..5ec248cb7f4a 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -19,6 +19,15 @@ config PM | |||
19 | will issue the hlt instruction if nothing is to be done, thereby | 19 | will issue the hlt instruction if nothing is to be done, thereby |
20 | sending the processor to sleep and saving power. | 20 | sending the processor to sleep and saving power. |
21 | 21 | ||
22 | config PM_LEGACY | ||
23 | bool "Legacy Power Management API" | ||
24 | depends on PM | ||
25 | default y | ||
26 | ---help--- | ||
27 | Support for pm_register() and friends. | ||
28 | |||
29 | If unsure, say Y. | ||
30 | |||
22 | config PM_DEBUG | 31 | config PM_DEBUG |
23 | bool "Power Management Debug Support" | 32 | bool "Power Management Debug Support" |
24 | depends on PM | 33 | depends on PM |
diff --git a/kernel/power/Makefile b/kernel/power/Makefile index c71eb4579c07..04be7d0d96a7 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile | |||
@@ -3,7 +3,8 @@ ifeq ($(CONFIG_PM_DEBUG),y) | |||
3 | EXTRA_CFLAGS += -DDEBUG | 3 | EXTRA_CFLAGS += -DDEBUG |
4 | endif | 4 | endif |
5 | 5 | ||
6 | obj-y := main.o process.o console.o pm.o | 6 | obj-y := main.o process.o console.o |
7 | obj-$(CONFIG_PM_LEGACY) += pm.o | ||
7 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o snapshot.o | 8 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o snapshot.o |
8 | 9 | ||
9 | obj-$(CONFIG_SUSPEND_SMP) += smp.o | 10 | obj-$(CONFIG_SUSPEND_SMP) += smp.o |
diff --git a/kernel/power/pm.c b/kernel/power/pm.c index 159149321b3c..33c508e857dd 100644 --- a/kernel/power/pm.c +++ b/kernel/power/pm.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
26 | #include <linux/pm_legacy.h> | ||
26 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
27 | 28 | ||
28 | int pm_active; | 29 | int pm_active; |
diff --git a/kernel/printk.c b/kernel/printk.c index e9be027bc930..ac8a08f36207 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -491,7 +491,10 @@ __attribute__((weak)) unsigned long long printk_clock(void) | |||
491 | return sched_clock(); | 491 | return sched_clock(); |
492 | } | 492 | } |
493 | 493 | ||
494 | /* | 494 | /** |
495 | * printk - print a kernel message | ||
496 | * @fmt: format string | ||
497 | * | ||
495 | * This is printk. It can be called from any context. We want it to work. | 498 | * This is printk. It can be called from any context. We want it to work. |
496 | * | 499 | * |
497 | * We try to grab the console_sem. If we succeed, it's easy - we log the output and | 500 | * We try to grab the console_sem. If we succeed, it's easy - we log the output and |
@@ -503,6 +506,9 @@ __attribute__((weak)) unsigned long long printk_clock(void) | |||
503 | * One effect of this deferred printing is that code which calls printk() and | 506 | * One effect of this deferred printing is that code which calls printk() and |
504 | * then changes console_loglevel may break. This is because console_loglevel | 507 | * then changes console_loglevel may break. This is because console_loglevel |
505 | * is inspected when the actual printing occurs. | 508 | * is inspected when the actual printing occurs. |
509 | * | ||
510 | * See also: | ||
511 | * printf(3) | ||
506 | */ | 512 | */ |
507 | 513 | ||
508 | asmlinkage int printk(const char *fmt, ...) | 514 | asmlinkage int printk(const char *fmt, ...) |
@@ -655,6 +661,9 @@ static void call_console_drivers(unsigned long start, unsigned long end) | |||
655 | 661 | ||
656 | /** | 662 | /** |
657 | * add_preferred_console - add a device to the list of preferred consoles. | 663 | * add_preferred_console - add a device to the list of preferred consoles. |
664 | * @name: device name | ||
665 | * @idx: device index | ||
666 | * @options: options for this console | ||
658 | * | 667 | * |
659 | * The last preferred console added will be used for kernel messages | 668 | * The last preferred console added will be used for kernel messages |
660 | * and stdin/out/err for init. Normally this is used by console_setup | 669 | * and stdin/out/err for init. Normally this is used by console_setup |
@@ -764,7 +773,8 @@ void release_console_sem(void) | |||
764 | } | 773 | } |
765 | EXPORT_SYMBOL(release_console_sem); | 774 | EXPORT_SYMBOL(release_console_sem); |
766 | 775 | ||
767 | /** console_conditional_schedule - yield the CPU if required | 776 | /** |
777 | * console_conditional_schedule - yield the CPU if required | ||
768 | * | 778 | * |
769 | * If the console code is currently allowed to sleep, and | 779 | * If the console code is currently allowed to sleep, and |
770 | * if this CPU should yield the CPU to another task, do | 780 | * if this CPU should yield the CPU to another task, do |
@@ -976,6 +986,8 @@ EXPORT_SYMBOL(unregister_console); | |||
976 | 986 | ||
977 | /** | 987 | /** |
978 | * tty_write_message - write a message to a certain tty, not just the console. | 988 | * tty_write_message - write a message to a certain tty, not just the console. |
989 | * @tty: the destination tty_struct | ||
990 | * @msg: the message to write | ||
979 | * | 991 | * |
980 | * This is used for messages that need to be redirected to a specific tty. | 992 | * This is used for messages that need to be redirected to a specific tty. |
981 | * We don't put it into the syslog queue right now maybe in the future if | 993 | * We don't put it into the syslog queue right now maybe in the future if |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index b88d4186cd7a..17ee7e5a3451 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -470,7 +470,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) | |||
470 | 470 | ||
471 | if (request == PTRACE_ATTACH) { | 471 | if (request == PTRACE_ATTACH) { |
472 | ret = ptrace_attach(child); | 472 | ret = ptrace_attach(child); |
473 | goto out; | 473 | goto out_put_task_struct; |
474 | } | 474 | } |
475 | 475 | ||
476 | ret = ptrace_check_attach(child, request == PTRACE_KILL); | 476 | ret = ptrace_check_attach(child, request == PTRACE_KILL); |
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 9b58f1eff3ca..eb6719c50b4e 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c | |||
@@ -195,6 +195,8 @@ rcu_torture_writer(void *arg) | |||
195 | static DEFINE_RCU_RANDOM(rand); | 195 | static DEFINE_RCU_RANDOM(rand); |
196 | 196 | ||
197 | VERBOSE_PRINTK_STRING("rcu_torture_writer task started"); | 197 | VERBOSE_PRINTK_STRING("rcu_torture_writer task started"); |
198 | set_user_nice(current, 19); | ||
199 | |||
198 | do { | 200 | do { |
199 | schedule_timeout_uninterruptible(1); | 201 | schedule_timeout_uninterruptible(1); |
200 | if (rcu_batches_completed() == oldbatch) | 202 | if (rcu_batches_completed() == oldbatch) |
@@ -238,6 +240,8 @@ rcu_torture_reader(void *arg) | |||
238 | int pipe_count; | 240 | int pipe_count; |
239 | 241 | ||
240 | VERBOSE_PRINTK_STRING("rcu_torture_reader task started"); | 242 | VERBOSE_PRINTK_STRING("rcu_torture_reader task started"); |
243 | set_user_nice(current, 19); | ||
244 | |||
241 | do { | 245 | do { |
242 | rcu_read_lock(); | 246 | rcu_read_lock(); |
243 | completed = rcu_batches_completed(); | 247 | completed = rcu_batches_completed(); |
diff --git a/kernel/sched.c b/kernel/sched.c index b6506671b2be..6f46c94cc29e 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -1437,7 +1437,7 @@ void fastcall sched_fork(task_t *p, int clone_flags) | |||
1437 | #endif | 1437 | #endif |
1438 | #ifdef CONFIG_PREEMPT | 1438 | #ifdef CONFIG_PREEMPT |
1439 | /* Want to start with kernel preemption disabled. */ | 1439 | /* Want to start with kernel preemption disabled. */ |
1440 | p->thread_info->preempt_count = 1; | 1440 | task_thread_info(p)->preempt_count = 1; |
1441 | #endif | 1441 | #endif |
1442 | /* | 1442 | /* |
1443 | * Share the timeslice between parent and child, thus the | 1443 | * Share the timeslice between parent and child, thus the |
@@ -4327,10 +4327,10 @@ static void show_task(task_t *p) | |||
4327 | #endif | 4327 | #endif |
4328 | #ifdef CONFIG_DEBUG_STACK_USAGE | 4328 | #ifdef CONFIG_DEBUG_STACK_USAGE |
4329 | { | 4329 | { |
4330 | unsigned long *n = (unsigned long *) (p->thread_info+1); | 4330 | unsigned long *n = end_of_stack(p); |
4331 | while (!*n) | 4331 | while (!*n) |
4332 | n++; | 4332 | n++; |
4333 | free = (unsigned long) n - (unsigned long)(p->thread_info+1); | 4333 | free = (unsigned long)n - (unsigned long)end_of_stack(p); |
4334 | } | 4334 | } |
4335 | #endif | 4335 | #endif |
4336 | printk("%5lu %5d %6d ", free, p->pid, p->parent->pid); | 4336 | printk("%5lu %5d %6d ", free, p->pid, p->parent->pid); |
@@ -4410,9 +4410,9 @@ void __devinit init_idle(task_t *idle, int cpu) | |||
4410 | 4410 | ||
4411 | /* Set the preempt count _outside_ the spinlocks! */ | 4411 | /* Set the preempt count _outside_ the spinlocks! */ |
4412 | #if defined(CONFIG_PREEMPT) && !defined(CONFIG_PREEMPT_BKL) | 4412 | #if defined(CONFIG_PREEMPT) && !defined(CONFIG_PREEMPT_BKL) |
4413 | idle->thread_info->preempt_count = (idle->lock_depth >= 0); | 4413 | task_thread_info(idle)->preempt_count = (idle->lock_depth >= 0); |
4414 | #else | 4414 | #else |
4415 | idle->thread_info->preempt_count = 0; | 4415 | task_thread_info(idle)->preempt_count = 0; |
4416 | #endif | 4416 | #endif |
4417 | } | 4417 | } |
4418 | 4418 | ||
diff --git a/kernel/signal.c b/kernel/signal.c index 80789a59b4db..d7611f189ef7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -513,16 +513,7 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, | |||
513 | { | 513 | { |
514 | int sig = 0; | 514 | int sig = 0; |
515 | 515 | ||
516 | /* SIGKILL must have priority, otherwise it is quite easy | 516 | sig = next_signal(pending, mask); |
517 | * to create an unkillable process, sending sig < SIGKILL | ||
518 | * to self */ | ||
519 | if (unlikely(sigismember(&pending->signal, SIGKILL))) { | ||
520 | if (!sigismember(mask, SIGKILL)) | ||
521 | sig = SIGKILL; | ||
522 | } | ||
523 | |||
524 | if (likely(!sig)) | ||
525 | sig = next_signal(pending, mask); | ||
526 | if (sig) { | 517 | if (sig) { |
527 | if (current->notifier) { | 518 | if (current->notifier) { |
528 | if (sigismember(current->notifier_mask, sig)) { | 519 | if (sigismember(current->notifier_mask, sig)) { |
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 84a9d18aa8da..b3d4dc858e35 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c | |||
@@ -119,13 +119,12 @@ static int stop_machine(void) | |||
119 | return ret; | 119 | return ret; |
120 | } | 120 | } |
121 | 121 | ||
122 | /* Don't schedule us away at this point, please. */ | ||
123 | local_irq_disable(); | ||
124 | |||
125 | /* Now they are all started, make them hold the CPUs, ready. */ | 122 | /* Now they are all started, make them hold the CPUs, ready. */ |
123 | preempt_disable(); | ||
126 | stopmachine_set_state(STOPMACHINE_PREPARE); | 124 | stopmachine_set_state(STOPMACHINE_PREPARE); |
127 | 125 | ||
128 | /* Make them disable irqs. */ | 126 | /* Make them disable irqs. */ |
127 | local_irq_disable(); | ||
129 | stopmachine_set_state(STOPMACHINE_DISABLE_IRQ); | 128 | stopmachine_set_state(STOPMACHINE_DISABLE_IRQ); |
130 | 129 | ||
131 | return 0; | 130 | return 0; |
@@ -135,6 +134,7 @@ static void restart_machine(void) | |||
135 | { | 134 | { |
136 | stopmachine_set_state(STOPMACHINE_EXIT); | 135 | stopmachine_set_state(STOPMACHINE_EXIT); |
137 | local_irq_enable(); | 136 | local_irq_enable(); |
137 | preempt_enable_no_resched(); | ||
138 | } | 138 | } |
139 | 139 | ||
140 | struct stop_machine_data | 140 | struct stop_machine_data |
diff --git a/mm/memory.c b/mm/memory.c index 0f60baf6f69b..2998cfc12f5b 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -549,10 +549,10 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
549 | return 0; | 549 | return 0; |
550 | } | 550 | } |
551 | 551 | ||
552 | static void zap_pte_range(struct mmu_gather *tlb, | 552 | static unsigned long zap_pte_range(struct mmu_gather *tlb, |
553 | struct vm_area_struct *vma, pmd_t *pmd, | 553 | struct vm_area_struct *vma, pmd_t *pmd, |
554 | unsigned long addr, unsigned long end, | 554 | unsigned long addr, unsigned long end, |
555 | struct zap_details *details) | 555 | long *zap_work, struct zap_details *details) |
556 | { | 556 | { |
557 | struct mm_struct *mm = tlb->mm; | 557 | struct mm_struct *mm = tlb->mm; |
558 | pte_t *pte; | 558 | pte_t *pte; |
@@ -563,10 +563,15 @@ static void zap_pte_range(struct mmu_gather *tlb, | |||
563 | pte = pte_offset_map_lock(mm, pmd, addr, &ptl); | 563 | pte = pte_offset_map_lock(mm, pmd, addr, &ptl); |
564 | do { | 564 | do { |
565 | pte_t ptent = *pte; | 565 | pte_t ptent = *pte; |
566 | if (pte_none(ptent)) | 566 | if (pte_none(ptent)) { |
567 | (*zap_work)--; | ||
567 | continue; | 568 | continue; |
569 | } | ||
568 | if (pte_present(ptent)) { | 570 | if (pte_present(ptent)) { |
569 | struct page *page = NULL; | 571 | struct page *page = NULL; |
572 | |||
573 | (*zap_work) -= PAGE_SIZE; | ||
574 | |||
570 | if (!(vma->vm_flags & VM_RESERVED)) { | 575 | if (!(vma->vm_flags & VM_RESERVED)) { |
571 | unsigned long pfn = pte_pfn(ptent); | 576 | unsigned long pfn = pte_pfn(ptent); |
572 | if (unlikely(!pfn_valid(pfn))) | 577 | if (unlikely(!pfn_valid(pfn))) |
@@ -624,16 +629,18 @@ static void zap_pte_range(struct mmu_gather *tlb, | |||
624 | if (!pte_file(ptent)) | 629 | if (!pte_file(ptent)) |
625 | free_swap_and_cache(pte_to_swp_entry(ptent)); | 630 | free_swap_and_cache(pte_to_swp_entry(ptent)); |
626 | pte_clear_full(mm, addr, pte, tlb->fullmm); | 631 | pte_clear_full(mm, addr, pte, tlb->fullmm); |
627 | } while (pte++, addr += PAGE_SIZE, addr != end); | 632 | } while (pte++, addr += PAGE_SIZE, (addr != end && *zap_work > 0)); |
628 | 633 | ||
629 | add_mm_rss(mm, file_rss, anon_rss); | 634 | add_mm_rss(mm, file_rss, anon_rss); |
630 | pte_unmap_unlock(pte - 1, ptl); | 635 | pte_unmap_unlock(pte - 1, ptl); |
636 | |||
637 | return addr; | ||
631 | } | 638 | } |
632 | 639 | ||
633 | static inline void zap_pmd_range(struct mmu_gather *tlb, | 640 | static inline unsigned long zap_pmd_range(struct mmu_gather *tlb, |
634 | struct vm_area_struct *vma, pud_t *pud, | 641 | struct vm_area_struct *vma, pud_t *pud, |
635 | unsigned long addr, unsigned long end, | 642 | unsigned long addr, unsigned long end, |
636 | struct zap_details *details) | 643 | long *zap_work, struct zap_details *details) |
637 | { | 644 | { |
638 | pmd_t *pmd; | 645 | pmd_t *pmd; |
639 | unsigned long next; | 646 | unsigned long next; |
@@ -641,16 +648,21 @@ static inline void zap_pmd_range(struct mmu_gather *tlb, | |||
641 | pmd = pmd_offset(pud, addr); | 648 | pmd = pmd_offset(pud, addr); |
642 | do { | 649 | do { |
643 | next = pmd_addr_end(addr, end); | 650 | next = pmd_addr_end(addr, end); |
644 | if (pmd_none_or_clear_bad(pmd)) | 651 | if (pmd_none_or_clear_bad(pmd)) { |
652 | (*zap_work)--; | ||
645 | continue; | 653 | continue; |
646 | zap_pte_range(tlb, vma, pmd, addr, next, details); | 654 | } |
647 | } while (pmd++, addr = next, addr != end); | 655 | next = zap_pte_range(tlb, vma, pmd, addr, next, |
656 | zap_work, details); | ||
657 | } while (pmd++, addr = next, (addr != end && *zap_work > 0)); | ||
658 | |||
659 | return addr; | ||
648 | } | 660 | } |
649 | 661 | ||
650 | static inline void zap_pud_range(struct mmu_gather *tlb, | 662 | static inline unsigned long zap_pud_range(struct mmu_gather *tlb, |
651 | struct vm_area_struct *vma, pgd_t *pgd, | 663 | struct vm_area_struct *vma, pgd_t *pgd, |
652 | unsigned long addr, unsigned long end, | 664 | unsigned long addr, unsigned long end, |
653 | struct zap_details *details) | 665 | long *zap_work, struct zap_details *details) |
654 | { | 666 | { |
655 | pud_t *pud; | 667 | pud_t *pud; |
656 | unsigned long next; | 668 | unsigned long next; |
@@ -658,15 +670,21 @@ static inline void zap_pud_range(struct mmu_gather *tlb, | |||
658 | pud = pud_offset(pgd, addr); | 670 | pud = pud_offset(pgd, addr); |
659 | do { | 671 | do { |
660 | next = pud_addr_end(addr, end); | 672 | next = pud_addr_end(addr, end); |
661 | if (pud_none_or_clear_bad(pud)) | 673 | if (pud_none_or_clear_bad(pud)) { |
674 | (*zap_work)--; | ||
662 | continue; | 675 | continue; |
663 | zap_pmd_range(tlb, vma, pud, addr, next, details); | 676 | } |
664 | } while (pud++, addr = next, addr != end); | 677 | next = zap_pmd_range(tlb, vma, pud, addr, next, |
678 | zap_work, details); | ||
679 | } while (pud++, addr = next, (addr != end && *zap_work > 0)); | ||
680 | |||
681 | return addr; | ||
665 | } | 682 | } |
666 | 683 | ||
667 | static void unmap_page_range(struct mmu_gather *tlb, struct vm_area_struct *vma, | 684 | static unsigned long unmap_page_range(struct mmu_gather *tlb, |
685 | struct vm_area_struct *vma, | ||
668 | unsigned long addr, unsigned long end, | 686 | unsigned long addr, unsigned long end, |
669 | struct zap_details *details) | 687 | long *zap_work, struct zap_details *details) |
670 | { | 688 | { |
671 | pgd_t *pgd; | 689 | pgd_t *pgd; |
672 | unsigned long next; | 690 | unsigned long next; |
@@ -679,11 +697,16 @@ static void unmap_page_range(struct mmu_gather *tlb, struct vm_area_struct *vma, | |||
679 | pgd = pgd_offset(vma->vm_mm, addr); | 697 | pgd = pgd_offset(vma->vm_mm, addr); |
680 | do { | 698 | do { |
681 | next = pgd_addr_end(addr, end); | 699 | next = pgd_addr_end(addr, end); |
682 | if (pgd_none_or_clear_bad(pgd)) | 700 | if (pgd_none_or_clear_bad(pgd)) { |
701 | (*zap_work)--; | ||
683 | continue; | 702 | continue; |
684 | zap_pud_range(tlb, vma, pgd, addr, next, details); | 703 | } |
685 | } while (pgd++, addr = next, addr != end); | 704 | next = zap_pud_range(tlb, vma, pgd, addr, next, |
705 | zap_work, details); | ||
706 | } while (pgd++, addr = next, (addr != end && *zap_work > 0)); | ||
686 | tlb_end_vma(tlb, vma); | 707 | tlb_end_vma(tlb, vma); |
708 | |||
709 | return addr; | ||
687 | } | 710 | } |
688 | 711 | ||
689 | #ifdef CONFIG_PREEMPT | 712 | #ifdef CONFIG_PREEMPT |
@@ -724,7 +747,7 @@ unsigned long unmap_vmas(struct mmu_gather **tlbp, | |||
724 | unsigned long end_addr, unsigned long *nr_accounted, | 747 | unsigned long end_addr, unsigned long *nr_accounted, |
725 | struct zap_details *details) | 748 | struct zap_details *details) |
726 | { | 749 | { |
727 | unsigned long zap_bytes = ZAP_BLOCK_SIZE; | 750 | long zap_work = ZAP_BLOCK_SIZE; |
728 | unsigned long tlb_start = 0; /* For tlb_finish_mmu */ | 751 | unsigned long tlb_start = 0; /* For tlb_finish_mmu */ |
729 | int tlb_start_valid = 0; | 752 | int tlb_start_valid = 0; |
730 | unsigned long start = start_addr; | 753 | unsigned long start = start_addr; |
@@ -745,27 +768,25 @@ unsigned long unmap_vmas(struct mmu_gather **tlbp, | |||
745 | *nr_accounted += (end - start) >> PAGE_SHIFT; | 768 | *nr_accounted += (end - start) >> PAGE_SHIFT; |
746 | 769 | ||
747 | while (start != end) { | 770 | while (start != end) { |
748 | unsigned long block; | ||
749 | |||
750 | if (!tlb_start_valid) { | 771 | if (!tlb_start_valid) { |
751 | tlb_start = start; | 772 | tlb_start = start; |
752 | tlb_start_valid = 1; | 773 | tlb_start_valid = 1; |
753 | } | 774 | } |
754 | 775 | ||
755 | if (is_vm_hugetlb_page(vma)) { | 776 | if (unlikely(is_vm_hugetlb_page(vma))) { |
756 | block = end - start; | ||
757 | unmap_hugepage_range(vma, start, end); | 777 | unmap_hugepage_range(vma, start, end); |
758 | } else { | 778 | zap_work -= (end - start) / |
759 | block = min(zap_bytes, end - start); | 779 | (HPAGE_SIZE / PAGE_SIZE); |
760 | unmap_page_range(*tlbp, vma, start, | 780 | start = end; |
761 | start + block, details); | 781 | } else |
782 | start = unmap_page_range(*tlbp, vma, | ||
783 | start, end, &zap_work, details); | ||
784 | |||
785 | if (zap_work > 0) { | ||
786 | BUG_ON(start != end); | ||
787 | break; | ||
762 | } | 788 | } |
763 | 789 | ||
764 | start += block; | ||
765 | zap_bytes -= block; | ||
766 | if ((long)zap_bytes > 0) | ||
767 | continue; | ||
768 | |||
769 | tlb_finish_mmu(*tlbp, tlb_start, start); | 790 | tlb_finish_mmu(*tlbp, tlb_start, start); |
770 | 791 | ||
771 | if (need_resched() || | 792 | if (need_resched() || |
@@ -779,7 +800,7 @@ unsigned long unmap_vmas(struct mmu_gather **tlbp, | |||
779 | 800 | ||
780 | *tlbp = tlb_gather_mmu(vma->vm_mm, fullmm); | 801 | *tlbp = tlb_gather_mmu(vma->vm_mm, fullmm); |
781 | tlb_start_valid = 0; | 802 | tlb_start_valid = 0; |
782 | zap_bytes = ZAP_BLOCK_SIZE; | 803 | zap_work = ZAP_BLOCK_SIZE; |
783 | } | 804 | } |
784 | } | 805 | } |
785 | out: | 806 | out: |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 987225bdd661..3c5cf664abd2 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -732,9 +732,7 @@ buffered_rmqueue(struct zone *zone, int order, gfp_t gfp_flags) | |||
732 | } | 732 | } |
733 | local_irq_restore(flags); | 733 | local_irq_restore(flags); |
734 | put_cpu(); | 734 | put_cpu(); |
735 | } | 735 | } else { |
736 | |||
737 | if (page == NULL) { | ||
738 | spin_lock_irqsave(&zone->lock, flags); | 736 | spin_lock_irqsave(&zone->lock, flags); |
739 | page = __rmqueue(zone, order); | 737 | page = __rmqueue(zone, order); |
740 | spin_unlock_irqrestore(&zone->lock, flags); | 738 | spin_unlock_irqrestore(&zone->lock, flags); |
@@ -754,20 +752,25 @@ buffered_rmqueue(struct zone *zone, int order, gfp_t gfp_flags) | |||
754 | return page; | 752 | return page; |
755 | } | 753 | } |
756 | 754 | ||
755 | #define ALLOC_NO_WATERMARKS 0x01 /* don't check watermarks at all */ | ||
756 | #define ALLOC_HARDER 0x02 /* try to alloc harder */ | ||
757 | #define ALLOC_HIGH 0x04 /* __GFP_HIGH set */ | ||
758 | #define ALLOC_CPUSET 0x08 /* check for correct cpuset */ | ||
759 | |||
757 | /* | 760 | /* |
758 | * Return 1 if free pages are above 'mark'. This takes into account the order | 761 | * Return 1 if free pages are above 'mark'. This takes into account the order |
759 | * of the allocation. | 762 | * of the allocation. |
760 | */ | 763 | */ |
761 | int zone_watermark_ok(struct zone *z, int order, unsigned long mark, | 764 | int zone_watermark_ok(struct zone *z, int order, unsigned long mark, |
762 | int classzone_idx, int can_try_harder, gfp_t gfp_high) | 765 | int classzone_idx, int alloc_flags) |
763 | { | 766 | { |
764 | /* free_pages my go negative - that's OK */ | 767 | /* free_pages my go negative - that's OK */ |
765 | long min = mark, free_pages = z->free_pages - (1 << order) + 1; | 768 | long min = mark, free_pages = z->free_pages - (1 << order) + 1; |
766 | int o; | 769 | int o; |
767 | 770 | ||
768 | if (gfp_high) | 771 | if (alloc_flags & ALLOC_HIGH) |
769 | min -= min / 2; | 772 | min -= min / 2; |
770 | if (can_try_harder) | 773 | if (alloc_flags & ALLOC_HARDER) |
771 | min -= min / 4; | 774 | min -= min / 4; |
772 | 775 | ||
773 | if (free_pages <= min + z->lowmem_reserve[classzone_idx]) | 776 | if (free_pages <= min + z->lowmem_reserve[classzone_idx]) |
@@ -785,14 +788,40 @@ int zone_watermark_ok(struct zone *z, int order, unsigned long mark, | |||
785 | return 1; | 788 | return 1; |
786 | } | 789 | } |
787 | 790 | ||
788 | static inline int | 791 | /* |
789 | should_reclaim_zone(struct zone *z, gfp_t gfp_mask) | 792 | * get_page_from_freeliest goes through the zonelist trying to allocate |
793 | * a page. | ||
794 | */ | ||
795 | static struct page * | ||
796 | get_page_from_freelist(gfp_t gfp_mask, unsigned int order, | ||
797 | struct zonelist *zonelist, int alloc_flags) | ||
790 | { | 798 | { |
791 | if (!z->reclaim_pages) | 799 | struct zone **z = zonelist->zones; |
792 | return 0; | 800 | struct page *page = NULL; |
793 | if (gfp_mask & __GFP_NORECLAIM) | 801 | int classzone_idx = zone_idx(*z); |
794 | return 0; | 802 | |
795 | return 1; | 803 | /* |
804 | * Go through the zonelist once, looking for a zone with enough free. | ||
805 | * See also cpuset_zone_allowed() comment in kernel/cpuset.c. | ||
806 | */ | ||
807 | do { | ||
808 | if ((alloc_flags & ALLOC_CPUSET) && | ||
809 | !cpuset_zone_allowed(*z, gfp_mask)) | ||
810 | continue; | ||
811 | |||
812 | if (!(alloc_flags & ALLOC_NO_WATERMARKS)) { | ||
813 | if (!zone_watermark_ok(*z, order, (*z)->pages_low, | ||
814 | classzone_idx, alloc_flags)) | ||
815 | continue; | ||
816 | } | ||
817 | |||
818 | page = buffered_rmqueue(*z, order, gfp_mask); | ||
819 | if (page) { | ||
820 | zone_statistics(zonelist, *z); | ||
821 | break; | ||
822 | } | ||
823 | } while (*(++z) != NULL); | ||
824 | return page; | ||
796 | } | 825 | } |
797 | 826 | ||
798 | /* | 827 | /* |
@@ -803,105 +832,75 @@ __alloc_pages(gfp_t gfp_mask, unsigned int order, | |||
803 | struct zonelist *zonelist) | 832 | struct zonelist *zonelist) |
804 | { | 833 | { |
805 | const gfp_t wait = gfp_mask & __GFP_WAIT; | 834 | const gfp_t wait = gfp_mask & __GFP_WAIT; |
806 | struct zone **zones, *z; | 835 | struct zone **z; |
807 | struct page *page; | 836 | struct page *page; |
808 | struct reclaim_state reclaim_state; | 837 | struct reclaim_state reclaim_state; |
809 | struct task_struct *p = current; | 838 | struct task_struct *p = current; |
810 | int i; | ||
811 | int classzone_idx; | ||
812 | int do_retry; | 839 | int do_retry; |
813 | int can_try_harder; | 840 | int alloc_flags; |
814 | int did_some_progress; | 841 | int did_some_progress; |
815 | 842 | ||
816 | might_sleep_if(wait); | 843 | might_sleep_if(wait); |
817 | 844 | ||
818 | /* | 845 | z = zonelist->zones; /* the list of zones suitable for gfp_mask */ |
819 | * The caller may dip into page reserves a bit more if the caller | ||
820 | * cannot run direct reclaim, or is the caller has realtime scheduling | ||
821 | * policy | ||
822 | */ | ||
823 | can_try_harder = (unlikely(rt_task(p)) && !in_interrupt()) || !wait; | ||
824 | 846 | ||
825 | zones = zonelist->zones; /* the list of zones suitable for gfp_mask */ | 847 | if (unlikely(*z == NULL)) { |
826 | |||
827 | if (unlikely(zones[0] == NULL)) { | ||
828 | /* Should this ever happen?? */ | 848 | /* Should this ever happen?? */ |
829 | return NULL; | 849 | return NULL; |
830 | } | 850 | } |
851 | restart: | ||
852 | page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order, | ||
853 | zonelist, ALLOC_CPUSET); | ||
854 | if (page) | ||
855 | goto got_pg; | ||
831 | 856 | ||
832 | classzone_idx = zone_idx(zones[0]); | 857 | do |
858 | wakeup_kswapd(*z, order); | ||
859 | while (*(++z)); | ||
833 | 860 | ||
834 | restart: | ||
835 | /* | 861 | /* |
836 | * Go through the zonelist once, looking for a zone with enough free. | 862 | * OK, we're below the kswapd watermark and have kicked background |
837 | * See also cpuset_zone_allowed() comment in kernel/cpuset.c. | 863 | * reclaim. Now things get more complex, so set up alloc_flags according |
864 | * to how we want to proceed. | ||
865 | * | ||
866 | * The caller may dip into page reserves a bit more if the caller | ||
867 | * cannot run direct reclaim, or if the caller has realtime scheduling | ||
868 | * policy. | ||
838 | */ | 869 | */ |
839 | for (i = 0; (z = zones[i]) != NULL; i++) { | 870 | alloc_flags = 0; |
840 | int do_reclaim = should_reclaim_zone(z, gfp_mask); | 871 | if ((unlikely(rt_task(p)) && !in_interrupt()) || !wait) |
841 | 872 | alloc_flags |= ALLOC_HARDER; | |
842 | if (!cpuset_zone_allowed(z, __GFP_HARDWALL)) | 873 | if (gfp_mask & __GFP_HIGH) |
843 | continue; | 874 | alloc_flags |= ALLOC_HIGH; |
844 | 875 | if (wait) | |
845 | /* | 876 | alloc_flags |= ALLOC_CPUSET; |
846 | * If the zone is to attempt early page reclaim then this loop | ||
847 | * will try to reclaim pages and check the watermark a second | ||
848 | * time before giving up and falling back to the next zone. | ||
849 | */ | ||
850 | zone_reclaim_retry: | ||
851 | if (!zone_watermark_ok(z, order, z->pages_low, | ||
852 | classzone_idx, 0, 0)) { | ||
853 | if (!do_reclaim) | ||
854 | continue; | ||
855 | else { | ||
856 | zone_reclaim(z, gfp_mask, order); | ||
857 | /* Only try reclaim once */ | ||
858 | do_reclaim = 0; | ||
859 | goto zone_reclaim_retry; | ||
860 | } | ||
861 | } | ||
862 | |||
863 | page = buffered_rmqueue(z, order, gfp_mask); | ||
864 | if (page) | ||
865 | goto got_pg; | ||
866 | } | ||
867 | |||
868 | for (i = 0; (z = zones[i]) != NULL; i++) | ||
869 | wakeup_kswapd(z, order); | ||
870 | 877 | ||
871 | /* | 878 | /* |
872 | * Go through the zonelist again. Let __GFP_HIGH and allocations | 879 | * Go through the zonelist again. Let __GFP_HIGH and allocations |
873 | * coming from realtime tasks to go deeper into reserves | 880 | * coming from realtime tasks go deeper into reserves. |
874 | * | 881 | * |
875 | * This is the last chance, in general, before the goto nopage. | 882 | * This is the last chance, in general, before the goto nopage. |
876 | * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc. | 883 | * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc. |
877 | * See also cpuset_zone_allowed() comment in kernel/cpuset.c. | 884 | * See also cpuset_zone_allowed() comment in kernel/cpuset.c. |
878 | */ | 885 | */ |
879 | for (i = 0; (z = zones[i]) != NULL; i++) { | 886 | page = get_page_from_freelist(gfp_mask, order, zonelist, alloc_flags); |
880 | if (!zone_watermark_ok(z, order, z->pages_min, | 887 | if (page) |
881 | classzone_idx, can_try_harder, | 888 | goto got_pg; |
882 | gfp_mask & __GFP_HIGH)) | ||
883 | continue; | ||
884 | |||
885 | if (wait && !cpuset_zone_allowed(z, gfp_mask)) | ||
886 | continue; | ||
887 | |||
888 | page = buffered_rmqueue(z, order, gfp_mask); | ||
889 | if (page) | ||
890 | goto got_pg; | ||
891 | } | ||
892 | 889 | ||
893 | /* This allocation should allow future memory freeing. */ | 890 | /* This allocation should allow future memory freeing. */ |
894 | 891 | ||
895 | if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE))) | 892 | if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE))) |
896 | && !in_interrupt()) { | 893 | && !in_interrupt()) { |
897 | if (!(gfp_mask & __GFP_NOMEMALLOC)) { | 894 | if (!(gfp_mask & __GFP_NOMEMALLOC)) { |
895 | nofail_alloc: | ||
898 | /* go through the zonelist yet again, ignoring mins */ | 896 | /* go through the zonelist yet again, ignoring mins */ |
899 | for (i = 0; (z = zones[i]) != NULL; i++) { | 897 | page = get_page_from_freelist(gfp_mask, order, |
900 | if (!cpuset_zone_allowed(z, gfp_mask)) | 898 | zonelist, ALLOC_NO_WATERMARKS|ALLOC_CPUSET); |
901 | continue; | 899 | if (page) |
902 | page = buffered_rmqueue(z, order, gfp_mask); | 900 | goto got_pg; |
903 | if (page) | 901 | if (gfp_mask & __GFP_NOFAIL) { |
904 | goto got_pg; | 902 | blk_congestion_wait(WRITE, HZ/50); |
903 | goto nofail_alloc; | ||
905 | } | 904 | } |
906 | } | 905 | } |
907 | goto nopage; | 906 | goto nopage; |
@@ -919,7 +918,7 @@ rebalance: | |||
919 | reclaim_state.reclaimed_slab = 0; | 918 | reclaim_state.reclaimed_slab = 0; |
920 | p->reclaim_state = &reclaim_state; | 919 | p->reclaim_state = &reclaim_state; |
921 | 920 | ||
922 | did_some_progress = try_to_free_pages(zones, gfp_mask); | 921 | did_some_progress = try_to_free_pages(zonelist->zones, gfp_mask); |
923 | 922 | ||
924 | p->reclaim_state = NULL; | 923 | p->reclaim_state = NULL; |
925 | p->flags &= ~PF_MEMALLOC; | 924 | p->flags &= ~PF_MEMALLOC; |
@@ -927,19 +926,10 @@ rebalance: | |||
927 | cond_resched(); | 926 | cond_resched(); |
928 | 927 | ||
929 | if (likely(did_some_progress)) { | 928 | if (likely(did_some_progress)) { |
930 | for (i = 0; (z = zones[i]) != NULL; i++) { | 929 | page = get_page_from_freelist(gfp_mask, order, |
931 | if (!zone_watermark_ok(z, order, z->pages_min, | 930 | zonelist, alloc_flags); |
932 | classzone_idx, can_try_harder, | 931 | if (page) |
933 | gfp_mask & __GFP_HIGH)) | 932 | goto got_pg; |
934 | continue; | ||
935 | |||
936 | if (!cpuset_zone_allowed(z, gfp_mask)) | ||
937 | continue; | ||
938 | |||
939 | page = buffered_rmqueue(z, order, gfp_mask); | ||
940 | if (page) | ||
941 | goto got_pg; | ||
942 | } | ||
943 | } else if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) { | 933 | } else if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) { |
944 | /* | 934 | /* |
945 | * Go through the zonelist yet one more time, keep | 935 | * Go through the zonelist yet one more time, keep |
@@ -947,18 +937,10 @@ rebalance: | |||
947 | * a parallel oom killing, we must fail if we're still | 937 | * a parallel oom killing, we must fail if we're still |
948 | * under heavy pressure. | 938 | * under heavy pressure. |
949 | */ | 939 | */ |
950 | for (i = 0; (z = zones[i]) != NULL; i++) { | 940 | page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order, |
951 | if (!zone_watermark_ok(z, order, z->pages_high, | 941 | zonelist, ALLOC_CPUSET); |
952 | classzone_idx, 0, 0)) | 942 | if (page) |
953 | continue; | 943 | goto got_pg; |
954 | |||
955 | if (!cpuset_zone_allowed(z, __GFP_HARDWALL)) | ||
956 | continue; | ||
957 | |||
958 | page = buffered_rmqueue(z, order, gfp_mask); | ||
959 | if (page) | ||
960 | goto got_pg; | ||
961 | } | ||
962 | 944 | ||
963 | out_of_memory(gfp_mask, order); | 945 | out_of_memory(gfp_mask, order); |
964 | goto restart; | 946 | goto restart; |
@@ -991,9 +973,7 @@ nopage: | |||
991 | dump_stack(); | 973 | dump_stack(); |
992 | show_mem(); | 974 | show_mem(); |
993 | } | 975 | } |
994 | return NULL; | ||
995 | got_pg: | 976 | got_pg: |
996 | zone_statistics(zonelist, z); | ||
997 | return page; | 977 | return page; |
998 | } | 978 | } |
999 | 979 | ||
@@ -2417,13 +2397,18 @@ void setup_per_zone_pages_min(void) | |||
2417 | } | 2397 | } |
2418 | 2398 | ||
2419 | for_each_zone(zone) { | 2399 | for_each_zone(zone) { |
2400 | unsigned long tmp; | ||
2420 | spin_lock_irqsave(&zone->lru_lock, flags); | 2401 | spin_lock_irqsave(&zone->lru_lock, flags); |
2402 | tmp = (pages_min * zone->present_pages) / lowmem_pages; | ||
2421 | if (is_highmem(zone)) { | 2403 | if (is_highmem(zone)) { |
2422 | /* | 2404 | /* |
2423 | * Often, highmem doesn't need to reserve any pages. | 2405 | * __GFP_HIGH and PF_MEMALLOC allocations usually don't |
2424 | * But the pages_min/low/high values are also used for | 2406 | * need highmem pages, so cap pages_min to a small |
2425 | * batching up page reclaim activity so we need a | 2407 | * value here. |
2426 | * decent value here. | 2408 | * |
2409 | * The (pages_high-pages_low) and (pages_low-pages_min) | ||
2410 | * deltas controls asynch page reclaim, and so should | ||
2411 | * not be capped for highmem. | ||
2427 | */ | 2412 | */ |
2428 | int min_pages; | 2413 | int min_pages; |
2429 | 2414 | ||
@@ -2434,19 +2419,15 @@ void setup_per_zone_pages_min(void) | |||
2434 | min_pages = 128; | 2419 | min_pages = 128; |
2435 | zone->pages_min = min_pages; | 2420 | zone->pages_min = min_pages; |
2436 | } else { | 2421 | } else { |
2437 | /* if it's a lowmem zone, reserve a number of pages | 2422 | /* |
2423 | * If it's a lowmem zone, reserve a number of pages | ||
2438 | * proportionate to the zone's size. | 2424 | * proportionate to the zone's size. |
2439 | */ | 2425 | */ |
2440 | zone->pages_min = (pages_min * zone->present_pages) / | 2426 | zone->pages_min = tmp; |
2441 | lowmem_pages; | ||
2442 | } | 2427 | } |
2443 | 2428 | ||
2444 | /* | 2429 | zone->pages_low = zone->pages_min + tmp / 4; |
2445 | * When interpreting these watermarks, just keep in mind that: | 2430 | zone->pages_high = zone->pages_min + tmp / 2; |
2446 | * zone->pages_min == (zone->pages_min * 4) / 4; | ||
2447 | */ | ||
2448 | zone->pages_low = (zone->pages_min * 5) / 4; | ||
2449 | zone->pages_high = (zone->pages_min * 6) / 4; | ||
2450 | spin_unlock_irqrestore(&zone->lru_lock, flags); | 2431 | spin_unlock_irqrestore(&zone->lru_lock, flags); |
2451 | } | 2432 | } |
2452 | } | 2433 | } |
@@ -565,14 +565,29 @@ static void **dbg_userword(kmem_cache_t *cachep, void *objp) | |||
565 | #define BREAK_GFP_ORDER_LO 0 | 565 | #define BREAK_GFP_ORDER_LO 0 |
566 | static int slab_break_gfp_order = BREAK_GFP_ORDER_LO; | 566 | static int slab_break_gfp_order = BREAK_GFP_ORDER_LO; |
567 | 567 | ||
568 | /* Macros for storing/retrieving the cachep and or slab from the | 568 | /* Functions for storing/retrieving the cachep and or slab from the |
569 | * global 'mem_map'. These are used to find the slab an obj belongs to. | 569 | * global 'mem_map'. These are used to find the slab an obj belongs to. |
570 | * With kfree(), these are used to find the cache which an obj belongs to. | 570 | * With kfree(), these are used to find the cache which an obj belongs to. |
571 | */ | 571 | */ |
572 | #define SET_PAGE_CACHE(pg,x) ((pg)->lru.next = (struct list_head *)(x)) | 572 | static inline void page_set_cache(struct page *page, struct kmem_cache *cache) |
573 | #define GET_PAGE_CACHE(pg) ((kmem_cache_t *)(pg)->lru.next) | 573 | { |
574 | #define SET_PAGE_SLAB(pg,x) ((pg)->lru.prev = (struct list_head *)(x)) | 574 | page->lru.next = (struct list_head *)cache; |
575 | #define GET_PAGE_SLAB(pg) ((struct slab *)(pg)->lru.prev) | 575 | } |
576 | |||
577 | static inline struct kmem_cache *page_get_cache(struct page *page) | ||
578 | { | ||
579 | return (struct kmem_cache *)page->lru.next; | ||
580 | } | ||
581 | |||
582 | static inline void page_set_slab(struct page *page, struct slab *slab) | ||
583 | { | ||
584 | page->lru.prev = (struct list_head *)slab; | ||
585 | } | ||
586 | |||
587 | static inline struct slab *page_get_slab(struct page *page) | ||
588 | { | ||
589 | return (struct slab *)page->lru.prev; | ||
590 | } | ||
576 | 591 | ||
577 | /* These are the default caches for kmalloc. Custom caches can have other sizes. */ | 592 | /* These are the default caches for kmalloc. Custom caches can have other sizes. */ |
578 | struct cache_sizes malloc_sizes[] = { | 593 | struct cache_sizes malloc_sizes[] = { |
@@ -1190,11 +1205,7 @@ static void *kmem_getpages(kmem_cache_t *cachep, gfp_t flags, int nodeid) | |||
1190 | int i; | 1205 | int i; |
1191 | 1206 | ||
1192 | flags |= cachep->gfpflags; | 1207 | flags |= cachep->gfpflags; |
1193 | if (likely(nodeid == -1)) { | 1208 | page = alloc_pages_node(nodeid, flags, cachep->gfporder); |
1194 | page = alloc_pages(flags, cachep->gfporder); | ||
1195 | } else { | ||
1196 | page = alloc_pages_node(nodeid, flags, cachep->gfporder); | ||
1197 | } | ||
1198 | if (!page) | 1209 | if (!page) |
1199 | return NULL; | 1210 | return NULL; |
1200 | addr = page_address(page); | 1211 | addr = page_address(page); |
@@ -1368,7 +1379,7 @@ static void check_poison_obj(kmem_cache_t *cachep, void *objp) | |||
1368 | /* Print some data about the neighboring objects, if they | 1379 | /* Print some data about the neighboring objects, if they |
1369 | * exist: | 1380 | * exist: |
1370 | */ | 1381 | */ |
1371 | struct slab *slabp = GET_PAGE_SLAB(virt_to_page(objp)); | 1382 | struct slab *slabp = page_get_slab(virt_to_page(objp)); |
1372 | int objnr; | 1383 | int objnr; |
1373 | 1384 | ||
1374 | objnr = (objp-slabp->s_mem)/cachep->objsize; | 1385 | objnr = (objp-slabp->s_mem)/cachep->objsize; |
@@ -2138,8 +2149,8 @@ static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp) | |||
2138 | i = 1 << cachep->gfporder; | 2149 | i = 1 << cachep->gfporder; |
2139 | page = virt_to_page(objp); | 2150 | page = virt_to_page(objp); |
2140 | do { | 2151 | do { |
2141 | SET_PAGE_CACHE(page, cachep); | 2152 | page_set_cache(page, cachep); |
2142 | SET_PAGE_SLAB(page, slabp); | 2153 | page_set_slab(page, slabp); |
2143 | page++; | 2154 | page++; |
2144 | } while (--i); | 2155 | } while (--i); |
2145 | } | 2156 | } |
@@ -2269,14 +2280,14 @@ static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp, | |||
2269 | kfree_debugcheck(objp); | 2280 | kfree_debugcheck(objp); |
2270 | page = virt_to_page(objp); | 2281 | page = virt_to_page(objp); |
2271 | 2282 | ||
2272 | if (GET_PAGE_CACHE(page) != cachep) { | 2283 | if (page_get_cache(page) != cachep) { |
2273 | printk(KERN_ERR "mismatch in kmem_cache_free: expected cache %p, got %p\n", | 2284 | printk(KERN_ERR "mismatch in kmem_cache_free: expected cache %p, got %p\n", |
2274 | GET_PAGE_CACHE(page),cachep); | 2285 | page_get_cache(page),cachep); |
2275 | printk(KERN_ERR "%p is %s.\n", cachep, cachep->name); | 2286 | printk(KERN_ERR "%p is %s.\n", cachep, cachep->name); |
2276 | printk(KERN_ERR "%p is %s.\n", GET_PAGE_CACHE(page), GET_PAGE_CACHE(page)->name); | 2287 | printk(KERN_ERR "%p is %s.\n", page_get_cache(page), page_get_cache(page)->name); |
2277 | WARN_ON(1); | 2288 | WARN_ON(1); |
2278 | } | 2289 | } |
2279 | slabp = GET_PAGE_SLAB(page); | 2290 | slabp = page_get_slab(page); |
2280 | 2291 | ||
2281 | if (cachep->flags & SLAB_RED_ZONE) { | 2292 | if (cachep->flags & SLAB_RED_ZONE) { |
2282 | if (*dbg_redzone1(cachep, objp) != RED_ACTIVE || *dbg_redzone2(cachep, objp) != RED_ACTIVE) { | 2293 | if (*dbg_redzone1(cachep, objp) != RED_ACTIVE || *dbg_redzone2(cachep, objp) != RED_ACTIVE) { |
@@ -2628,7 +2639,7 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects, int n | |||
2628 | struct slab *slabp; | 2639 | struct slab *slabp; |
2629 | unsigned int objnr; | 2640 | unsigned int objnr; |
2630 | 2641 | ||
2631 | slabp = GET_PAGE_SLAB(virt_to_page(objp)); | 2642 | slabp = page_get_slab(virt_to_page(objp)); |
2632 | l3 = cachep->nodelists[node]; | 2643 | l3 = cachep->nodelists[node]; |
2633 | list_del(&slabp->list); | 2644 | list_del(&slabp->list); |
2634 | objnr = (objp - slabp->s_mem) / cachep->objsize; | 2645 | objnr = (objp - slabp->s_mem) / cachep->objsize; |
@@ -2744,7 +2755,7 @@ static inline void __cache_free(kmem_cache_t *cachep, void *objp) | |||
2744 | #ifdef CONFIG_NUMA | 2755 | #ifdef CONFIG_NUMA |
2745 | { | 2756 | { |
2746 | struct slab *slabp; | 2757 | struct slab *slabp; |
2747 | slabp = GET_PAGE_SLAB(virt_to_page(objp)); | 2758 | slabp = page_get_slab(virt_to_page(objp)); |
2748 | if (unlikely(slabp->nodeid != numa_node_id())) { | 2759 | if (unlikely(slabp->nodeid != numa_node_id())) { |
2749 | struct array_cache *alien = NULL; | 2760 | struct array_cache *alien = NULL; |
2750 | int nodeid = slabp->nodeid; | 2761 | int nodeid = slabp->nodeid; |
@@ -2830,7 +2841,7 @@ int fastcall kmem_ptr_validate(kmem_cache_t *cachep, void *ptr) | |||
2830 | page = virt_to_page(ptr); | 2841 | page = virt_to_page(ptr); |
2831 | if (unlikely(!PageSlab(page))) | 2842 | if (unlikely(!PageSlab(page))) |
2832 | goto out; | 2843 | goto out; |
2833 | if (unlikely(GET_PAGE_CACHE(page) != cachep)) | 2844 | if (unlikely(page_get_cache(page) != cachep)) |
2834 | goto out; | 2845 | goto out; |
2835 | return 1; | 2846 | return 1; |
2836 | out: | 2847 | out: |
@@ -3026,7 +3037,7 @@ void kfree(const void *objp) | |||
3026 | return; | 3037 | return; |
3027 | local_irq_save(flags); | 3038 | local_irq_save(flags); |
3028 | kfree_debugcheck(objp); | 3039 | kfree_debugcheck(objp); |
3029 | c = GET_PAGE_CACHE(virt_to_page(objp)); | 3040 | c = page_get_cache(virt_to_page(objp)); |
3030 | __cache_free(c, (void*)objp); | 3041 | __cache_free(c, (void*)objp); |
3031 | local_irq_restore(flags); | 3042 | local_irq_restore(flags); |
3032 | } | 3043 | } |
@@ -3596,7 +3607,7 @@ unsigned int ksize(const void *objp) | |||
3596 | if (unlikely(objp == NULL)) | 3607 | if (unlikely(objp == NULL)) |
3597 | return 0; | 3608 | return 0; |
3598 | 3609 | ||
3599 | return obj_reallen(GET_PAGE_CACHE(virt_to_page(objp))); | 3610 | return obj_reallen(page_get_cache(virt_to_page(objp))); |
3600 | } | 3611 | } |
3601 | 3612 | ||
3602 | 3613 | ||
diff --git a/mm/vmscan.c b/mm/vmscan.c index 135bf8ca96ee..28130541270f 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -1074,7 +1074,7 @@ loop_again: | |||
1074 | continue; | 1074 | continue; |
1075 | 1075 | ||
1076 | if (!zone_watermark_ok(zone, order, | 1076 | if (!zone_watermark_ok(zone, order, |
1077 | zone->pages_high, 0, 0, 0)) { | 1077 | zone->pages_high, 0, 0)) { |
1078 | end_zone = i; | 1078 | end_zone = i; |
1079 | goto scan; | 1079 | goto scan; |
1080 | } | 1080 | } |
@@ -1111,7 +1111,7 @@ scan: | |||
1111 | 1111 | ||
1112 | if (nr_pages == 0) { /* Not software suspend */ | 1112 | if (nr_pages == 0) { /* Not software suspend */ |
1113 | if (!zone_watermark_ok(zone, order, | 1113 | if (!zone_watermark_ok(zone, order, |
1114 | zone->pages_high, end_zone, 0, 0)) | 1114 | zone->pages_high, end_zone, 0)) |
1115 | all_zones_ok = 0; | 1115 | all_zones_ok = 0; |
1116 | } | 1116 | } |
1117 | zone->temp_priority = priority; | 1117 | zone->temp_priority = priority; |
@@ -1259,7 +1259,7 @@ void wakeup_kswapd(struct zone *zone, int order) | |||
1259 | return; | 1259 | return; |
1260 | 1260 | ||
1261 | pgdat = zone->zone_pgdat; | 1261 | pgdat = zone->zone_pgdat; |
1262 | if (zone_watermark_ok(zone, order, zone->pages_low, 0, 0, 0)) | 1262 | if (zone_watermark_ok(zone, order, zone->pages_low, 0, 0)) |
1263 | return; | 1263 | return; |
1264 | if (pgdat->kswapd_max_order < order) | 1264 | if (pgdat->kswapd_max_order < order) |
1265 | pgdat->kswapd_max_order = order; | 1265 | pgdat->kswapd_max_order = order; |
diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 8aaf74e64183..2f45fd2969d0 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc | |||
@@ -117,6 +117,8 @@ use strict; | |||
117 | # struct my_struct { | 117 | # struct my_struct { |
118 | # int a; | 118 | # int a; |
119 | # int b; | 119 | # int b; |
120 | # /* private: */ | ||
121 | # int c; | ||
120 | # }; | 122 | # }; |
121 | # | 123 | # |
122 | # All descriptions can be multiline, except the short function description. | 124 | # All descriptions can be multiline, except the short function description. |
@@ -1304,6 +1306,12 @@ sub dump_struct($$) { | |||
1304 | # ignore embedded structs or unions | 1306 | # ignore embedded structs or unions |
1305 | $members =~ s/{.*?}//g; | 1307 | $members =~ s/{.*?}//g; |
1306 | 1308 | ||
1309 | # ignore members marked private: | ||
1310 | $members =~ s/\/\*.*?private:.*?public:.*?\*\///gos; | ||
1311 | $members =~ s/\/\*.*?private:.*//gos; | ||
1312 | # strip comments: | ||
1313 | $members =~ s/\/\*.*?\*\///gos; | ||
1314 | |||
1307 | create_parameterlist($members, ';', $file); | 1315 | create_parameterlist($members, ';', $file); |
1308 | 1316 | ||
1309 | output_declaration($declaration_name, | 1317 | output_declaration($declaration_name, |
@@ -1329,6 +1337,7 @@ sub dump_enum($$) { | |||
1329 | my $x = shift; | 1337 | my $x = shift; |
1330 | my $file = shift; | 1338 | my $file = shift; |
1331 | 1339 | ||
1340 | $x =~ s@/\*.*?\*/@@gos; # strip comments. | ||
1332 | if ($x =~ /enum\s+(\w+)\s*{(.*)}/) { | 1341 | if ($x =~ /enum\s+(\w+)\s*{(.*)}/) { |
1333 | $declaration_name = $1; | 1342 | $declaration_name = $1; |
1334 | my $members = $2; | 1343 | my $members = $2; |
@@ -1365,6 +1374,7 @@ sub dump_typedef($$) { | |||
1365 | my $x = shift; | 1374 | my $x = shift; |
1366 | my $file = shift; | 1375 | my $file = shift; |
1367 | 1376 | ||
1377 | $x =~ s@/\*.*?\*/@@gos; # strip comments. | ||
1368 | while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) { | 1378 | while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) { |
1369 | $x =~ s/\(*.\)\s*;$/;/; | 1379 | $x =~ s/\(*.\)\s*;$/;/; |
1370 | $x =~ s/\[*.\]\s*;$/;/; | 1380 | $x =~ s/\[*.\]\s*;$/;/; |
@@ -1420,7 +1430,7 @@ sub create_parameterlist($$$) { | |||
1420 | $type = $arg; | 1430 | $type = $arg; |
1421 | $type =~ s/([^\(]+\(\*)$param/$1/; | 1431 | $type =~ s/([^\(]+\(\*)$param/$1/; |
1422 | push_parameter($param, $type, $file); | 1432 | push_parameter($param, $type, $file); |
1423 | } else { | 1433 | } elsif ($arg) { |
1424 | $arg =~ s/\s*:\s*/:/g; | 1434 | $arg =~ s/\s*:\s*/:/g; |
1425 | $arg =~ s/\s*\[/\[/g; | 1435 | $arg =~ s/\s*\[/\[/g; |
1426 | 1436 | ||
@@ -1628,7 +1638,6 @@ sub process_state3_type($$) { | |||
1628 | my $x = shift; | 1638 | my $x = shift; |
1629 | my $file = shift; | 1639 | my $file = shift; |
1630 | 1640 | ||
1631 | $x =~ s@/\*.*?\*/@@gos; # strip comments. | ||
1632 | $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's. | 1641 | $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's. |
1633 | $x =~ s@^\s+@@gos; # strip leading spaces | 1642 | $x =~ s@^\s+@@gos; # strip leading spaces |
1634 | $x =~ s@\s+$@@gos; # strip trailing spaces | 1643 | $x =~ s@\s+$@@gos; # strip trailing spaces |
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c index 7c835abd99bc..3f30c57676c1 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
48 | #include <linux/stddef.h> | 48 | #include <linux/stddef.h> |
49 | #include <linux/pm.h> | 49 | #include <linux/pm.h> |
50 | #include <linux/pm_legacy.h> | ||
50 | #include <linux/isapnp.h> | 51 | #include <linux/isapnp.h> |
51 | #include <linux/pnp.h> | 52 | #include <linux/pnp.h> |
52 | #include <linux/spinlock.h> | 53 | #include <linux/spinlock.h> |
diff --git a/sound/oss/cs4281/cs4281m.c b/sound/oss/cs4281/cs4281m.c index d0d3963e1b83..adc689649fe1 100644 --- a/sound/oss/cs4281/cs4281m.c +++ b/sound/oss/cs4281/cs4281m.c | |||
@@ -298,6 +298,7 @@ struct cs4281_state { | |||
298 | struct cs4281_pipeline pl[CS4281_NUMBER_OF_PIPELINES]; | 298 | struct cs4281_pipeline pl[CS4281_NUMBER_OF_PIPELINES]; |
299 | }; | 299 | }; |
300 | 300 | ||
301 | #include <linux/pm_legacy.h> | ||
301 | #include "cs4281pm-24.c" | 302 | #include "cs4281pm-24.c" |
302 | 303 | ||
303 | #if CSDEBUG | 304 | #if CSDEBUG |
diff --git a/sound/oss/maestro.c b/sound/oss/maestro.c index 3dce504e6d6d..3abd3541cbc7 100644 --- a/sound/oss/maestro.c +++ b/sound/oss/maestro.c | |||
@@ -231,6 +231,7 @@ | |||
231 | #include <asm/uaccess.h> | 231 | #include <asm/uaccess.h> |
232 | 232 | ||
233 | #include <linux/pm.h> | 233 | #include <linux/pm.h> |
234 | #include <linux/pm_legacy.h> | ||
234 | static int maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *d); | 235 | static int maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *d); |
235 | 236 | ||
236 | #include "maestro.h" | 237 | #include "maestro.h" |
diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c index 66970062eb36..0ce2c404a730 100644 --- a/sound/oss/nm256_audio.c +++ b/sound/oss/nm256_audio.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/pm.h> | 27 | #include <linux/pm.h> |
28 | #include <linux/pm_legacy.h> | ||
28 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
29 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
30 | #include "sound_config.h" | 31 | #include "sound_config.h" |
diff --git a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c index 2efbd865109b..cd41d0e4706a 100644 --- a/sound/oss/opl3sa2.c +++ b/sound/oss/opl3sa2.c | |||
@@ -70,6 +70,7 @@ | |||
70 | #include <linux/module.h> | 70 | #include <linux/module.h> |
71 | #include <linux/delay.h> | 71 | #include <linux/delay.h> |
72 | #include <linux/pm.h> | 72 | #include <linux/pm.h> |
73 | #include <linux/pm_legacy.h> | ||
73 | #include "sound_config.h" | 74 | #include "sound_config.h" |
74 | 75 | ||
75 | #include "ad1848.h" | 76 | #include "ad1848.h" |
@@ -138,7 +139,7 @@ typedef struct { | |||
138 | struct pnp_dev* pdev; | 139 | struct pnp_dev* pdev; |
139 | int activated; /* Whether said devices have been activated */ | 140 | int activated; /* Whether said devices have been activated */ |
140 | #endif | 141 | #endif |
141 | #ifdef CONFIG_PM | 142 | #ifdef CONFIG_PM_LEGACY |
142 | unsigned int in_suspend; | 143 | unsigned int in_suspend; |
143 | struct pm_dev *pmdev; | 144 | struct pm_dev *pmdev; |
144 | #endif | 145 | #endif |
@@ -341,7 +342,7 @@ static void opl3sa2_mixer_reset(opl3sa2_state_t* devc) | |||
341 | } | 342 | } |
342 | 343 | ||
343 | /* Currently only used for power management */ | 344 | /* Currently only used for power management */ |
344 | #ifdef CONFIG_PM | 345 | #ifdef CONFIG_PM_LEGACY |
345 | static void opl3sa2_mixer_restore(opl3sa2_state_t* devc) | 346 | static void opl3sa2_mixer_restore(opl3sa2_state_t* devc) |
346 | { | 347 | { |
347 | if (devc) { | 348 | if (devc) { |
@@ -354,7 +355,7 @@ static void opl3sa2_mixer_restore(opl3sa2_state_t* devc) | |||
354 | } | 355 | } |
355 | } | 356 | } |
356 | } | 357 | } |
357 | #endif | 358 | #endif /* CONFIG_PM_LEGACY */ |
358 | 359 | ||
359 | static inline void arg_to_vol_mono(unsigned int vol, int* value) | 360 | static inline void arg_to_vol_mono(unsigned int vol, int* value) |
360 | { | 361 | { |
@@ -831,7 +832,8 @@ static struct pnp_driver opl3sa2_driver = { | |||
831 | 832 | ||
832 | /* End of component functions */ | 833 | /* End of component functions */ |
833 | 834 | ||
834 | #ifdef CONFIG_PM | 835 | #ifdef CONFIG_PM_LEGACY |
836 | |||
835 | static DEFINE_SPINLOCK(opl3sa2_lock); | 837 | static DEFINE_SPINLOCK(opl3sa2_lock); |
836 | 838 | ||
837 | /* Power Management support functions */ | 839 | /* Power Management support functions */ |
@@ -906,7 +908,7 @@ static int opl3sa2_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *dat | |||
906 | } | 908 | } |
907 | return 0; | 909 | return 0; |
908 | } | 910 | } |
909 | #endif /* CONFIG_PM */ | 911 | #endif /* CONFIG_PM_LEGACY */ |
910 | 912 | ||
911 | /* | 913 | /* |
912 | * Install OPL3-SA2 based card(s). | 914 | * Install OPL3-SA2 based card(s). |
@@ -1019,12 +1021,12 @@ static int __init init_opl3sa2(void) | |||
1019 | 1021 | ||
1020 | /* ewww =) */ | 1022 | /* ewww =) */ |
1021 | opl3sa2_state[card].card = card; | 1023 | opl3sa2_state[card].card = card; |
1022 | #ifdef CONFIG_PM | 1024 | #ifdef CONFIG_PM_LEGACY |
1023 | /* register our power management capabilities */ | 1025 | /* register our power management capabilities */ |
1024 | opl3sa2_state[card].pmdev = pm_register(PM_ISA_DEV, card, opl3sa2_pm_callback); | 1026 | opl3sa2_state[card].pmdev = pm_register(PM_ISA_DEV, card, opl3sa2_pm_callback); |
1025 | if (opl3sa2_state[card].pmdev) | 1027 | if (opl3sa2_state[card].pmdev) |
1026 | opl3sa2_state[card].pmdev->data = &opl3sa2_state[card]; | 1028 | opl3sa2_state[card].pmdev->data = &opl3sa2_state[card]; |
1027 | #endif /* CONFIG_PM */ | 1029 | #endif /* CONFIG_PM_LEGACY */ |
1028 | 1030 | ||
1029 | /* | 1031 | /* |
1030 | * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and | 1032 | * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and |
@@ -1081,7 +1083,7 @@ static void __exit cleanup_opl3sa2(void) | |||
1081 | int card; | 1083 | int card; |
1082 | 1084 | ||
1083 | for(card = 0; card < opl3sa2_cards_num; card++) { | 1085 | for(card = 0; card < opl3sa2_cards_num; card++) { |
1084 | #ifdef CONFIG_PM | 1086 | #ifdef CONFIG_PM_LEGACY |
1085 | if (opl3sa2_state[card].pmdev) | 1087 | if (opl3sa2_state[card].pmdev) |
1086 | pm_unregister(opl3sa2_state[card].pmdev); | 1088 | pm_unregister(opl3sa2_state[card].pmdev); |
1087 | #endif | 1089 | #endif |