diff --git a/[refs] b/[refs]
index a94114cae945..60368c788508 100644
--- a/[refs]
+++ b/[refs]
@@ -1,2 +1,2 @@
---
-refs/heads/master: 2ba14a017a4ba8d2266316f481d4ad7400073d18
+refs/heads/master: 6561168cb442be8d2769dce663870b6a28573e16
diff --git a/trunk/Documentation/DocBook/videobook.tmpl b/trunk/Documentation/DocBook/videobook.tmpl
index b3d93ee27693..b629da33951d 100644
--- a/trunk/Documentation/DocBook/videobook.tmpl
+++ b/trunk/Documentation/DocBook/videobook.tmpl
@@ -96,6 +96,7 @@ static struct video_device my_radio
{
"My radio",
VID_TYPE_TUNER,
+ VID_HARDWARE_MYRADIO,
radio_open.
radio_close,
NULL, /* no read */
@@ -117,6 +118,13 @@ static struct video_device my_radio
indicates that the device can be tuned. Clearly our radio is going to have some
way to change channel so it is tuneable.
+
+ The VID_HARDWARE_ types are unique to each device. Numbers are assigned by
+ alan@redhat.com when device drivers are going to be released. Until then you
+ can pull a suitably large number out of your hat and use it. 10000 should be
+ safe for a very long time even allowing for the huge number of vendors
+ making new and different radio cards at the moment.
+
We declare an open and close routine, but we do not need read or write,
which are used to read and write video data to or from the card itself. As
@@ -836,6 +844,7 @@ static struct video_device my_camera
"My Camera",
VID_TYPE_OVERLAY|VID_TYPE_SCALES|\
VID_TYPE_CAPTURE|VID_TYPE_CHROMAKEY,
+ VID_HARDWARE_MYCAMERA,
camera_open.
camera_close,
camera_read, /* no read */
diff --git a/trunk/Documentation/RCU/RTFP.txt b/trunk/Documentation/RCU/RTFP.txt
index 39ad8f56783a..6221464d1a7e 100644
--- a/trunk/Documentation/RCU/RTFP.txt
+++ b/trunk/Documentation/RCU/RTFP.txt
@@ -9,8 +9,8 @@ The first thing resembling RCU was published in 1980, when Kung and Lehman
[Kung80] recommended use of a garbage collector to defer destruction
of nodes in a parallel binary search tree in order to simplify its
implementation. This works well in environments that have garbage
-collectors, but most production garbage collectors incur significant
-overhead.
+collectors, but current production garbage collectors incur significant
+read-side overhead.
In 1982, Manber and Ladner [Manber82,Manber84] recommended deferring
destruction until all threads running at that time have terminated, again
@@ -99,25 +99,16 @@ locking, reduces contention, reduces memory latency for readers, and
parallelizes pipeline stalls and memory latency for writers. However,
these techniques still impose significant read-side overhead in the
form of memory barriers. Researchers at Sun worked along similar lines
-in the same timeframe [HerlihyLM02]. These techniques can be thought
-of as inside-out reference counts, where the count is represented by the
-number of hazard pointers referencing a given data structure (rather than
-the more conventional counter field within the data structure itself).
-
-By the same token, RCU can be thought of as a "bulk reference count",
-where some form of reference counter covers all reference by a given CPU
-or thread during a set timeframe. This timeframe is related to, but
-not necessarily exactly the same as, an RCU grace period. In classic
-RCU, the reference counter is the per-CPU bit in the "bitmask" field,
-and each such bit covers all references that might have been made by
-the corresponding CPU during the prior grace period. Of course, RCU
-can be thought of in other terms as well.
+in the same timeframe [HerlihyLM02,HerlihyLMS03]. These techniques
+can be thought of as inside-out reference counts, where the count is
+represented by the number of hazard pointers referencing a given data
+structure (rather than the more conventional counter field within the
+data structure itself).
In 2003, the K42 group described how RCU could be used to create
-hot-pluggable implementations of operating-system functions [Appavoo03a].
-Later that year saw a paper describing an RCU implementation of System
-V IPC [Arcangeli03], and an introduction to RCU in Linux Journal
-[McKenney03a].
+hot-pluggable implementations of operating-system functions. Later that
+year saw a paper describing an RCU implementation of System V IPC
+[Arcangeli03], and an introduction to RCU in Linux Journal [McKenney03a].
2004 has seen a Linux-Journal article on use of RCU in dcache
[McKenney04a], a performance comparison of locking to RCU on several
@@ -126,19 +117,10 @@ number of operating-system kernels [PaulEdwardMcKenneyPhD], a paper
describing how to make RCU safe for soft-realtime applications [Sarma04c],
and a paper describing SELinux performance with RCU [JamesMorris04b].
-2005 brought further adaptation of RCU to realtime use, permitting
+2005 has seen further adaptation of RCU to realtime use, permitting
preemption of RCU realtime critical sections [PaulMcKenney05a,
PaulMcKenney05b].
-2006 saw the first best-paper award for an RCU paper [ThomasEHart2006a],
-as well as further work on efficient implementations of preemptible
-RCU [PaulEMcKenney2006b], but priority-boosting of RCU read-side critical
-sections proved elusive. An RCU implementation permitting general
-blocking in read-side critical sections appeared [PaulEMcKenney2006c],
-Robert Olsson described an RCU-protected trie-hash combination
-[RobertOlsson2006a].
-
-
Bibtex Entries
@article{Kung80
@@ -221,41 +203,6 @@ Bibtex Entries
,Address="New Orleans, LA"
}
-@conference{Pu95a,
-Author = "Calton Pu and Tito Autrey and Andrew Black and Charles Consel and
-Crispin Cowan and Jon Inouye and Lakshmi Kethana and Jonathan Walpole and
-Ke Zhang",
-Title = "Optimistic Incremental Specialization: Streamlining a Commercial
-Operating System",
-Booktitle = "15\textsuperscript{th} ACM Symposium on
-Operating Systems Principles (SOSP'95)",
-address = "Copper Mountain, CO",
-month="December",
-year="1995",
-pages="314-321",
-annotation="
- Uses a replugger, but with a flag to signal when people are
- using the resource at hand. Only one reader at a time.
-"
-}
-
-@conference{Cowan96a,
-Author = "Crispin Cowan and Tito Autrey and Charles Krasic and
-Calton Pu and Jonathan Walpole",
-Title = "Fast Concurrent Dynamic Linking for an Adaptive Operating System",
-Booktitle = "International Conference on Configurable Distributed Systems
-(ICCDS'96)",
-address = "Annapolis, MD",
-month="May",
-year="1996",
-pages="108",
-isbn="0-8186-7395-8",
-annotation="
- Uses a replugger, but with a counter to signal when people are
- using the resource at hand. Allows multiple readers.
-"
-}
-
@techreport{Slingwine95
,author="John D. Slingwine and Paul E. McKenney"
,title="Apparatus and Method for Achieving Reduced Overhead Mutual
@@ -365,49 +312,6 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
[Viewed June 23, 2004]"
}
-@conference{Michael02a
-,author="Maged M. Michael"
-,title="Safe Memory Reclamation for Dynamic Lock-Free Objects Using Atomic
-Reads and Writes"
-,Year="2002"
-,Month="August"
-,booktitle="{Proceedings of the 21\textsuperscript{st} Annual ACM
-Symposium on Principles of Distributed Computing}"
-,pages="21-30"
-,annotation="
- Each thread keeps an array of pointers to items that it is
- currently referencing. Sort of an inside-out garbage collection
- mechanism, but one that requires the accessing code to explicitly
- state its needs. Also requires read-side memory barriers on
- most architectures.
-"
-}
-
-@conference{Michael02b
-,author="Maged M. Michael"
-,title="High Performance Dynamic Lock-Free Hash Tables and List-Based Sets"
-,Year="2002"
-,Month="August"
-,booktitle="{Proceedings of the 14\textsuperscript{th} Annual ACM
-Symposium on Parallel
-Algorithms and Architecture}"
-,pages="73-82"
-,annotation="
- Like the title says...
-"
-}
-
-@InProceedings{HerlihyLM02
-,author={Maurice Herlihy and Victor Luchangco and Mark Moir}
-,title="The Repeat Offender Problem: A Mechanism for Supporting Dynamic-Sized,
-Lock-Free Data Structures"
-,booktitle={Proceedings of 16\textsuperscript{th} International
-Symposium on Distributed Computing}
-,year=2002
-,month="October"
-,pages="339-353"
-}
-
@article{Appavoo03a
,author="J. Appavoo and K. Hui and C. A. N. Soules and R. W. Wisniewski and
D. M. {Da Silva} and O. Krieger and M. A. Auslander and D. J. Edelsohn and
@@ -543,95 +447,3 @@ Oregon Health and Sciences University"
Realtime turns into making RCU yet more realtime friendly.
"
}
-
-@conference{ThomasEHart2006a
-,Author="Thomas E. Hart and Paul E. McKenney and Angela Demke Brown"
-,Title="Making Lockless Synchronization Fast: Performance Implications
-of Memory Reclamation"
-,Booktitle="20\textsuperscript{th} {IEEE} International Parallel and
-Distributed Processing Symposium"
-,month="April"
-,year="2006"
-,day="25-29"
-,address="Rhodes, Greece"
-,annotation="
- Compares QSBR (AKA "classic RCU"), HPBR, EBR, and lock-free
- reference counting.
-"
-}
-
-@Conference{PaulEMcKenney2006b
-,Author="Paul E. McKenney and Dipankar Sarma and Ingo Molnar and
-Suparna Bhattacharya"
-,Title="Extending RCU for Realtime and Embedded Workloads"
-,Booktitle="{Ottawa Linux Symposium}"
-,Month="July"
-,Year="2006"
-,pages="v2 123-138"
-,note="Available:
-\url{http://www.linuxsymposium.org/2006/view_abstract.php?content_key=184}
-\url{http://www.rdrop.com/users/paulmck/RCU/OLSrtRCU.2006.08.11a.pdf}
-[Viewed January 1, 2007]"
-,annotation="
- Described how to improve the -rt implementation of realtime RCU.
-"
-}
-
-@unpublished{PaulEMcKenney2006c
-,Author="Paul E. McKenney"
-,Title="Sleepable {RCU}"
-,month="October"
-,day="9"
-,year="2006"
-,note="Available:
-\url{http://lwn.net/Articles/202847/}
-Revised:
-\url{http://www.rdrop.com/users/paulmck/RCU/srcu.2007.01.14a.pdf}
-[Viewed August 21, 2006]"
-,annotation="
- LWN article introducing SRCU.
-"
-}
-
-@unpublished{RobertOlsson2006a
-,Author="Robert Olsson and Stefan Nilsson"
-,Title="{TRASH}: A dynamic {LC}-trie and hash data structure"
-,month="August"
-,day="18"
-,year="2006"
-,note="Available:
-\url{http://www.nada.kth.se/~snilsson/public/papers/trash/trash.pdf}
-[Viewed February 24, 2007]"
-,annotation="
- RCU-protected dynamic trie-hash combination.
-"
-}
-
-@unpublished{ThomasEHart2007a
-,Author="Thomas E. Hart and Paul E. McKenney and Angela Demke Brown and Jonathan Walpole"
-,Title="Performance of memory reclamation for lockless synchronization"
-,journal="J. Parallel Distrib. Comput."
-,year="2007"
-,note="To appear in J. Parallel Distrib. Comput.
- \url{doi=10.1016/j.jpdc.2007.04.010}"
-,annotation={
- Compares QSBR (AKA "classic RCU"), HPBR, EBR, and lock-free
- reference counting. Journal version of ThomasEHart2006a.
-}
-}
-
-@unpublished{PaulEMcKenney2007QRCUspin
-,Author="Paul E. McKenney"
-,Title="Using Promela and Spin to verify parallel algorithms"
-,month="August"
-,day="1"
-,year="2007"
-,note="Available:
-\url{http://lwn.net/Articles/243851/}
-[Viewed September 8, 2007]"
-,annotation="
- LWN article describing Promela and spin, and also using Oleg
- Nesterov's QRCU as an example (with Paul McKenney's fastpath).
-"
-}
-
diff --git a/trunk/Documentation/RCU/rcu.txt b/trunk/Documentation/RCU/rcu.txt
index 95821a29ae41..f84407cba816 100644
--- a/trunk/Documentation/RCU/rcu.txt
+++ b/trunk/Documentation/RCU/rcu.txt
@@ -36,14 +36,6 @@ o How can the updater tell when a grace period has completed
executed in user mode, or executed in the idle loop, we can
safely free up that item.
- Preemptible variants of RCU (CONFIG_PREEMPT_RCU) get the
- same effect, but require that the readers manipulate CPU-local
- counters. These counters allow limited types of blocking
- within RCU read-side critical sections. SRCU also uses
- CPU-local counters, and permits general blocking within
- RCU read-side critical sections. These two variants of
- RCU detect grace periods by sampling these counters.
-
o If I am running on a uniprocessor kernel, which can only do one
thing at a time, why should I wait for a grace period?
@@ -54,10 +46,7 @@ o How can I see where RCU is currently used in the Linux kernel?
Search for "rcu_read_lock", "rcu_read_unlock", "call_rcu",
"rcu_read_lock_bh", "rcu_read_unlock_bh", "call_rcu_bh",
"srcu_read_lock", "srcu_read_unlock", "synchronize_rcu",
- "synchronize_net", "synchronize_srcu", and the other RCU
- primitives. Or grab one of the cscope databases from:
-
- http://www.rdrop.com/users/paulmck/RCU/linuxusage/rculocktab.html
+ "synchronize_net", and "synchronize_srcu".
o What guidelines should I follow when writing code that uses RCU?
@@ -78,11 +67,7 @@ o I hear that RCU is patented? What is with that?
o I hear that RCU needs work in order to support realtime kernels?
- This work is largely completed. Realtime-friendly RCU can be
- enabled via the CONFIG_PREEMPT_RCU kernel configuration parameter.
- However, work is in progress for enabling priority boosting of
- preempted RCU read-side critical sections.This is needed if you
- have CPU-bound realtime threads.
+ Yes, work in progress.
o Where can I find more information on RCU?
diff --git a/trunk/Documentation/RCU/torture.txt b/trunk/Documentation/RCU/torture.txt
index 2967a65269d8..25a3c3f7d378 100644
--- a/trunk/Documentation/RCU/torture.txt
+++ b/trunk/Documentation/RCU/torture.txt
@@ -46,13 +46,12 @@ stat_interval The number of seconds between output of torture
shuffle_interval
The number of seconds to keep the test threads affinitied
- to a particular subset of the CPUs, defaults to 5 seconds.
- Used in conjunction with test_no_idle_hz.
+ to a particular subset of the CPUs. Used in conjunction
+ with test_no_idle_hz.
test_no_idle_hz Whether or not to test the ability of RCU to operate in
a kernel that disables the scheduling-clock interrupt to
idle CPUs. Boolean parameter, "1" to test, "0" otherwise.
- Defaults to omitting this test.
torture_type The type of RCU to test: "rcu" for the rcu_read_lock() API,
"rcu_sync" for rcu_read_lock() with synchronous reclamation,
@@ -83,6 +82,8 @@ be evident. ;-)
The entries are as follows:
+o "ggp": The number of counter flips (or batches) since boot.
+
o "rtc": The hexadecimal address of the structure currently visible
to readers.
@@ -116,8 +117,8 @@ o "Reader Pipe": Histogram of "ages" of structures seen by readers.
o "Reader Batch": Another histogram of "ages" of structures seen
by readers, but in terms of counter flips (or batches) rather
than in terms of grace periods. The legal number of non-zero
- entries is again two. The reason for this separate view is that
- it is sometimes easier to get the third entry to show up in the
+ entries is again two. The reason for this separate view is
+ that it is easier to get the third entry to show up in the
"Reader Batch" list than in the "Reader Pipe" list.
o "Free-Block Circulation": Shows the number of torture structures
diff --git a/trunk/Documentation/cpu-hotplug.txt b/trunk/Documentation/cpu-hotplug.txt
index fb94f5a71b68..a741f658a3c9 100644
--- a/trunk/Documentation/cpu-hotplug.txt
+++ b/trunk/Documentation/cpu-hotplug.txt
@@ -109,13 +109,12 @@ Never use anything other than cpumask_t to represent bitmap of CPUs.
for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask.
#include
- get_online_cpus() and put_online_cpus():
+ lock_cpu_hotplug() and unlock_cpu_hotplug():
-The above calls are used to inhibit cpu hotplug operations. While the
-cpu_hotplug.refcount is non zero, the cpu_online_map will not change.
-If you merely need to avoid cpus going away, you could also use
-preempt_disable() and preempt_enable() for those sections.
-Just remember the critical section cannot call any
+The above calls are used to inhibit cpu hotplug operations. While holding the
+cpucontrol mutex, cpu_online_map will not change. If you merely need to avoid
+cpus going away, you could also use preempt_disable() and preempt_enable()
+for those sections. Just remember the critical section cannot call any
function that can sleep or schedule this process away. The preempt_disable()
will work as long as stop_machine_run() is used to take a cpu down.
diff --git a/trunk/Documentation/dvb/bt8xx.txt b/trunk/Documentation/dvb/bt8xx.txt
index b7b1d1b1da46..ecb47adda063 100644
--- a/trunk/Documentation/dvb/bt8xx.txt
+++ b/trunk/Documentation/dvb/bt8xx.txt
@@ -78,18 +78,6 @@ Example:
For a full list of card ID's please see Documentation/video4linux/CARDLIST.bttv.
In case of further problems please subscribe and send questions to the mailing list: linux-dvb@linuxtv.org.
-2c) Probing the cards with broken PCI subsystem ID
---------------------------------------------------
-There are some TwinHan cards that the EEPROM has become corrupted for some
-reason. The cards do not have correct PCI subsystem ID. But we can force
-probing the cards with broken PCI subsystem ID
-
- $ echo 109e 0878 $subvendor $subdevice > \
- /sys/bus/pci/drivers/bt878/new_id
-
-109e: PCI_VENDOR_ID_BROOKTREE
-0878: PCI_DEVICE_ID_BROOKTREE_878
-
Authors: Richard Walker,
Jamie Honan,
Michael Hunold,
diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt
index 9b8291f4c211..20c4c8bac9d7 100644
--- a/trunk/Documentation/feature-removal-schedule.txt
+++ b/trunk/Documentation/feature-removal-schedule.txt
@@ -295,6 +295,16 @@ Who: linuxppc-dev@ozlabs.org
---------------------------
+What: mthca driver's MSI support
+When: January 2008
+Files: drivers/infiniband/hw/mthca/*.[ch]
+Why: All mthca hardware also supports MSI-X, which provides
+ strictly more functionality than MSI. So there is no point in
+ having both MSI-X and MSI support in the driver.
+Who: Roland Dreier
+
+---------------------------
+
What: sk98lin network driver
When: Feburary 2008
Why: In kernel tree version of driver is unmaintained. Sk98lin driver
diff --git a/trunk/Documentation/video4linux/CARDLIST.cx23885 b/trunk/Documentation/video4linux/CARDLIST.cx23885
index 0924e6e142c4..00cb646a4bde 100644
--- a/trunk/Documentation/video4linux/CARDLIST.cx23885
+++ b/trunk/Documentation/video4linux/CARDLIST.cx23885
@@ -1,7 +1,5 @@
0 -> UNKNOWN/GENERIC [0070:3400]
1 -> Hauppauge WinTV-HVR1800lp [0070:7600]
- 2 -> Hauppauge WinTV-HVR1800 [0070:7800,0070:7801,0070:7809]
+ 2 -> Hauppauge WinTV-HVR1800 [0070:7800,0070:7801]
3 -> Hauppauge WinTV-HVR1250 [0070:7911]
4 -> DViCO FusionHDTV5 Express [18ac:d500]
- 5 -> Hauppauge WinTV-HVR1500Q [0070:7790,0070:7797]
- 6 -> Hauppauge WinTV-HVR1500 [0070:7710,0070:7717]
diff --git a/trunk/Documentation/video4linux/CARDLIST.cx88 b/trunk/Documentation/video4linux/CARDLIST.cx88
index bc5593bd9704..82ac8250e978 100644
--- a/trunk/Documentation/video4linux/CARDLIST.cx88
+++ b/trunk/Documentation/video4linux/CARDLIST.cx88
@@ -56,4 +56,3 @@
55 -> Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM [c180:c980]
56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder [0070:9600,0070:9601,0070:9602]
57 -> ADS Tech Instant Video PCI [1421:0390]
- 58 -> Pinnacle PCTV HD 800i [11bd:0051]
diff --git a/trunk/Documentation/video4linux/CARDLIST.em28xx b/trunk/Documentation/video4linux/CARDLIST.em28xx
index 6a8469f2bcae..37f0e3cedf43 100644
--- a/trunk/Documentation/video4linux/CARDLIST.em28xx
+++ b/trunk/Documentation/video4linux/CARDLIST.em28xx
@@ -1,17 +1,14 @@
0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800]
- 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2750,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
+ 1 -> Unknown EM2820/2840 video grabber (em2820/em2840)
2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036]
3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208]
- 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201]
- 5 -> MSI VOX USB 2.0 (em2820/em2840)
+ 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200]
+ 5 -> MSI VOX USB 2.0 (em2820/em2840) [eb1a:2820]
6 -> Terratec Cinergy 200 USB (em2800)
7 -> Leadtek Winfast USB II (em2800)
8 -> Kworld USB2800 (em2800)
- 9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a]
- 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500]
- 11 -> Terratec Hybrid XS (em2880) [0ccd:0042]
+ 9 -> Pinnacle Dazzle DVC 90 (em2820/em2840) [2304:0207]
+ 10 -> Hauppauge WinTV HVR 900 (em2880)
+ 11 -> Terratec Hybrid XS (em2880)
12 -> Kworld PVR TV 2800 RF (em2820/em2840)
- 13 -> Terratec Prodigy XS (em2880) [0ccd:0047]
- 14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
- 15 -> V-Gear PocketTV (em2800)
- 16 -> Hauppauge WinTV HVR 950 (em2880) [2040:6513]
+ 13 -> Terratec Prodigy XS (em2880)
diff --git a/trunk/Documentation/video4linux/CARDLIST.ivtv b/trunk/Documentation/video4linux/CARDLIST.ivtv
index a019e27e42b3..ddd76a0eb100 100644
--- a/trunk/Documentation/video4linux/CARDLIST.ivtv
+++ b/trunk/Documentation/video4linux/CARDLIST.ivtv
@@ -16,9 +16,3 @@
16 -> GOTVIEW PCI DVD2 Deluxe [ffac:0600]
17 -> Yuan MPC622 [ff01:d998]
18 -> Digital Cowboy DCT-MTVP1 [1461:bfff]
-19 -> Yuan PG600V2/GotView PCI DVD Lite [ffab:0600,ffad:0600]
-20 -> Club3D ZAP-TV1x01 [ffab:0600]
-21 -> AverTV MCE 116 Plus [1461:c439]
-22 -> ASUS Falcon2 [1043:4b66,1043:462e,1043:4b2e]
-23 -> AverMedia PVR-150 Plus [1461:c035]
-24 -> AverMedia EZMaker PCI Deluxe [1461:c03f]
diff --git a/trunk/Documentation/video4linux/CARDLIST.saa7134 b/trunk/Documentation/video4linux/CARDLIST.saa7134
index 5d3b6b4d2515..a14545300e4c 100644
--- a/trunk/Documentation/video4linux/CARDLIST.saa7134
+++ b/trunk/Documentation/video4linux/CARDLIST.saa7134
@@ -80,7 +80,7 @@
79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)
80 -> ASUS Digimatrix TV [1043:0210]
81 -> Philips Tiger reference design [1131:2018]
- 82 -> MSI TV@Anywhere plus [1462:6231,1462:8624]
+ 82 -> MSI TV@Anywhere plus [1462:6231]
83 -> Terratec Cinergy 250 PCI TV [153b:1160]
84 -> LifeView FlyDVB Trio [5168:0319]
85 -> AverTV DVB-T 777 [1461:2c05,1461:2c05]
@@ -102,7 +102,7 @@
101 -> Pinnacle PCTV 310i [11bd:002f]
102 -> Avermedia AVerTV Studio 507 [1461:9715]
103 -> Compro Videomate DVB-T200A
-104 -> Hauppauge WinTV-HVR1110 DVB-T/Hybrid [0070:6700,0070:6701,0070:6702,0070:6703,0070:6704,0070:6705]
+104 -> Hauppauge WinTV-HVR1110 DVB-T/Hybrid [0070:6701]
105 -> Terratec Cinergy HT PCMCIA [153b:1172]
106 -> Encore ENLTV [1131:2342,1131:2341,3016:2344]
107 -> Encore ENLTV-FM [1131:230f]
@@ -116,16 +116,3 @@
115 -> Sabrent PCMCIA TV-PCB05 [0919:2003]
116 -> 10MOONS TM300 TV Card [1131:2304]
117 -> Avermedia Super 007 [1461:f01d]
-118 -> Beholder BeholdTV 401 [0000:4016]
-119 -> Beholder BeholdTV 403 [0000:4036]
-120 -> Beholder BeholdTV 403 FM [0000:4037]
-121 -> Beholder BeholdTV 405 [0000:4050]
-122 -> Beholder BeholdTV 405 FM [0000:4051]
-123 -> Beholder BeholdTV 407 [0000:4070]
-124 -> Beholder BeholdTV 407 FM [0000:4071]
-125 -> Beholder BeholdTV 409 [0000:4090]
-126 -> Beholder BeholdTV 505 FM/RDS [0000:5051,0000:505B,5ace:5050]
-127 -> Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM [0000:5071,0000:507B,5ace:5070,5ace:5090]
-128 -> Beholder BeholdTV Columbus TVFM [0000:5201]
-129 -> Beholder BeholdTV 607 / BeholdTV 609 [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093]
-130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193]
diff --git a/trunk/Documentation/video4linux/CARDLIST.tuner b/trunk/Documentation/video4linux/CARDLIST.tuner
index 0e2394695bb8..a88c02d23805 100644
--- a/trunk/Documentation/video4linux/CARDLIST.tuner
+++ b/trunk/Documentation/video4linux/CARDLIST.tuner
@@ -52,7 +52,7 @@ tuner=50 - TCL 2002N
tuner=51 - Philips PAL/SECAM_D (FM 1256 I-H3)
tuner=52 - Thomson DTT 7610 (ATSC/NTSC)
tuner=53 - Philips FQ1286
-tuner=54 - Philips/NXP TDA 8290/8295 + 8275/8275A/18271
+tuner=54 - tda8290+75
tuner=55 - TCL 2002MB
tuner=56 - Philips PAL/SECAM multi (FQ1216AME MK4)
tuner=57 - Philips FQ1236A MK4
@@ -69,8 +69,7 @@ tuner=67 - Philips TD1316 Hybrid Tuner
tuner=68 - Philips TUV1236D ATSC/NTSC dual in
tuner=69 - Tena TNF 5335 and similar models
tuner=70 - Samsung TCPN 2121P30A
-tuner=71 - Xceive xc2028/xc3028 tuner
+tuner=71 - Xceive xc3028
tuner=72 - Thomson FE6600
tuner=73 - Samsung TCPG 6121P30A
tuner=75 - Philips TEA5761 FM Radio
-tuner=76 - Xceive 5000 tuner
diff --git a/trunk/Documentation/video4linux/CARDLIST.usbvision b/trunk/Documentation/video4linux/CARDLIST.usbvision
index 0b72d3fee17e..3d6850ef0245 100644
--- a/trunk/Documentation/video4linux/CARDLIST.usbvision
+++ b/trunk/Documentation/video4linux/CARDLIST.usbvision
@@ -62,4 +62,3 @@
61 -> Pinnacle Studio Linx Video input cable (PAL) [2304:0301]
62 -> Pinnacle PCTV Bungee USB (PAL) FM [2304:0419]
63 -> Hauppauge WinTv-USB [2400:4200]
- 64 -> Pinnacle Studio PCTV USB (NTSC) FM V3 [2304:0113]
diff --git a/trunk/Documentation/video4linux/extract_xc3028.pl b/trunk/Documentation/video4linux/extract_xc3028.pl
deleted file mode 100644
index cced8ac5c543..000000000000
--- a/trunk/Documentation/video4linux/extract_xc3028.pl
+++ /dev/null
@@ -1,926 +0,0 @@
-#!/usr/bin/perl
-
-# Copyright (c) Mauro Carvalho Chehab
-# Released under GPLv2
-#
-# In order to use, you need to:
-# 1) Download the windows driver with something like:
-# wget http://www.steventoth.net/linux/xc5000/HVR-12x0-14x0-17x0_1_25_25271_WHQL.zip
-# 2) Extract the file hcw85bda.sys from the zip into the current dir:
-# unzip -j HVR-12x0-14x0-17x0_1_25_25271_WHQL.zip Driver85/hcw85bda.sys
-# 3) run the script:
-# ./extract_xc3028.pl
-# 4) copy the generated file:
-# cp xc3028-v27.fw /lib/firmware
-
-#use strict;
-use IO::Handle;
-
-my $debug=0;
-
-sub verify ($$)
-{
- my ($filename, $hash) = @_;
- my ($testhash);
-
- if (system("which md5sum > /dev/null 2>&1")) {
- die "This firmware requires the md5sum command - see http://www.gnu.org/software/coreutils/\n";
- }
-
- open(CMD, "md5sum ".$filename."|");
- $testhash = ;
- $testhash =~ /([a-zA-Z0-9]*)/;
- $testhash = $1;
- close CMD;
- die "Hash of extracted file does not match (found $testhash, expected $hash!\n" if ($testhash ne $hash);
-}
-
-sub get_hunk ($$)
-{
- my ($offset, $length) = @_;
- my ($chunklength, $buf, $rcount, $out);
-
- sysseek(INFILE, $offset, SEEK_SET);
- while ($length > 0) {
- # Calc chunk size
- $chunklength = 2048;
- $chunklength = $length if ($chunklength > $length);
-
- $rcount = sysread(INFILE, $buf, $chunklength);
- die "Ran out of data\n" if ($rcount != $chunklength);
- $out .= $buf;
- $length -= $rcount;
- }
- return $out;
-}
-
-sub write_le16($)
-{
- my $val = shift;
- my $msb = ($val >> 8) &0xff;
- my $lsb = $val & 0xff;
-
- syswrite(OUTFILE, chr($lsb).chr($msb));
-}
-
-sub write_le32($)
-{
- my $val = shift;
- my $l3 = ($val >> 24) & 0xff;
- my $l2 = ($val >> 16) & 0xff;
- my $l1 = ($val >> 8) & 0xff;
- my $l0 = $val & 0xff;
-
- syswrite(OUTFILE, chr($l0).chr($l1).chr($l2).chr($l3));
-}
-
-sub write_le64($$)
-{
- my $msb_val = shift;
- my $lsb_val = shift;
- my $l7 = ($msb_val >> 24) & 0xff;
- my $l6 = ($msb_val >> 16) & 0xff;
- my $l5 = ($msb_val >> 8) & 0xff;
- my $l4 = $msb_val & 0xff;
-
- my $l3 = ($lsb_val >> 24) & 0xff;
- my $l2 = ($lsb_val >> 16) & 0xff;
- my $l1 = ($lsb_val >> 8) & 0xff;
- my $l0 = $lsb_val & 0xff;
-
- syswrite(OUTFILE,
- chr($l0).chr($l1).chr($l2).chr($l3).
- chr($l4).chr($l5).chr($l6).chr($l7));
-}
-
-sub write_hunk($$)
-{
- my ($offset, $length) = @_;
- my $out = get_hunk($offset, $length);
-
- printf "(len %d) ",$length if ($debug);
-
- for (my $i=0;$i<$length;$i++) {
- printf "%02x ",ord(substr($out,$i,1)) if ($debug);
- }
- printf "\n" if ($debug);
-
- syswrite(OUTFILE, $out);
-}
-
-sub write_hunk_fix_endian($$)
-{
- my ($offset, $length) = @_;
- my $out = get_hunk($offset, $length);
-
- printf "(len_fix %d) ",$length if ($debug);
-
- for (my $i=0;$i<$length;$i++) {
- printf "%02x ",ord(substr($out,$i,1)) if ($debug);
- }
- printf "\n" if ($debug);
-
- my $i=0;
- while ($i<$length) {
- my $size = ord(substr($out,$i,1))*256+ord(substr($out,$i+1,1));
- syswrite(OUTFILE, substr($out,$i+1,1));
- syswrite(OUTFILE, substr($out,$i,1));
- $i+=2;
- if ($size>0 && $size <0x8000) {
- for (my $j=0;$j<$size;$j++) {
- syswrite(OUTFILE, substr($out,$j+$i,1));
- }
- $i+=$size;
- }
- }
-}
-
-sub main_firmware($$$$)
-{
- my $out;
- my $j=0;
- my $outfile = shift;
- my $name = shift;
- my $version = shift;
- my $nr_desc = shift;
-
- for ($j = length($name); $j <32; $j++) {
- $name = $name.chr(0);
-}
-
- open OUTFILE, ">$outfile";
- syswrite(OUTFILE, $name);
- write_le16($version);
- write_le16($nr_desc);
-
- #
- # Firmware 0, type: BASE FW F8MHZ (0x00000003), id: (0000000000000000), size: 8718
- #
-
- write_le32(0x00000003); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(8718); # Size
- write_hunk_fix_endian(813432, 8718);
-
- #
- # Firmware 1, type: BASE FW F8MHZ MTS (0x00000007), id: (0000000000000000), size: 8712
- #
-
- write_le32(0x00000007); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(8712); # Size
- write_hunk_fix_endian(822152, 8712);
-
- #
- # Firmware 2, type: BASE FW FM (0x00000401), id: (0000000000000000), size: 8562
- #
-
- write_le32(0x00000401); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(8562); # Size
- write_hunk_fix_endian(830872, 8562);
-
- #
- # Firmware 3, type: BASE FW FM INPUT1 (0x00000c01), id: (0000000000000000), size: 8576
- #
-
- write_le32(0x00000c01); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(8576); # Size
- write_hunk_fix_endian(839440, 8576);
-
- #
- # Firmware 4, type: BASE FW (0x00000001), id: (0000000000000000), size: 8706
- #
-
- write_le32(0x00000001); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(8706); # Size
- write_hunk_fix_endian(848024, 8706);
-
- #
- # Firmware 5, type: BASE FW MTS (0x00000005), id: (0000000000000000), size: 8682
- #
-
- write_le32(0x00000005); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(8682); # Size
- write_hunk_fix_endian(856736, 8682);
-
- #
- # Firmware 6, type: STD FW (0x00000000), id: PAL/BG A2/A (0000000100000007), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x00000001, 0x00000007); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(865424, 161);
-
- #
- # Firmware 7, type: STD FW MTS (0x00000004), id: PAL/BG A2/A (0000000100000007), size: 169
- #
-
- write_le32(0x00000004); # Type
- write_le64(0x00000001, 0x00000007); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(865592, 169);
-
- #
- # Firmware 8, type: STD FW (0x00000000), id: PAL/BG A2/B (0000000200000007), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x00000002, 0x00000007); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(865424, 161);
-
- #
- # Firmware 9, type: STD FW MTS (0x00000004), id: PAL/BG A2/B (0000000200000007), size: 169
- #
-
- write_le32(0x00000004); # Type
- write_le64(0x00000002, 0x00000007); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(865592, 169);
-
- #
- # Firmware 10, type: STD FW (0x00000000), id: PAL/BG NICAM/A (0000000400000007), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x00000004, 0x00000007); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(866112, 161);
-
- #
- # Firmware 11, type: STD FW MTS (0x00000004), id: PAL/BG NICAM/A (0000000400000007), size: 169
- #
-
- write_le32(0x00000004); # Type
- write_le64(0x00000004, 0x00000007); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(866280, 169);
-
- #
- # Firmware 12, type: STD FW (0x00000000), id: PAL/BG NICAM/B (0000000800000007), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x00000008, 0x00000007); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(866112, 161);
-
- #
- # Firmware 13, type: STD FW MTS (0x00000004), id: PAL/BG NICAM/B (0000000800000007), size: 169
- #
-
- write_le32(0x00000004); # Type
- write_le64(0x00000008, 0x00000007); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(866280, 169);
-
- #
- # Firmware 14, type: STD FW (0x00000000), id: PAL/DK A2 (00000003000000e0), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x00000003, 0x000000e0); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(866800, 161);
-
- #
- # Firmware 15, type: STD FW MTS (0x00000004), id: PAL/DK A2 (00000003000000e0), size: 169
- #
-
- write_le32(0x00000004); # Type
- write_le64(0x00000003, 0x000000e0); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(866968, 169);
-
- #
- # Firmware 16, type: STD FW (0x00000000), id: PAL/DK NICAM (0000000c000000e0), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x0000000c, 0x000000e0); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(867144, 161);
-
- #
- # Firmware 17, type: STD FW MTS (0x00000004), id: PAL/DK NICAM (0000000c000000e0), size: 169
- #
-
- write_le32(0x00000004); # Type
- write_le64(0x0000000c, 0x000000e0); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(867312, 169);
-
- #
- # Firmware 18, type: STD FW (0x00000000), id: SECAM/K1 (0000000000200000), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x00000000, 0x00200000); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(867488, 161);
-
- #
- # Firmware 19, type: STD FW MTS (0x00000004), id: SECAM/K1 (0000000000200000), size: 169
- #
-
- write_le32(0x00000004); # Type
- write_le64(0x00000000, 0x00200000); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(867656, 169);
-
- #
- # Firmware 20, type: STD FW (0x00000000), id: SECAM/K3 (0000000004000000), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x00000000, 0x04000000); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(867832, 161);
-
- #
- # Firmware 21, type: STD FW MTS (0x00000004), id: SECAM/K3 (0000000004000000), size: 169
- #
-
- write_le32(0x00000004); # Type
- write_le64(0x00000000, 0x04000000); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(868000, 169);
-
- #
- # Firmware 22, type: STD FW D2633 DTV6 ATSC (0x00010030), id: (0000000000000000), size: 149
- #
-
- write_le32(0x00010030); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(149); # Size
- write_hunk_fix_endian(868176, 149);
-
- #
- # Firmware 23, type: STD FW D2620 DTV6 QAM (0x00000068), id: (0000000000000000), size: 149
- #
-
- write_le32(0x00000068); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(149); # Size
- write_hunk_fix_endian(868336, 149);
-
- #
- # Firmware 24, type: STD FW D2633 DTV6 QAM (0x00000070), id: (0000000000000000), size: 149
- #
-
- write_le32(0x00000070); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(149); # Size
- write_hunk_fix_endian(868488, 149);
-
- #
- # Firmware 25, type: STD FW D2620 DTV7 (0x00000088), id: (0000000000000000), size: 149
- #
-
- write_le32(0x00000088); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(149); # Size
- write_hunk_fix_endian(868648, 149);
-
- #
- # Firmware 26, type: STD FW D2633 DTV7 (0x00000090), id: (0000000000000000), size: 149
- #
-
- write_le32(0x00000090); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(149); # Size
- write_hunk_fix_endian(868800, 149);
-
- #
- # Firmware 27, type: STD FW D2620 DTV78 (0x00000108), id: (0000000000000000), size: 149
- #
-
- write_le32(0x00000108); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(149); # Size
- write_hunk_fix_endian(868960, 149);
-
- #
- # Firmware 28, type: STD FW D2633 DTV78 (0x00000110), id: (0000000000000000), size: 149
- #
-
- write_le32(0x00000110); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(149); # Size
- write_hunk_fix_endian(869112, 149);
-
- #
- # Firmware 29, type: STD FW D2620 DTV8 (0x00000208), id: (0000000000000000), size: 149
- #
-
- write_le32(0x00000208); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(149); # Size
- write_hunk_fix_endian(868648, 149);
-
- #
- # Firmware 30, type: STD FW D2633 DTV8 (0x00000210), id: (0000000000000000), size: 149
- #
-
- write_le32(0x00000210); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(149); # Size
- write_hunk_fix_endian(868800, 149);
-
- #
- # Firmware 31, type: STD FW FM (0x00000400), id: (0000000000000000), size: 135
- #
-
- write_le32(0x00000400); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le32(135); # Size
- write_hunk_fix_endian(869584, 135);
-
- #
- # Firmware 32, type: STD FW (0x00000000), id: PAL/I (0000000000000010), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x00000000, 0x00000010); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(869728, 161);
-
- #
- # Firmware 33, type: STD FW MTS (0x00000004), id: PAL/I (0000000000000010), size: 169
- #
-
- write_le32(0x00000004); # Type
- write_le64(0x00000000, 0x00000010); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(869896, 169);
-
- #
- # Firmware 34, type: STD FW (0x00000000), id: SECAM/L AM (0000001000400000), size: 169
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x00000010, 0x00400000); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(870072, 169);
-
- #
- # Firmware 35, type: STD FW (0x00000000), id: SECAM/L NICAM (0000000c00400000), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x0000000c, 0x00400000); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(870248, 161);
-
- #
- # Firmware 36, type: STD FW (0x00000000), id: SECAM/Lc (0000000000800000), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x00000000, 0x00800000); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(870416, 161);
-
- #
- # Firmware 37, type: STD FW (0x00000000), id: NTSC/M Kr (0000000000008000), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x00000000, 0x00008000); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(870584, 161);
-
- #
- # Firmware 38, type: STD FW LCD (0x00001000), id: NTSC/M Kr (0000000000008000), size: 161
- #
-
- write_le32(0x00001000); # Type
- write_le64(0x00000000, 0x00008000); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(870752, 161);
-
- #
- # Firmware 39, type: STD FW LCD NOGD (0x00003000), id: NTSC/M Kr (0000000000008000), size: 161
- #
-
- write_le32(0x00003000); # Type
- write_le64(0x00000000, 0x00008000); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(870920, 161);
-
- #
- # Firmware 40, type: STD FW MTS (0x00000004), id: NTSC/M Kr (0000000000008000), size: 169
- #
-
- write_le32(0x00000004); # Type
- write_le64(0x00000000, 0x00008000); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(871088, 169);
-
- #
- # Firmware 41, type: STD FW (0x00000000), id: NTSC PAL/M PAL/N (000000000000b700), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x00000000, 0x0000b700); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(871264, 161);
-
- #
- # Firmware 42, type: STD FW LCD (0x00001000), id: NTSC PAL/M PAL/N (000000000000b700), size: 161
- #
-
- write_le32(0x00001000); # Type
- write_le64(0x00000000, 0x0000b700); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(871432, 161);
-
- #
- # Firmware 43, type: STD FW LCD NOGD (0x00003000), id: NTSC PAL/M PAL/N (000000000000b700), size: 161
- #
-
- write_le32(0x00003000); # Type
- write_le64(0x00000000, 0x0000b700); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(871600, 161);
-
- #
- # Firmware 44, type: STD FW (0x00000000), id: NTSC/M Jp (0000000000002000), size: 161
- #
-
- write_le32(0x00000000); # Type
- write_le64(0x00000000, 0x00002000); # ID
- write_le32(161); # Size
- write_hunk_fix_endian(871264, 161);
-
- #
- # Firmware 45, type: STD FW MTS (0x00000004), id: NTSC PAL/M PAL/N (000000000000b700), size: 169
- #
-
- write_le32(0x00000004); # Type
- write_le64(0x00000000, 0x0000b700); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(871936, 169);
-
- #
- # Firmware 46, type: STD FW MTS LCD (0x00001004), id: NTSC PAL/M PAL/N (000000000000b700), size: 169
- #
-
- write_le32(0x00001004); # Type
- write_le64(0x00000000, 0x0000b700); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(872112, 169);
-
- #
- # Firmware 47, type: STD FW MTS LCD NOGD (0x00003004), id: NTSC PAL/M PAL/N (000000000000b700), size: 169
- #
-
- write_le32(0x00003004); # Type
- write_le64(0x00000000, 0x0000b700); # ID
- write_le32(169); # Size
- write_hunk_fix_endian(872288, 169);
-
- #
- # Firmware 48, type: SCODE FW HAS IF (0x60000000), IF = 3.28 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(3280); # IF
- write_le32(192); # Size
- write_hunk(811896, 192);
-
- #
- # Firmware 49, type: SCODE FW HAS IF (0x60000000), IF = 3.30 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(3300); # IF
- write_le32(192); # Size
- write_hunk(813048, 192);
-
- #
- # Firmware 50, type: SCODE FW HAS IF (0x60000000), IF = 3.44 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(3440); # IF
- write_le32(192); # Size
- write_hunk(812280, 192);
-
- #
- # Firmware 51, type: SCODE FW HAS IF (0x60000000), IF = 3.46 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(3460); # IF
- write_le32(192); # Size
- write_hunk(812472, 192);
-
- #
- # Firmware 52, type: SCODE FW DTV6 ATSC OREN36 HAS IF (0x60210020), IF = 3.80 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60210020); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(3800); # IF
- write_le32(192); # Size
- write_hunk(809784, 192);
-
- #
- # Firmware 53, type: SCODE FW HAS IF (0x60000000), IF = 4.00 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(4000); # IF
- write_le32(192); # Size
- write_hunk(812088, 192);
-
- #
- # Firmware 54, type: SCODE FW DTV6 ATSC TOYOTA388 HAS IF (0x60410020), IF = 4.08 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60410020); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(4080); # IF
- write_le32(192); # Size
- write_hunk(809976, 192);
-
- #
- # Firmware 55, type: SCODE FW HAS IF (0x60000000), IF = 4.20 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(4200); # IF
- write_le32(192); # Size
- write_hunk(811704, 192);
-
- #
- # Firmware 56, type: SCODE FW MONO HAS IF (0x60008000), IF = 4.32 MHz id: NTSC/M Kr (0000000000008000), size: 192
- #
-
- write_le32(0x60008000); # Type
- write_le64(0x00000000, 0x00008000); # ID
- write_le16(4320); # IF
- write_le32(192); # Size
- write_hunk(808056, 192);
-
- #
- # Firmware 57, type: SCODE FW HAS IF (0x60000000), IF = 4.45 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(4450); # IF
- write_le32(192); # Size
- write_hunk(812664, 192);
-
- #
- # Firmware 58, type: SCODE FW HAS IF (0x60000000), IF = 4.50 MHz id: NTSC/M Jp (0000000000002000), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000000, 0x00002000); # ID
- write_le16(4500); # IF
- write_le32(192); # Size
- write_hunk(807672, 192);
-
- #
- # Firmware 59, type: SCODE FW LCD NOGD IF HAS IF (0x60023000), IF = 4.60 MHz id: NTSC/M Kr (0000000000008000), size: 192
- #
-
- write_le32(0x60023000); # Type
- write_le64(0x00000000, 0x00008000); # ID
- write_le16(4600); # IF
- write_le32(192); # Size
- write_hunk(807864, 192);
-
- #
- # Firmware 60, type: SCODE FW DTV78 ZARLINK456 HAS IF (0x62000100), IF = 4.76 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x62000100); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(4760); # IF
- write_le32(192); # Size
- write_hunk(807288, 192);
-
- #
- # Firmware 61, type: SCODE FW HAS IF (0x60000000), IF = 4.94 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(4940); # IF
- write_le32(192); # Size
- write_hunk(811512, 192);
-
- #
- # Firmware 62, type: SCODE FW DTV7 ZARLINK456 HAS IF (0x62000080), IF = 5.26 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x62000080); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(5260); # IF
- write_le32(192); # Size
- write_hunk(810552, 192);
-
- #
- # Firmware 63, type: SCODE FW MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
- #
-
- write_le32(0x60008000); # Type
- write_le64(0x00000008, 0x00000007); # ID
- write_le16(5320); # IF
- write_le32(192); # Size
- write_hunk(810744, 192);
-
- #
- # Firmware 64, type: SCODE FW DTV8 CHINA HAS IF (0x64000200), IF = 5.40 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x64000200); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(5400); # IF
- write_le32(192); # Size
- write_hunk(807096, 192);
-
- #
- # Firmware 65, type: SCODE FW DTV6 ATSC OREN538 HAS IF (0x60110020), IF = 5.58 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60110020); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(5580); # IF
- write_le32(192); # Size
- write_hunk(809592, 192);
-
- #
- # Firmware 66, type: SCODE FW HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2/B (0000000200000007), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000002, 0x00000007); # ID
- write_le16(5640); # IF
- write_le32(192); # Size
- write_hunk(808440, 192);
-
- #
- # Firmware 67, type: SCODE FW HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000008, 0x00000007); # ID
- write_le16(5740); # IF
- write_le32(192); # Size
- write_hunk(808632, 192);
-
- #
- # Firmware 68, type: SCODE FW DTV7 DIBCOM52 HAS IF (0x61000080), IF = 5.90 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x61000080); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(5900); # IF
- write_le32(192); # Size
- write_hunk(810360, 192);
-
- #
- # Firmware 69, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/I (0000000000000010), size: 192
- #
-
- write_le32(0x60008000); # Type
- write_le64(0x00000000, 0x00000010); # ID
- write_le16(6000); # IF
- write_le32(192); # Size
- write_hunk(808824, 192);
-
- #
- # Firmware 70, type: SCODE FW DTV6 QAM F6MHZ HAS IF (0x68000060), IF = 6.20 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x68000060); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(6200); # IF
- write_le32(192); # Size
- write_hunk(809400, 192);
-
- #
- # Firmware 71, type: SCODE FW HAS IF (0x60000000), IF = 6.24 MHz id: PAL/I (0000000000000010), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000000, 0x00000010); # ID
- write_le16(6240); # IF
- write_le32(192); # Size
- write_hunk(808248, 192);
-
- #
- # Firmware 72, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.32 MHz id: SECAM/K1 (0000000000200000), size: 192
- #
-
- write_le32(0x60008000); # Type
- write_le64(0x00000000, 0x00200000); # ID
- write_le16(6320); # IF
- write_le32(192); # Size
- write_hunk(811320, 192);
-
- #
- # Firmware 73, type: SCODE FW HAS IF (0x60000000), IF = 6.34 MHz id: SECAM/K1 (0000000000200000), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000000, 0x00200000); # ID
- write_le16(6340); # IF
- write_le32(192); # Size
- write_hunk(809208, 192);
-
- #
- # Firmware 74, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.50 MHz id: SECAM/K3 (0000000004000000), size: 192
- #
-
- write_le32(0x60008000); # Type
- write_le64(0x00000000, 0x04000000); # ID
- write_le16(6500); # IF
- write_le32(192); # Size
- write_hunk(811128, 192);
-
- #
- # Firmware 75, type: SCODE FW DTV6 ATSC ATI638 HAS IF (0x60090020), IF = 6.58 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60090020); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(6580); # IF
- write_le32(192); # Size
- write_hunk(807480, 192);
-
- #
- # Firmware 76, type: SCODE FW HAS IF (0x60000000), IF = 6.60 MHz id: PAL/DK A2 (00000003000000e0), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000003, 0x000000e0); # ID
- write_le16(6600); # IF
- write_le32(192); # Size
- write_hunk(809016, 192);
-
- #
- # Firmware 77, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.68 MHz id: PAL/DK A2 (00000003000000e0), size: 192
- #
-
- write_le32(0x60008000); # Type
- write_le64(0x00000003, 0x000000e0); # ID
- write_le16(6680); # IF
- write_le32(192); # Size
- write_hunk(810936, 192);
-
- #
- # Firmware 78, type: SCODE FW DTV6 ATSC TOYOTA794 HAS IF (0x60810020), IF = 8.14 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60810020); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(8140); # IF
- write_le32(192); # Size
- write_hunk(810168, 192);
-
- #
- # Firmware 79, type: SCODE FW HAS IF (0x60000000), IF = 8.20 MHz id: (0000000000000000), size: 192
- #
-
- write_le32(0x60000000); # Type
- write_le64(0x00000000, 0x00000000); # ID
- write_le16(8200); # IF
- write_le32(192); # Size
- write_hunk(812856, 192);
-}
-
-sub extract_firmware {
- my $sourcefile = "hcw85bda.sys";
- my $hash = "0e44dbf63bb0169d57446aec21881ff2";
- my $outfile = "xc3028-v27.fw";
- my $name = "xc2028 firmware";
- my $version = 519;
- my $nr_desc = 80;
- my $out;
-
- verify($sourcefile, $hash);
-
- open INFILE, "<$sourcefile";
- main_firmware($outfile, $name, $version, $nr_desc);
- close INFILE;
-}
-
-extract_firmware;
-printf "Firmwares generated.\n";
diff --git a/trunk/Documentation/video4linux/sn9c102.txt b/trunk/Documentation/video4linux/sn9c102.txt
index b26f5195af51..1ffad19ce891 100644
--- a/trunk/Documentation/video4linux/sn9c102.txt
+++ b/trunk/Documentation/video4linux/sn9c102.txt
@@ -568,7 +568,6 @@ the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'.
Many thanks to following persons for their contribute (listed in alphabetical
order):
-- David Anderson for the donation of a webcam;
- Luca Capello for the donation of a webcam;
- Philippe Coval for having helped testing the PAS202BCA image sensor;
- Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the
diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS
index 17524afa7475..2340cfb1e25d 100644
--- a/trunk/MAINTAINERS
+++ b/trunk/MAINTAINERS
@@ -2141,15 +2141,6 @@ L: isdn4linux@listserv.isdn4linux.de
W: http://www.melware.de
S: Maintained
-IVTV VIDEO4LINUX DRIVER
-P: Hans Verkuil
-M: hverkuil@xs4all.nl
-L: ivtv-devel@ivtvdriver.org
-L: ivtv-users@ivtvdriver.org
-L: video4linux-list@redhat.com
-W: http://www.ivtvdriver.org
-S: Maintained
-
JOURNALLING FLASH FILE SYSTEM V2 (JFFS2)
P: David Woodhouse
M: dwmw2@infradead.org
diff --git a/trunk/arch/arm/kernel/time.c b/trunk/arch/arm/kernel/time.c
index e59b5b84168d..f6f3689a86ee 100644
--- a/trunk/arch/arm/kernel/time.c
+++ b/trunk/arch/arm/kernel/time.c
@@ -79,6 +79,17 @@ static unsigned long dummy_gettimeoffset(void)
}
#endif
+/*
+ * An implementation of printk_clock() independent from
+ * sched_clock(). This avoids non-bootable kernels when
+ * printk_clock is enabled.
+ */
+unsigned long long printk_clock(void)
+{
+ return (unsigned long long)(jiffies - INITIAL_JIFFIES) *
+ (1000000000 / HZ);
+}
+
static unsigned long next_rtc_update;
/*
diff --git a/trunk/arch/ia64/kernel/setup.c b/trunk/arch/ia64/kernel/setup.c
index 86028c69861e..4ac2b1f1bd3b 100644
--- a/trunk/arch/ia64/kernel/setup.c
+++ b/trunk/arch/ia64/kernel/setup.c
@@ -71,6 +71,8 @@ unsigned long __per_cpu_offset[NR_CPUS];
EXPORT_SYMBOL(__per_cpu_offset);
#endif
+extern void ia64_setup_printk_clock(void);
+
DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info);
DEFINE_PER_CPU(unsigned long, local_per_cpu_offset);
unsigned long ia64_cycles_per_usec;
@@ -505,6 +507,8 @@ setup_arch (char **cmdline_p)
/* process SAL system table: */
ia64_sal_init(__va(efi.sal_systab));
+ ia64_setup_printk_clock();
+
#ifdef CONFIG_SMP
cpu_physical_id(0) = hard_smp_processor_id();
#endif
diff --git a/trunk/arch/ia64/kernel/time.c b/trunk/arch/ia64/kernel/time.c
index 3ab042720970..2bb84214e5f1 100644
--- a/trunk/arch/ia64/kernel/time.c
+++ b/trunk/arch/ia64/kernel/time.c
@@ -344,6 +344,33 @@ udelay (unsigned long usecs)
}
EXPORT_SYMBOL(udelay);
+static unsigned long long ia64_itc_printk_clock(void)
+{
+ if (ia64_get_kr(IA64_KR_PER_CPU_DATA))
+ return sched_clock();
+ return 0;
+}
+
+static unsigned long long ia64_default_printk_clock(void)
+{
+ return (unsigned long long)(jiffies_64 - INITIAL_JIFFIES) *
+ (1000000000/HZ);
+}
+
+unsigned long long (*ia64_printk_clock)(void) = &ia64_default_printk_clock;
+
+unsigned long long printk_clock(void)
+{
+ return ia64_printk_clock();
+}
+
+void __init
+ia64_setup_printk_clock(void)
+{
+ if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT))
+ ia64_printk_clock = ia64_itc_printk_clock;
+}
+
/* IA64 doesn't cache the timezone */
void update_vsyscall_tz(void)
{
diff --git a/trunk/arch/ia64/sn/kernel/setup.c b/trunk/arch/ia64/sn/kernel/setup.c
index bb1d24929640..1f38a3a68390 100644
--- a/trunk/arch/ia64/sn/kernel/setup.c
+++ b/trunk/arch/ia64/sn/kernel/setup.c
@@ -64,6 +64,7 @@ extern void sn_timer_init(void);
extern unsigned long last_time_offset;
extern void (*ia64_mark_idle) (int);
extern void snidle(int);
+extern unsigned long long (*ia64_printk_clock)(void);
unsigned long sn_rtc_cycles_per_second;
EXPORT_SYMBOL(sn_rtc_cycles_per_second);
@@ -359,6 +360,14 @@ sn_scan_pcdp(void)
static unsigned long sn2_rtc_initial;
+static unsigned long long ia64_sn2_printk_clock(void)
+{
+ unsigned long rtc_now = rtc_time();
+
+ return (rtc_now - sn2_rtc_initial) *
+ (1000000000 / sn_rtc_cycles_per_second);
+}
+
/**
* sn_setup - SN platform setup routine
* @cmdline_p: kernel command line
@@ -459,6 +468,8 @@ void __init sn_setup(char **cmdline_p)
platform_intr_list[ACPI_INTERRUPT_CPEI] = IA64_CPE_VECTOR;
+ ia64_printk_clock = ia64_sn2_printk_clock;
+
printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
/*
diff --git a/trunk/arch/mips/kernel/mips-mt-fpaff.c b/trunk/arch/mips/kernel/mips-mt-fpaff.c
index bb4f00c0cbe9..892665bb12b1 100644
--- a/trunk/arch/mips/kernel/mips-mt-fpaff.c
+++ b/trunk/arch/mips/kernel/mips-mt-fpaff.c
@@ -58,13 +58,13 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
return -EFAULT;
- get_online_cpus();
+ lock_cpu_hotplug();
read_lock(&tasklist_lock);
p = find_process_by_pid(pid);
if (!p) {
read_unlock(&tasklist_lock);
- put_online_cpus();
+ unlock_cpu_hotplug();
return -ESRCH;
}
@@ -106,7 +106,7 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
out_unlock:
put_task_struct(p);
- put_online_cpus();
+ unlock_cpu_hotplug();
return retval;
}
@@ -125,7 +125,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
if (len < real_len)
return -EINVAL;
- get_online_cpus();
+ lock_cpu_hotplug();
read_lock(&tasklist_lock);
retval = -ESRCH;
@@ -140,7 +140,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
out_unlock:
read_unlock(&tasklist_lock);
- put_online_cpus();
+ unlock_cpu_hotplug();
if (retval)
return retval;
if (copy_to_user(user_mask_ptr, &mask, real_len))
diff --git a/trunk/arch/powerpc/platforms/pseries/hotplug-cpu.c b/trunk/arch/powerpc/platforms/pseries/hotplug-cpu.c
index c4ad54e0f288..412e6b42986f 100644
--- a/trunk/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/trunk/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -153,7 +153,7 @@ static int pseries_add_processor(struct device_node *np)
for (i = 0; i < nthreads; i++)
cpu_set(i, tmp);
- cpu_maps_update_begin();
+ lock_cpu_hotplug();
BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map));
@@ -190,7 +190,7 @@ static int pseries_add_processor(struct device_node *np)
}
err = 0;
out_unlock:
- cpu_maps_update_done();
+ unlock_cpu_hotplug();
return err;
}
@@ -211,7 +211,7 @@ static void pseries_remove_processor(struct device_node *np)
nthreads = len / sizeof(u32);
- cpu_maps_update_begin();
+ lock_cpu_hotplug();
for (i = 0; i < nthreads; i++) {
for_each_present_cpu(cpu) {
if (get_hard_smp_processor_id(cpu) != intserv[i])
@@ -225,7 +225,7 @@ static void pseries_remove_processor(struct device_node *np)
printk(KERN_WARNING "Could not find cpu to remove "
"with physical id 0x%x\n", intserv[i]);
}
- cpu_maps_update_done();
+ unlock_cpu_hotplug();
}
static int pseries_smp_notifier(struct notifier_block *nb,
diff --git a/trunk/arch/powerpc/platforms/pseries/rtasd.c b/trunk/arch/powerpc/platforms/pseries/rtasd.c
index e3078ce41518..73401c820110 100644
--- a/trunk/arch/powerpc/platforms/pseries/rtasd.c
+++ b/trunk/arch/powerpc/platforms/pseries/rtasd.c
@@ -382,7 +382,7 @@ static void do_event_scan_all_cpus(long delay)
{
int cpu;
- get_online_cpus();
+ lock_cpu_hotplug();
cpu = first_cpu(cpu_online_map);
for (;;) {
set_cpus_allowed(current, cpumask_of_cpu(cpu));
@@ -390,15 +390,15 @@ static void do_event_scan_all_cpus(long delay)
set_cpus_allowed(current, CPU_MASK_ALL);
/* Drop hotplug lock, and sleep for the specified delay */
- put_online_cpus();
+ unlock_cpu_hotplug();
msleep_interruptible(delay);
- get_online_cpus();
+ lock_cpu_hotplug();
cpu = next_cpu(cpu, cpu_online_map);
if (cpu == NR_CPUS)
break;
}
- put_online_cpus();
+ unlock_cpu_hotplug();
}
static int rtasd(void *unused)
diff --git a/trunk/arch/x86/kernel/cpu/mtrr/main.c b/trunk/arch/x86/kernel/cpu/mtrr/main.c
index beb45c9c0835..3b20613325dc 100644
--- a/trunk/arch/x86/kernel/cpu/mtrr/main.c
+++ b/trunk/arch/x86/kernel/cpu/mtrr/main.c
@@ -349,7 +349,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
replace = -1;
/* No CPU hotplug when we change MTRR entries */
- get_online_cpus();
+ lock_cpu_hotplug();
/* Search for existing MTRR */
mutex_lock(&mtrr_mutex);
for (i = 0; i < num_var_ranges; ++i) {
@@ -405,7 +405,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
error = i;
out:
mutex_unlock(&mtrr_mutex);
- put_online_cpus();
+ unlock_cpu_hotplug();
return error;
}
@@ -495,7 +495,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
max = num_var_ranges;
/* No CPU hotplug when we change MTRR entries */
- get_online_cpus();
+ lock_cpu_hotplug();
mutex_lock(&mtrr_mutex);
if (reg < 0) {
/* Search for existing MTRR */
@@ -536,7 +536,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
error = reg;
out:
mutex_unlock(&mtrr_mutex);
- put_online_cpus();
+ unlock_cpu_hotplug();
return error;
}
/**
diff --git a/trunk/arch/x86/kernel/entry_64.S b/trunk/arch/x86/kernel/entry_64.S
index e70f3881d7e4..3a058bb16409 100644
--- a/trunk/arch/x86/kernel/entry_64.S
+++ b/trunk/arch/x86/kernel/entry_64.S
@@ -283,7 +283,7 @@ sysret_careful:
sysret_signal:
TRACE_IRQS_ON
sti
- testl $_TIF_DO_NOTIFY_MASK,%edx
+ testl $(_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY),%edx
jz 1f
/* Really a signal */
@@ -377,7 +377,7 @@ int_very_careful:
jmp int_restore_rest
int_signal:
- testl $_TIF_DO_NOTIFY_MASK,%edx
+ testl $(_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY),%edx
jz 1f
movq %rsp,%rdi # &ptregs -> arg1
xorl %esi,%esi # oldset -> arg2
@@ -603,7 +603,7 @@ retint_careful:
jmp retint_check
retint_signal:
- testl $_TIF_DO_NOTIFY_MASK,%edx
+ testl $(_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY),%edx
jz retint_swapgs
TRACE_IRQS_ON
sti
diff --git a/trunk/arch/x86/kernel/microcode.c b/trunk/arch/x86/kernel/microcode.c
index 40cfd5488719..09c315214a5e 100644
--- a/trunk/arch/x86/kernel/microcode.c
+++ b/trunk/arch/x86/kernel/microcode.c
@@ -436,7 +436,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
return -EINVAL;
}
- get_online_cpus();
+ lock_cpu_hotplug();
mutex_lock(µcode_mutex);
user_buffer = (void __user *) buf;
@@ -447,7 +447,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
ret = (ssize_t)len;
mutex_unlock(µcode_mutex);
- put_online_cpus();
+ unlock_cpu_hotplug();
return ret;
}
@@ -658,14 +658,14 @@ static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
old = current->cpus_allowed;
- get_online_cpus();
+ lock_cpu_hotplug();
set_cpus_allowed(current, cpumask_of_cpu(cpu));
mutex_lock(µcode_mutex);
if (uci->valid)
err = cpu_request_microcode(cpu);
mutex_unlock(µcode_mutex);
- put_online_cpus();
+ unlock_cpu_hotplug();
set_cpus_allowed(current, old);
}
if (err)
@@ -817,9 +817,9 @@ static int __init microcode_init (void)
return PTR_ERR(microcode_pdev);
}
- get_online_cpus();
+ lock_cpu_hotplug();
error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver);
- put_online_cpus();
+ unlock_cpu_hotplug();
if (error) {
microcode_dev_exit();
platform_device_unregister(microcode_pdev);
@@ -839,9 +839,9 @@ static void __exit microcode_exit (void)
unregister_hotcpu_notifier(&mc_cpu_notifier);
- get_online_cpus();
+ lock_cpu_hotplug();
sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
- put_online_cpus();
+ unlock_cpu_hotplug();
platform_device_unregister(microcode_pdev);
}
diff --git a/trunk/arch/x86/kernel/signal_32.c b/trunk/arch/x86/kernel/signal_32.c
index 20f29e4c1d33..9bdd83022f5f 100644
--- a/trunk/arch/x86/kernel/signal_32.c
+++ b/trunk/arch/x86/kernel/signal_32.c
@@ -658,9 +658,6 @@ void do_notify_resume(struct pt_regs *regs, void *_unused,
/* deal with pending signal delivery */
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
do_signal(regs);
-
- if (thread_info_flags & _TIF_HRTICK_RESCHED)
- hrtick_resched();
clear_thread_flag(TIF_IRET);
}
diff --git a/trunk/arch/x86/kernel/signal_64.c b/trunk/arch/x86/kernel/signal_64.c
index 38d806467c0f..ab086b0357fc 100644
--- a/trunk/arch/x86/kernel/signal_64.c
+++ b/trunk/arch/x86/kernel/signal_64.c
@@ -480,9 +480,6 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
/* deal with pending signal delivery */
if (thread_info_flags & (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK))
do_signal(regs);
-
- if (thread_info_flags & _TIF_HRTICK_RESCHED)
- hrtick_resched();
}
void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
diff --git a/trunk/arch/x86/kernel/stacktrace.c b/trunk/arch/x86/kernel/stacktrace.c
index 55771fd7e545..6fa6cf036c70 100644
--- a/trunk/arch/x86/kernel/stacktrace.c
+++ b/trunk/arch/x86/kernel/stacktrace.c
@@ -33,19 +33,6 @@ static void save_stack_address(void *data, unsigned long addr)
trace->entries[trace->nr_entries++] = addr;
}
-static void save_stack_address_nosched(void *data, unsigned long addr)
-{
- struct stack_trace *trace = (struct stack_trace *)data;
- if (in_sched_functions(addr))
- return;
- if (trace->skip > 0) {
- trace->skip--;
- return;
- }
- if (trace->nr_entries < trace->max_entries)
- trace->entries[trace->nr_entries++] = addr;
-}
-
static const struct stacktrace_ops save_stack_ops = {
.warning = save_stack_warning,
.warning_symbol = save_stack_warning_symbol,
@@ -53,13 +40,6 @@ static const struct stacktrace_ops save_stack_ops = {
.address = save_stack_address,
};
-static const struct stacktrace_ops save_stack_ops_nosched = {
- .warning = save_stack_warning,
- .warning_symbol = save_stack_warning_symbol,
- .stack = save_stack_stack,
- .address = save_stack_address_nosched,
-};
-
/*
* Save stack-backtrace addresses into a stack_trace buffer.
*/
@@ -70,10 +50,3 @@ void save_stack_trace(struct stack_trace *trace)
trace->entries[trace->nr_entries++] = ULONG_MAX;
}
EXPORT_SYMBOL(save_stack_trace);
-
-void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
-{
- dump_trace(tsk, NULL, NULL, &save_stack_ops_nosched, trace);
- if (trace->nr_entries < trace->max_entries)
- trace->entries[trace->nr_entries++] = ULONG_MAX;
-}
diff --git a/trunk/drivers/ata/Kconfig b/trunk/drivers/ata/Kconfig
index 2478cca653de..ba63619ae5df 100644
--- a/trunk/drivers/ata/Kconfig
+++ b/trunk/drivers/ata/Kconfig
@@ -459,15 +459,6 @@ config PATA_NETCELL
If unsure, say N.
-config PATA_NINJA32
- tristate "Ninja32/Delkin Cardbus ATA support (Experimental)"
- depends on PCI && EXPERIMENTAL
- help
- This option enables support for the Ninja32, Delkin and
- possibly other brands of Cardbus ATA adapter
-
- If unsure, say N.
-
config PATA_NS87410
tristate "Nat Semi NS87410 PATA support (Experimental)"
depends on PCI && EXPERIMENTAL
diff --git a/trunk/drivers/ata/Makefile b/trunk/drivers/ata/Makefile
index 82550c16818c..b13feb2c5dae 100644
--- a/trunk/drivers/ata/Makefile
+++ b/trunk/drivers/ata/Makefile
@@ -41,7 +41,6 @@ obj-$(CONFIG_PATA_IT821X) += pata_it821x.o
obj-$(CONFIG_PATA_IT8213) += pata_it8213.o
obj-$(CONFIG_PATA_JMICRON) += pata_jmicron.o
obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o
-obj-$(CONFIG_PATA_NINJA32) += pata_ninja32.o
obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o
obj-$(CONFIG_PATA_NS87415) += pata_ns87415.o
obj-$(CONFIG_PATA_OPTI) += pata_opti.o
diff --git a/trunk/drivers/ata/ahci.c b/trunk/drivers/ata/ahci.c
index 6f089b899a1a..54f38c21dd95 100644
--- a/trunk/drivers/ata/ahci.c
+++ b/trunk/drivers/ata/ahci.c
@@ -198,18 +198,18 @@ enum {
};
struct ahci_cmd_hdr {
- __le32 opts;
- __le32 status;
- __le32 tbl_addr;
- __le32 tbl_addr_hi;
- __le32 reserved[4];
+ u32 opts;
+ u32 status;
+ u32 tbl_addr;
+ u32 tbl_addr_hi;
+ u32 reserved[4];
};
struct ahci_sg {
- __le32 addr;
- __le32 addr_hi;
- __le32 reserved;
- __le32 flags_size;
+ u32 addr;
+ u32 addr_hi;
+ u32 reserved;
+ u32 flags_size;
};
struct ahci_host_priv {
@@ -597,20 +597,6 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap)
return __ahci_port_base(ap->host, ap->port_no);
}
-static void ahci_enable_ahci(void __iomem *mmio)
-{
- u32 tmp;
-
- /* turn on AHCI_EN */
- tmp = readl(mmio + HOST_CTL);
- if (!(tmp & HOST_AHCI_EN)) {
- tmp |= HOST_AHCI_EN;
- writel(tmp, mmio + HOST_CTL);
- tmp = readl(mmio + HOST_CTL); /* flush && sanity check */
- WARN_ON(!(tmp & HOST_AHCI_EN));
- }
-}
-
/**
* ahci_save_initial_config - Save and fixup initial config values
* @pdev: target PCI device
@@ -633,9 +619,6 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
u32 cap, port_map;
int i;
- /* make sure AHCI mode is enabled before accessing CAP */
- ahci_enable_ahci(mmio);
-
/* Values prefixed with saved_ are written back to host after
* reset. Values without are used for driver operation.
*/
@@ -1053,17 +1036,19 @@ static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
static int ahci_reset_controller(struct ata_host *host)
{
struct pci_dev *pdev = to_pci_dev(host->dev);
- struct ahci_host_priv *hpriv = host->private_data;
void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
u32 tmp;
/* we must be in AHCI mode, before using anything
* AHCI-specific, such as HOST_RESET.
*/
- ahci_enable_ahci(mmio);
+ tmp = readl(mmio + HOST_CTL);
+ if (!(tmp & HOST_AHCI_EN)) {
+ tmp |= HOST_AHCI_EN;
+ writel(tmp, mmio + HOST_CTL);
+ }
/* global controller reset */
- tmp = readl(mmio + HOST_CTL);
if ((tmp & HOST_RESET) == 0) {
writel(tmp | HOST_RESET, mmio + HOST_CTL);
readl(mmio + HOST_CTL); /* flush */
@@ -1082,7 +1067,8 @@ static int ahci_reset_controller(struct ata_host *host)
}
/* turn on AHCI mode */
- ahci_enable_ahci(mmio);
+ writel(HOST_AHCI_EN, mmio + HOST_CTL);
+ (void) readl(mmio + HOST_CTL); /* flush */
/* some registers might be cleared on reset. restore initial values */
ahci_restore_initial_config(host);
@@ -1092,10 +1078,8 @@ static int ahci_reset_controller(struct ata_host *host)
/* configure PCS */
pci_read_config_word(pdev, 0x92, &tmp16);
- if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
- tmp16 |= hpriv->port_map;
- pci_write_config_word(pdev, 0x92, tmp16);
- }
+ tmp16 |= 0xf;
+ pci_write_config_word(pdev, 0x92, tmp16);
}
return 0;
@@ -1496,31 +1480,35 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
{
struct scatterlist *sg;
- struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
- unsigned int si;
+ struct ahci_sg *ahci_sg;
+ unsigned int n_sg = 0;
VPRINTK("ENTER\n");
/*
* Next, the S/G list.
*/
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
+ ata_for_each_sg(sg, qc) {
dma_addr_t addr = sg_dma_address(sg);
u32 sg_len = sg_dma_len(sg);
- ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
- ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
- ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);
+ ahci_sg->addr = cpu_to_le32(addr & 0xffffffff);
+ ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
+ ahci_sg->flags_size = cpu_to_le32(sg_len - 1);
+
+ ahci_sg++;
+ n_sg++;
}
- return si;
+ return n_sg;
}
static void ahci_qc_prep(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct ahci_port_priv *pp = ap->private_data;
- int is_atapi = ata_is_atapi(qc->tf.protocol);
+ int is_atapi = is_atapi_taskfile(&qc->tf);
void *cmd_tbl;
u32 opts;
const u32 cmd_fis_len = 5; /* five dwords */
diff --git a/trunk/drivers/ata/ata_generic.c b/trunk/drivers/ata/ata_generic.c
index 20534202fc79..90329982bef7 100644
--- a/trunk/drivers/ata/ata_generic.c
+++ b/trunk/drivers/ata/ata_generic.c
@@ -26,7 +26,7 @@
#include
#define DRV_NAME "ata_generic"
-#define DRV_VERSION "0.2.15"
+#define DRV_VERSION "0.2.13"
/*
* A generic parallel ATA driver using libata
@@ -48,47 +48,27 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
struct ata_port *ap = link->ap;
int dma_enabled = 0;
struct ata_device *dev;
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
/* Bits 5 and 6 indicate if DMA is active on master/slave */
if (ap->ioaddr.bmdma_addr)
dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
- if (pdev->vendor == PCI_VENDOR_ID_CENATEK)
- dma_enabled = 0xFF;
-
ata_link_for_each_dev(dev, link) {
- if (!ata_dev_enabled(dev))
- continue;
-
- /* We don't really care */
- dev->pio_mode = XFER_PIO_0;
- dev->dma_mode = XFER_MW_DMA_0;
- /* We do need the right mode information for DMA or PIO
- and this comes from the current configuration flags */
- if (dma_enabled & (1 << (5 + dev->devno))) {
- unsigned int xfer_mask = ata_id_xfermask(dev->id);
- const char *name;
-
- if (xfer_mask & (ATA_MASK_MWDMA | ATA_MASK_UDMA))
- name = ata_mode_string(xfer_mask);
- else {
- /* SWDMA perhaps? */
- name = "DMA";
- xfer_mask |= ata_xfer_mode2mask(XFER_MW_DMA_0);
+ if (ata_dev_enabled(dev)) {
+ /* We don't really care */
+ dev->pio_mode = XFER_PIO_0;
+ dev->dma_mode = XFER_MW_DMA_0;
+ /* We do need the right mode information for DMA or PIO
+ and this comes from the current configuration flags */
+ if (dma_enabled & (1 << (5 + dev->devno))) {
+ ata_id_to_dma_mode(dev, XFER_MW_DMA_0);
+ dev->flags &= ~ATA_DFLAG_PIO;
+ } else {
+ ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+ dev->xfer_mode = XFER_PIO_0;
+ dev->xfer_shift = ATA_SHIFT_PIO;
+ dev->flags |= ATA_DFLAG_PIO;
}
-
- ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
- name);
-
- dev->xfer_mode = ata_xfer_mask2mode(xfer_mask);
- dev->xfer_shift = ata_xfer_mode2shift(dev->xfer_mode);
- dev->flags &= ~ATA_DFLAG_PIO;
- } else {
- ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
- dev->xfer_mode = XFER_PIO_0;
- dev->xfer_shift = ATA_SHIFT_PIO;
- dev->flags |= ATA_DFLAG_PIO;
}
}
return 0;
@@ -205,7 +185,6 @@ static struct pci_device_id ata_generic[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561), },
{ PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), },
- { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), },
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO), },
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), },
diff --git a/trunk/drivers/ata/ata_piix.c b/trunk/drivers/ata/ata_piix.c
index a65c8ae5c461..b406b39b878e 100644
--- a/trunk/drivers/ata/ata_piix.c
+++ b/trunk/drivers/ata/ata_piix.c
@@ -101,21 +101,39 @@ enum {
ICH5_PMR = 0x90, /* port mapping register */
ICH5_PCS = 0x92, /* port control and status */
PIIX_SCC = 0x0A, /* sub-class code register */
- PIIX_SIDPR_BAR = 5,
- PIIX_SIDPR_LEN = 16,
- PIIX_SIDPR_IDX = 0,
- PIIX_SIDPR_DATA = 4,
+ PIIX_FLAG_SCR = (1 << 26), /* SCR available */
PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */
PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */
- PIIX_FLAG_SIDPR = (1 << 29), /* SATA idx/data pair regs */
PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS,
PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
+ /* combined mode. if set, PATA is channel 0.
+ * if clear, PATA is channel 1.
+ */
+ PIIX_PORT_ENABLED = (1 << 0),
+ PIIX_PORT_PRESENT = (1 << 4),
+
PIIX_80C_PRI = (1 << 5) | (1 << 4),
PIIX_80C_SEC = (1 << 7) | (1 << 6),
+ /* controller IDs */
+ piix_pata_mwdma = 0, /* PIIX3 MWDMA only */
+ piix_pata_33, /* PIIX4 at 33Mhz */
+ ich_pata_33, /* ICH up to UDMA 33 only */
+ ich_pata_66, /* ICH up to 66 Mhz */
+ ich_pata_100, /* ICH up to UDMA 100 */
+ ich5_sata,
+ ich6_sata,
+ ich6_sata_ahci,
+ ich6m_sata_ahci,
+ ich8_sata_ahci,
+ ich8_2port_sata,
+ ich8m_apple_sata_ahci, /* locks up on second port enable */
+ tolapai_sata_ahci,
+ piix_pata_vmw, /* PIIX4 for VMware, spurious DMA_ERR */
+
/* constants for mapping table */
P0 = 0, /* port 0 */
P1 = 1, /* port 1 */
@@ -131,24 +149,6 @@ enum {
PIIX_HOST_BROKEN_SUSPEND = (1 << 24),
};
-enum piix_controller_ids {
- /* controller IDs */
- piix_pata_mwdma, /* PIIX3 MWDMA only */
- piix_pata_33, /* PIIX4 at 33Mhz */
- ich_pata_33, /* ICH up to UDMA 33 only */
- ich_pata_66, /* ICH up to 66 Mhz */
- ich_pata_100, /* ICH up to UDMA 100 */
- ich5_sata,
- ich6_sata,
- ich6_sata_ahci,
- ich6m_sata_ahci,
- ich8_sata_ahci,
- ich8_2port_sata,
- ich8m_apple_sata_ahci, /* locks up on second port enable */
- tolapai_sata_ahci,
- piix_pata_vmw, /* PIIX4 for VMware, spurious DMA_ERR */
-};
-
struct piix_map_db {
const u32 mask;
const u16 port_enable;
@@ -157,7 +157,6 @@ struct piix_map_db {
struct piix_host_priv {
const int *map;
- void __iomem *sidpr;
};
static int piix_init_one(struct pci_dev *pdev,
@@ -168,9 +167,6 @@ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
static int ich_pata_cable_detect(struct ata_port *ap);
static u8 piix_vmw_bmdma_status(struct ata_port *ap);
-static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
-static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
-static void piix_sidpr_error_handler(struct ata_port *ap);
#ifdef CONFIG_PM
static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int piix_pci_device_resume(struct pci_dev *pdev);
@@ -325,6 +321,7 @@ static const struct ata_port_operations piix_pata_ops = {
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.cable_detect = ata_cable_40wire,
+ .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
@@ -356,6 +353,7 @@ static const struct ata_port_operations ich_pata_ops = {
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.cable_detect = ich_pata_cable_detect,
+ .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
@@ -382,6 +380,7 @@ static const struct ata_port_operations piix_sata_ops = {
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
@@ -420,35 +419,6 @@ static const struct ata_port_operations piix_vmw_ops = {
.port_start = ata_port_start,
};
-static const struct ata_port_operations piix_sidpr_sata_ops = {
- .tf_load = ata_tf_load,
- .tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .exec_command = ata_exec_command,
- .dev_select = ata_std_dev_select,
-
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
- .bmdma_stop = ata_bmdma_stop,
- .bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
- .data_xfer = ata_data_xfer,
-
- .scr_read = piix_sidpr_scr_read,
- .scr_write = piix_sidpr_scr_write,
-
- .freeze = ata_bmdma_freeze,
- .thaw = ata_bmdma_thaw,
- .error_handler = piix_sidpr_error_handler,
- .post_internal_cmd = ata_bmdma_post_internal_cmd,
-
- .irq_clear = ata_bmdma_irq_clear,
- .irq_on = ata_irq_on,
-
- .port_start = ata_port_start,
-};
-
static const struct piix_map_db ich5_map_db = {
.mask = 0x7,
.port_enable = 0x3,
@@ -556,6 +526,7 @@ static const struct piix_map_db *piix_map_db_table[] = {
static struct ata_port_info piix_port_info[] = {
[piix_pata_mwdma] = /* PIIX3 MWDMA only */
{
+ .sht = &piix_sht,
.flags = PIIX_PATA_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
@@ -564,6 +535,7 @@ static struct ata_port_info piix_port_info[] = {
[piix_pata_33] = /* PIIX4 at 33MHz */
{
+ .sht = &piix_sht,
.flags = PIIX_PATA_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
@@ -573,6 +545,7 @@ static struct ata_port_info piix_port_info[] = {
[ich_pata_33] = /* ICH0 - ICH at 33Mhz*/
{
+ .sht = &piix_sht,
.flags = PIIX_PATA_FLAGS,
.pio_mask = 0x1f, /* pio 0-4 */
.mwdma_mask = 0x06, /* Check: maybe 0x07 */
@@ -582,6 +555,7 @@ static struct ata_port_info piix_port_info[] = {
[ich_pata_66] = /* ICH controllers up to 66MHz */
{
+ .sht = &piix_sht,
.flags = PIIX_PATA_FLAGS,
.pio_mask = 0x1f, /* pio 0-4 */
.mwdma_mask = 0x06, /* MWDMA0 is broken on chip */
@@ -591,6 +565,7 @@ static struct ata_port_info piix_port_info[] = {
[ich_pata_100] =
{
+ .sht = &piix_sht,
.flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x06, /* mwdma1-2 */
@@ -600,6 +575,7 @@ static struct ata_port_info piix_port_info[] = {
[ich5_sata] =
{
+ .sht = &piix_sht,
.flags = PIIX_SATA_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@@ -609,7 +585,8 @@ static struct ata_port_info piix_port_info[] = {
[ich6_sata] =
{
- .flags = PIIX_SATA_FLAGS,
+ .sht = &piix_sht,
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA6,
@@ -618,7 +595,9 @@ static struct ata_port_info piix_port_info[] = {
[ich6_sata_ahci] =
{
- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
+ .sht = &piix_sht,
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+ PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA6,
@@ -627,7 +606,9 @@ static struct ata_port_info piix_port_info[] = {
[ich6m_sata_ahci] =
{
- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
+ .sht = &piix_sht,
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+ PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA6,
@@ -636,8 +617,9 @@ static struct ata_port_info piix_port_info[] = {
[ich8_sata_ahci] =
{
- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
- PIIX_FLAG_SIDPR,
+ .sht = &piix_sht,
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+ PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA6,
@@ -646,8 +628,9 @@ static struct ata_port_info piix_port_info[] = {
[ich8_2port_sata] =
{
- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
- PIIX_FLAG_SIDPR,
+ .sht = &piix_sht,
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+ PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA6,
@@ -656,7 +639,9 @@ static struct ata_port_info piix_port_info[] = {
[tolapai_sata_ahci] =
{
- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
+ .sht = &piix_sht,
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+ PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA6,
@@ -665,8 +650,9 @@ static struct ata_port_info piix_port_info[] = {
[ich8m_apple_sata_ahci] =
{
- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
- PIIX_FLAG_SIDPR,
+ .sht = &piix_sht,
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+ PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA6,
@@ -1015,180 +1001,6 @@ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev)
do_pata_set_dmamode(ap, adev, 1);
}
-/*
- * Serial ATA Index/Data Pair Superset Registers access
- *
- * Beginning from ICH8, there's a sane way to access SCRs using index
- * and data register pair located at BAR5. This creates an
- * interesting problem of mapping two SCRs to one port.
- *
- * Although they have separate SCRs, the master and slave aren't
- * independent enough to be treated as separate links - e.g. softreset
- * resets both. Also, there's no protocol defined for hard resetting
- * singled device sharing the virtual port (no defined way to acquire
- * device signature). This is worked around by merging the SCR values
- * into one sensible value and requesting follow-up SRST after
- * hardreset.
- *
- * SCR merging is perfomed in nibbles which is the unit contents in
- * SCRs are organized. If two values are equal, the value is used.
- * When they differ, merge table which lists precedence of possible
- * values is consulted and the first match or the last entry when
- * nothing matches is used. When there's no merge table for the
- * specific nibble, value from the first port is used.
- */
-static const int piix_sidx_map[] = {
- [SCR_STATUS] = 0,
- [SCR_ERROR] = 2,
- [SCR_CONTROL] = 1,
-};
-
-static void piix_sidpr_sel(struct ata_device *dev, unsigned int reg)
-{
- struct ata_port *ap = dev->link->ap;
- struct piix_host_priv *hpriv = ap->host->private_data;
-
- iowrite32(((ap->port_no * 2 + dev->devno) << 8) | piix_sidx_map[reg],
- hpriv->sidpr + PIIX_SIDPR_IDX);
-}
-
-static int piix_sidpr_read(struct ata_device *dev, unsigned int reg)
-{
- struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
-
- piix_sidpr_sel(dev, reg);
- return ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
-}
-
-static void piix_sidpr_write(struct ata_device *dev, unsigned int reg, u32 val)
-{
- struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
-
- piix_sidpr_sel(dev, reg);
- iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
-}
-
-u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl)
-{
- u32 val = 0;
- int i, mi;
-
- for (i = 0, mi = 0; i < 32 / 4; i++) {
- u8 c0 = (val0 >> (i * 4)) & 0xf;
- u8 c1 = (val1 >> (i * 4)) & 0xf;
- u8 merged = c0;
- const int *cur;
-
- /* if no merge preference, assume the first value */
- cur = merge_tbl[mi];
- if (!cur)
- goto done;
- mi++;
-
- /* if two values equal, use it */
- if (c0 == c1)
- goto done;
-
- /* choose the first match or the last from the merge table */
- while (*cur != -1) {
- if (c0 == *cur || c1 == *cur)
- break;
- cur++;
- }
- if (*cur == -1)
- cur--;
- merged = *cur;
- done:
- val |= merged << (i * 4);
- }
-
- return val;
-}
-
-static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val)
-{
- const int * const sstatus_merge_tbl[] = {
- /* DET */ (const int []){ 1, 3, 0, 4, 3, -1 },
- /* SPD */ (const int []){ 2, 1, 0, -1 },
- /* IPM */ (const int []){ 6, 2, 1, 0, -1 },
- NULL,
- };
- const int * const scontrol_merge_tbl[] = {
- /* DET */ (const int []){ 1, 0, 4, 0, -1 },
- /* SPD */ (const int []){ 0, 2, 1, 0, -1 },
- /* IPM */ (const int []){ 0, 1, 2, 3, 0, -1 },
- NULL,
- };
- u32 v0, v1;
-
- if (reg >= ARRAY_SIZE(piix_sidx_map))
- return -EINVAL;
-
- if (!(ap->flags & ATA_FLAG_SLAVE_POSS)) {
- *val = piix_sidpr_read(&ap->link.device[0], reg);
- return 0;
- }
-
- v0 = piix_sidpr_read(&ap->link.device[0], reg);
- v1 = piix_sidpr_read(&ap->link.device[1], reg);
-
- switch (reg) {
- case SCR_STATUS:
- *val = piix_merge_scr(v0, v1, sstatus_merge_tbl);
- break;
- case SCR_ERROR:
- *val = v0 | v1;
- break;
- case SCR_CONTROL:
- *val = piix_merge_scr(v0, v1, scontrol_merge_tbl);
- break;
- }
-
- return 0;
-}
-
-static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val)
-{
- if (reg >= ARRAY_SIZE(piix_sidx_map))
- return -EINVAL;
-
- piix_sidpr_write(&ap->link.device[0], reg, val);
-
- if (ap->flags & ATA_FLAG_SLAVE_POSS)
- piix_sidpr_write(&ap->link.device[1], reg, val);
-
- return 0;
-}
-
-static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline)
-{
- const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
- int rc;
-
- /* do hardreset */
- rc = sata_link_hardreset(link, timing, deadline);
- if (rc) {
- ata_link_printk(link, KERN_ERR,
- "COMRESET failed (errno=%d)\n", rc);
- return rc;
- }
-
- /* TODO: phy layer with polling, timeouts, etc. */
- if (ata_link_offline(link)) {
- *class = ATA_DEV_NONE;
- return 0;
- }
-
- return -EAGAIN;
-}
-
-static void piix_sidpr_error_handler(struct ata_port *ap)
-{
- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
- piix_sidpr_hardreset, ata_std_postreset);
-}
-
#ifdef CONFIG_PM
static int piix_broken_suspend(void)
{
@@ -1221,13 +1033,6 @@ static int piix_broken_suspend(void)
DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M5"),
},
},
- {
- .ident = "TECRA M6",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
- DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M6"),
- },
- },
{
.ident = "TECRA M7",
.matches = {
@@ -1242,13 +1047,6 @@ static int piix_broken_suspend(void)
DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A8"),
},
},
- {
- .ident = "Satellite R20",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R20"),
- },
- },
{
.ident = "Satellite R25",
.matches = {
@@ -1455,10 +1253,10 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
return no_piix_dma;
}
-static void __devinit piix_init_pcs(struct ata_host *host,
+static void __devinit piix_init_pcs(struct pci_dev *pdev,
+ struct ata_port_info *pinfo,
const struct piix_map_db *map_db)
{
- struct pci_dev *pdev = to_pci_dev(host->dev);
u16 pcs, new_pcs;
pci_read_config_word(pdev, ICH5_PCS, &pcs);
@@ -1472,10 +1270,11 @@ static void __devinit piix_init_pcs(struct ata_host *host,
}
}
-static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
- struct ata_port_info *pinfo,
- const struct piix_map_db *map_db)
+static void __devinit piix_init_sata_map(struct pci_dev *pdev,
+ struct ata_port_info *pinfo,
+ const struct piix_map_db *map_db)
{
+ struct piix_host_priv *hpriv = pinfo[0].private_data;
const int *map;
int i, invalid_map = 0;
u8 map_value;
@@ -1499,6 +1298,7 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
case IDE:
WARN_ON((i & 1) || map[i + 1] != IDE);
pinfo[i / 2] = piix_port_info[ich_pata_100];
+ pinfo[i / 2].private_data = hpriv;
i++;
printk(" IDE IDE");
break;
@@ -1516,33 +1316,7 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
dev_printk(KERN_ERR, &pdev->dev,
"invalid MAP value %u\n", map_value);
- return map;
-}
-
-static void __devinit piix_init_sidpr(struct ata_host *host)
-{
- struct pci_dev *pdev = to_pci_dev(host->dev);
- struct piix_host_priv *hpriv = host->private_data;
- int i;
-
- /* check for availability */
- for (i = 0; i < 4; i++)
- if (hpriv->map[i] == IDE)
- return;
-
- if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
- return;
-
- if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 ||
- pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN)
- return;
-
- if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME))
- return;
-
- hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR];
- host->ports[0]->ops = &piix_sidpr_sata_ops;
- host->ports[1]->ops = &piix_sidpr_sata_ops;
+ hpriv->map = map;
}
static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
@@ -1601,10 +1375,8 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
struct device *dev = &pdev->dev;
struct ata_port_info port_info[2];
const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
- unsigned long port_flags;
- struct ata_host *host;
struct piix_host_priv *hpriv;
- int rc;
+ unsigned long port_flags;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev,
@@ -1614,31 +1386,17 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!in_module_init)
return -ENODEV;
- port_info[0] = piix_port_info[ent->driver_data];
- port_info[1] = piix_port_info[ent->driver_data];
-
- port_flags = port_info[0].flags;
-
- /* enable device and prepare host */
- rc = pcim_enable_device(pdev);
- if (rc)
- return rc;
-
- /* SATA map init can change port_info, do it before prepping host */
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
if (!hpriv)
return -ENOMEM;
- if (port_flags & ATA_FLAG_SATA)
- hpriv->map = piix_init_sata_map(pdev, port_info,
- piix_map_db_table[ent->driver_data]);
+ port_info[0] = piix_port_info[ent->driver_data];
+ port_info[1] = piix_port_info[ent->driver_data];
+ port_info[0].private_data = hpriv;
+ port_info[1].private_data = hpriv;
- rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
- if (rc)
- return rc;
- host->private_data = hpriv;
+ port_flags = port_info[0].flags;
- /* initialize controller */
if (port_flags & PIIX_FLAG_AHCI) {
u8 tmp;
pci_read_config_byte(pdev, PIIX_SCC, &tmp);
@@ -1649,9 +1407,12 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
}
+ /* Initialize SATA map */
if (port_flags & ATA_FLAG_SATA) {
- piix_init_pcs(host, piix_map_db_table[ent->driver_data]);
- piix_init_sidpr(host);
+ piix_init_sata_map(pdev, port_info,
+ piix_map_db_table[ent->driver_data]);
+ piix_init_pcs(pdev, port_info,
+ piix_map_db_table[ent->driver_data]);
}
/* apply IOCFG bit18 quirk */
@@ -1670,14 +1431,12 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* This writes into the master table but it does not
really matter for this errata as we will apply it to
all the PIIX devices on the board */
- host->ports[0]->mwdma_mask = 0;
- host->ports[0]->udma_mask = 0;
- host->ports[1]->mwdma_mask = 0;
- host->ports[1]->udma_mask = 0;
+ port_info[0].mwdma_mask = 0;
+ port_info[0].udma_mask = 0;
+ port_info[1].mwdma_mask = 0;
+ port_info[1].udma_mask = 0;
}
-
- pci_set_master(pdev);
- return ata_pci_activate_sff_host(host, ata_interrupt, &piix_sht);
+ return ata_pci_init_one(pdev, ppi);
}
static int __init piix_init(void)
diff --git a/trunk/drivers/ata/libata-acpi.c b/trunk/drivers/ata/libata-acpi.c
index 9e8ec19260af..7bf4befd96bc 100644
--- a/trunk/drivers/ata/libata-acpi.c
+++ b/trunk/drivers/ata/libata-acpi.c
@@ -441,78 +441,41 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
return rc;
}
-/**
- * ata_acpi_gtm_xfermode - determine xfermode from GTM parameter
- * @dev: target device
- * @gtm: GTM parameter to use
- *
- * Determine xfermask for @dev from @gtm.
- *
- * LOCKING:
- * None.
- *
- * RETURNS:
- * Determined xfermask.
- */
-unsigned long ata_acpi_gtm_xfermask(struct ata_device *dev,
- const struct ata_acpi_gtm *gtm)
-{
- unsigned long xfer_mask = 0;
- unsigned int type;
- int unit;
- u8 mode;
-
- /* we always use the 0 slot for crap hardware */
- unit = dev->devno;
- if (!(gtm->flags & 0x10))
- unit = 0;
-
- /* PIO */
- mode = ata_timing_cycle2mode(ATA_SHIFT_PIO, gtm->drive[unit].pio);
- xfer_mask |= ata_xfer_mode2mask(mode);
-
- /* See if we have MWDMA or UDMA data. We don't bother with
- * MWDMA if UDMA is available as this means the BIOS set UDMA
- * and our error changedown if it works is UDMA to PIO anyway.
- */
- if (!(gtm->flags & (1 << (2 * unit))))
- type = ATA_SHIFT_MWDMA;
- else
- type = ATA_SHIFT_UDMA;
-
- mode = ata_timing_cycle2mode(type, gtm->drive[unit].dma);
- xfer_mask |= ata_xfer_mode2mask(mode);
-
- return xfer_mask;
-}
-EXPORT_SYMBOL_GPL(ata_acpi_gtm_xfermask);
-
/**
* ata_acpi_cbl_80wire - Check for 80 wire cable
* @ap: Port to check
- * @gtm: GTM data to use
*
- * Return 1 if the @gtm indicates the BIOS selected an 80wire mode.
+ * Return 1 if the ACPI mode data for this port indicates the BIOS selected
+ * an 80wire mode.
*/
-int ata_acpi_cbl_80wire(struct ata_port *ap, const struct ata_acpi_gtm *gtm)
-{
- struct ata_device *dev;
-
- ata_link_for_each_dev(dev, &ap->link) {
- unsigned long xfer_mask, udma_mask;
- if (!ata_dev_enabled(dev))
- continue;
-
- xfer_mask = ata_acpi_gtm_xfermask(dev, gtm);
- ata_unpack_xfermask(xfer_mask, NULL, NULL, &udma_mask);
+int ata_acpi_cbl_80wire(struct ata_port *ap)
+{
+ const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap);
+ int valid = 0;
- if (udma_mask & ~ATA_UDMA_MASK_40C)
- return 1;
- }
+ if (!gtm)
+ return 0;
+ /* Split timing, DMA enabled */
+ if ((gtm->flags & 0x11) == 0x11 && gtm->drive[0].dma < 55)
+ valid |= 1;
+ if ((gtm->flags & 0x14) == 0x14 && gtm->drive[1].dma < 55)
+ valid |= 2;
+ /* Shared timing, DMA enabled */
+ if ((gtm->flags & 0x11) == 0x01 && gtm->drive[0].dma < 55)
+ valid |= 1;
+ if ((gtm->flags & 0x14) == 0x04 && gtm->drive[0].dma < 55)
+ valid |= 2;
+
+ /* Drive check */
+ if ((valid & 1) && ata_dev_enabled(&ap->link.device[0]))
+ return 1;
+ if ((valid & 2) && ata_dev_enabled(&ap->link.device[1]))
+ return 1;
return 0;
}
+
EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire);
static void ata_acpi_gtf_to_tf(struct ata_device *dev,
@@ -812,36 +775,6 @@ void ata_acpi_on_resume(struct ata_port *ap)
}
}
-/**
- * ata_acpi_set_state - set the port power state
- * @ap: target ATA port
- * @state: state, on/off
- *
- * This function executes the _PS0/_PS3 ACPI method to set the power state.
- * ACPI spec requires _PS0 when IDE power on and _PS3 when power off
- */
-void ata_acpi_set_state(struct ata_port *ap, pm_message_t state)
-{
- struct ata_device *dev;
-
- if (!ap->acpi_handle || (ap->flags & ATA_FLAG_ACPI_SATA))
- return;
-
- /* channel first and then drives for power on and vica versa
- for power off */
- if (state.event == PM_EVENT_ON)
- acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D0);
-
- ata_link_for_each_dev(dev, &ap->link) {
- if (dev->acpi_handle && ata_dev_enabled(dev))
- acpi_bus_set_power(dev->acpi_handle,
- state.event == PM_EVENT_ON ?
- ACPI_STATE_D0 : ACPI_STATE_D3);
- }
- if (state.event != PM_EVENT_ON)
- acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D3);
-}
-
/**
* ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration
* @dev: target ATA device
diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c
index ce803d18e96a..6380726f7538 100644
--- a/trunk/drivers/ata/libata-core.c
+++ b/trunk/drivers/ata/libata-core.c
@@ -119,10 +119,6 @@ int libata_noacpi = 0;
module_param_named(noacpi, libata_noacpi, int, 0444);
MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in probe/suspend/resume when set");
-int libata_allow_tpm = 0;
-module_param_named(allow_tpm, libata_allow_tpm, int, 0444);
-MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands");
-
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("Library module for ATA devices");
MODULE_LICENSE("GPL");
@@ -454,9 +450,9 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
* RETURNS:
* Packed xfer_mask.
*/
-unsigned long ata_pack_xfermask(unsigned long pio_mask,
- unsigned long mwdma_mask,
- unsigned long udma_mask)
+static unsigned int ata_pack_xfermask(unsigned int pio_mask,
+ unsigned int mwdma_mask,
+ unsigned int udma_mask)
{
return ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) |
((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) |
@@ -473,8 +469,10 @@ unsigned long ata_pack_xfermask(unsigned long pio_mask,
* Unpack @xfer_mask into @pio_mask, @mwdma_mask and @udma_mask.
* Any NULL distination masks will be ignored.
*/
-void ata_unpack_xfermask(unsigned long xfer_mask, unsigned long *pio_mask,
- unsigned long *mwdma_mask, unsigned long *udma_mask)
+static void ata_unpack_xfermask(unsigned int xfer_mask,
+ unsigned int *pio_mask,
+ unsigned int *mwdma_mask,
+ unsigned int *udma_mask)
{
if (pio_mask)
*pio_mask = (xfer_mask & ATA_MASK_PIO) >> ATA_SHIFT_PIO;
@@ -488,9 +486,9 @@ static const struct ata_xfer_ent {
int shift, bits;
u8 base;
} ata_xfer_tbl[] = {
- { ATA_SHIFT_PIO, ATA_NR_PIO_MODES, XFER_PIO_0 },
- { ATA_SHIFT_MWDMA, ATA_NR_MWDMA_MODES, XFER_MW_DMA_0 },
- { ATA_SHIFT_UDMA, ATA_NR_UDMA_MODES, XFER_UDMA_0 },
+ { ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 },
+ { ATA_SHIFT_MWDMA, ATA_BITS_MWDMA, XFER_MW_DMA_0 },
+ { ATA_SHIFT_UDMA, ATA_BITS_UDMA, XFER_UDMA_0 },
{ -1, },
};
@@ -505,9 +503,9 @@ static const struct ata_xfer_ent {
* None.
*
* RETURNS:
- * Matching XFER_* value, 0xff if no match found.
+ * Matching XFER_* value, 0 if no match found.
*/
-u8 ata_xfer_mask2mode(unsigned long xfer_mask)
+static u8 ata_xfer_mask2mode(unsigned int xfer_mask)
{
int highbit = fls(xfer_mask) - 1;
const struct ata_xfer_ent *ent;
@@ -515,7 +513,7 @@ u8 ata_xfer_mask2mode(unsigned long xfer_mask)
for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
if (highbit >= ent->shift && highbit < ent->shift + ent->bits)
return ent->base + highbit - ent->shift;
- return 0xff;
+ return 0;
}
/**
@@ -530,14 +528,13 @@ u8 ata_xfer_mask2mode(unsigned long xfer_mask)
* RETURNS:
* Matching xfer_mask, 0 if no match found.
*/
-unsigned long ata_xfer_mode2mask(u8 xfer_mode)
+static unsigned int ata_xfer_mode2mask(u8 xfer_mode)
{
const struct ata_xfer_ent *ent;
for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits)
- return ((2 << (ent->shift + xfer_mode - ent->base)) - 1)
- & ~((1 << ent->shift) - 1);
+ return 1 << (ent->shift + xfer_mode - ent->base);
return 0;
}
@@ -553,7 +550,7 @@ unsigned long ata_xfer_mode2mask(u8 xfer_mode)
* RETURNS:
* Matching xfer_shift, -1 if no match found.
*/
-int ata_xfer_mode2shift(unsigned long xfer_mode)
+static int ata_xfer_mode2shift(unsigned int xfer_mode)
{
const struct ata_xfer_ent *ent;
@@ -577,7 +574,7 @@ int ata_xfer_mode2shift(unsigned long xfer_mode)
* Constant C string representing highest speed listed in
* @mode_mask, or the constant C string "".
*/
-const char *ata_mode_string(unsigned long xfer_mask)
+static const char *ata_mode_string(unsigned int xfer_mask)
{
static const char * const xfer_mode_str[] = {
"PIO0",
@@ -950,8 +947,8 @@ unsigned int ata_dev_try_classify(struct ata_device *dev, int present,
if (r_err)
*r_err = err;
- /* see if device passed diags: continue and warn later */
- if (err == 0)
+ /* see if device passed diags: if master then continue and warn later */
+ if (err == 0 && dev->devno == 0)
/* diagnostic fail : do nothing _YET_ */
dev->horkage |= ATA_HORKAGE_DIAGNOSTIC;
else if (err == 1)
@@ -1288,6 +1285,48 @@ static int ata_hpa_resize(struct ata_device *dev)
return 0;
}
+/**
+ * ata_id_to_dma_mode - Identify DMA mode from id block
+ * @dev: device to identify
+ * @unknown: mode to assume if we cannot tell
+ *
+ * Set up the timing values for the device based upon the identify
+ * reported values for the DMA mode. This function is used by drivers
+ * which rely upon firmware configured modes, but wish to report the
+ * mode correctly when possible.
+ *
+ * In addition we emit similarly formatted messages to the default
+ * ata_dev_set_mode handler, in order to provide consistency of
+ * presentation.
+ */
+
+void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown)
+{
+ unsigned int mask;
+ u8 mode;
+
+ /* Pack the DMA modes */
+ mask = ((dev->id[63] >> 8) << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA;
+ if (dev->id[53] & 0x04)
+ mask |= ((dev->id[88] >> 8) << ATA_SHIFT_UDMA) & ATA_MASK_UDMA;
+
+ /* Select the mode in use */
+ mode = ata_xfer_mask2mode(mask);
+
+ if (mode != 0) {
+ ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
+ ata_mode_string(mask));
+ } else {
+ /* SWDMA perhaps ? */
+ mode = unknown;
+ ata_dev_printk(dev, KERN_INFO, "configured for DMA\n");
+ }
+
+ /* Configure the device reporting */
+ dev->xfer_mode = mode;
+ dev->xfer_shift = ata_xfer_mode2shift(mode);
+}
+
/**
* ata_noop_dev_select - Select device 0/1 on ATA bus
* @ap: ATA channel to manipulate
@@ -1425,9 +1464,9 @@ static inline void ata_dump_id(const u16 *id)
* RETURNS:
* Computed xfermask
*/
-unsigned long ata_id_xfermask(const u16 *id)
+static unsigned int ata_id_xfermask(const u16 *id)
{
- unsigned long pio_mask, mwdma_mask, udma_mask;
+ unsigned int pio_mask, mwdma_mask, udma_mask;
/* Usual case. Word 53 indicates word 64 is valid */
if (id[ATA_ID_FIELD_VALID] & (1 << 1)) {
@@ -1480,7 +1519,7 @@ unsigned long ata_id_xfermask(const u16 *id)
}
/**
- * ata_pio_queue_task - Queue port_task
+ * ata_port_queue_task - Queue port_task
* @ap: The ata_port to queue port_task for
* @fn: workqueue function to be scheduled
* @data: data for @fn to use
@@ -1492,15 +1531,16 @@ unsigned long ata_id_xfermask(const u16 *id)
* one task is active at any given time.
*
* libata core layer takes care of synchronization between
- * port_task and EH. ata_pio_queue_task() may be ignored for EH
+ * port_task and EH. ata_port_queue_task() may be ignored for EH
* synchronization.
*
* LOCKING:
* Inherited from caller.
*/
-static void ata_pio_queue_task(struct ata_port *ap, void *data,
- unsigned long delay)
+void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
+ unsigned long delay)
{
+ PREPARE_DELAYED_WORK(&ap->port_task, fn);
ap->port_task_data = data;
/* may fail if ata_port_flush_task() in progress */
@@ -2050,7 +2090,7 @@ int ata_dev_configure(struct ata_device *dev)
struct ata_eh_context *ehc = &dev->link->eh_context;
int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
const u16 *id = dev->id;
- unsigned long xfer_mask;
+ unsigned int xfer_mask;
char revbuf[7]; /* XYZ-99\0 */
char fwrevbuf[ATA_ID_FW_REV_LEN+1];
char modelbuf[ATA_ID_PROD_LEN+1];
@@ -2121,14 +2161,8 @@ int ata_dev_configure(struct ata_device *dev)
"supports DRM functions and may "
"not be fully accessable.\n");
snprintf(revbuf, 7, "CFA");
- } else {
+ } else
snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
- /* Warn the user if the device has TPM extensions */
- if (ata_id_has_tpm(id))
- ata_dev_printk(dev, KERN_WARNING,
- "supports DRM functions and may "
- "not be fully accessable.\n");
- }
dev->n_sectors = ata_id_n_sectors(id);
@@ -2261,8 +2295,19 @@ int ata_dev_configure(struct ata_device *dev)
dev->flags |= ATA_DFLAG_DIPM;
}
- /* Limit PATA drive on SATA cable bridge transfers to udma5,
- 200 sectors */
+ if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
+ /* Let the user know. We don't want to disallow opens for
+ rescue purposes, or in case the vendor is just a blithering
+ idiot */
+ if (print_info) {
+ ata_dev_printk(dev, KERN_WARNING,
+"Drive reports diagnostics failure. This may indicate a drive\n");
+ ata_dev_printk(dev, KERN_WARNING,
+"fault or invalid emulation. Contact drive vendor for information.\n");
+ }
+ }
+
+ /* limit bridge transfers to udma5, 200 sectors */
if (ata_dev_knobble(dev)) {
if (ata_msg_drv(ap) && print_info)
ata_dev_printk(dev, KERN_INFO,
@@ -2291,21 +2336,6 @@ int ata_dev_configure(struct ata_device *dev)
if (ap->ops->dev_config)
ap->ops->dev_config(dev);
- if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
- /* Let the user know. We don't want to disallow opens for
- rescue purposes, or in case the vendor is just a blithering
- idiot. Do this after the dev_config call as some controllers
- with buggy firmware may want to avoid reporting false device
- bugs */
-
- if (print_info) {
- ata_dev_printk(dev, KERN_WARNING,
-"Drive reports diagnostics failure. This may indicate a drive\n");
- ata_dev_printk(dev, KERN_WARNING,
-"fault or invalid emulation. Contact drive vendor for information.\n");
- }
- }
-
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n",
__FUNCTION__, ata_chk_status(ap));
@@ -2356,18 +2386,6 @@ int ata_cable_unknown(struct ata_port *ap)
return ATA_CBL_PATA_UNK;
}
-/**
- * ata_cable_ignore - return ignored PATA cable.
- * @ap: port
- *
- * Helper method for drivers which don't use cable type to limit
- * transfer mode.
- */
-int ata_cable_ignore(struct ata_port *ap)
-{
- return ATA_CBL_PATA_IGN;
-}
-
/**
* ata_cable_sata - return SATA cable type
* @ap: port
@@ -2763,33 +2781,38 @@ int sata_set_spd(struct ata_link *link)
*/
static const struct ata_timing ata_timing[] = {
-/* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960, 0 }, */
- { XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0 },
- { XFER_PIO_1, 50, 290, 93, 383, 125, 100, 383, 0 },
- { XFER_PIO_2, 30, 290, 40, 330, 100, 90, 240, 0 },
- { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 },
- { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 },
- { XFER_PIO_5, 15, 65, 25, 100, 65, 25, 100, 0 },
- { XFER_PIO_6, 10, 55, 20, 80, 55, 20, 80, 0 },
- { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 },
- { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 },
- { XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 240, 0 },
+ { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 15 },
+ { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 20 },
+ { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 },
+ { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 },
- { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 },
- { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 },
- { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 },
- { XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 100, 0 },
{ XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 80, 0 },
+ { XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 100, 0 },
+ { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 },
+ { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 },
+ { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 },
/* { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 150 }, */
- { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 },
- { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 },
- { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 },
- { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 },
- { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 },
- { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 20 },
- { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 15 },
+
+ { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 },
+ { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 },
+ { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 },
+
+ { XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 240, 0 },
+ { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 },
+ { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 },
+
+ { XFER_PIO_6, 10, 55, 20, 80, 55, 20, 80, 0 },
+ { XFER_PIO_5, 15, 65, 25, 100, 65, 25, 100, 0 },
+ { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 },
+ { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 },
+
+ { XFER_PIO_2, 30, 290, 40, 330, 100, 90, 240, 0 },
+ { XFER_PIO_1, 50, 290, 93, 383, 125, 100, 383, 0 },
+ { XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0 },
+
+/* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960, 0 }, */
{ 0xFF }
};
@@ -2822,16 +2845,14 @@ void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
if (what & ATA_TIMING_UDMA ) m->udma = max(a->udma, b->udma);
}
-const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)
+static const struct ata_timing *ata_timing_find_mode(unsigned short speed)
{
- const struct ata_timing *t = ata_timing;
-
- while (xfer_mode > t->mode)
- t++;
+ const struct ata_timing *t;
- if (xfer_mode == t->mode)
- return t;
- return NULL;
+ for (t = ata_timing; t->mode != speed; t++)
+ if (t->mode == 0xFF)
+ return NULL;
+ return t;
}
int ata_timing_compute(struct ata_device *adev, unsigned short speed,
@@ -2905,57 +2926,6 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
return 0;
}
-/**
- * ata_timing_cycle2mode - find xfer mode for the specified cycle duration
- * @xfer_shift: ATA_SHIFT_* value for transfer type to examine.
- * @cycle: cycle duration in ns
- *
- * Return matching xfer mode for @cycle. The returned mode is of
- * the transfer type specified by @xfer_shift. If @cycle is too
- * slow for @xfer_shift, 0xff is returned. If @cycle is faster
- * than the fastest known mode, the fasted mode is returned.
- *
- * LOCKING:
- * None.
- *
- * RETURNS:
- * Matching xfer_mode, 0xff if no match found.
- */
-u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle)
-{
- u8 base_mode = 0xff, last_mode = 0xff;
- const struct ata_xfer_ent *ent;
- const struct ata_timing *t;
-
- for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
- if (ent->shift == xfer_shift)
- base_mode = ent->base;
-
- for (t = ata_timing_find_mode(base_mode);
- t && ata_xfer_mode2shift(t->mode) == xfer_shift; t++) {
- unsigned short this_cycle;
-
- switch (xfer_shift) {
- case ATA_SHIFT_PIO:
- case ATA_SHIFT_MWDMA:
- this_cycle = t->cycle;
- break;
- case ATA_SHIFT_UDMA:
- this_cycle = t->udma;
- break;
- default:
- return 0xff;
- }
-
- if (cycle > this_cycle)
- break;
-
- last_mode = t->mode;
- }
-
- return last_mode;
-}
-
/**
* ata_down_xfermask_limit - adjust dev xfer masks downward
* @dev: Device to adjust xfer masks
@@ -2974,8 +2944,8 @@ u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle)
int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel)
{
char buf[32];
- unsigned long orig_mask, xfer_mask;
- unsigned long pio_mask, mwdma_mask, udma_mask;
+ unsigned int orig_mask, xfer_mask;
+ unsigned int pio_mask, mwdma_mask, udma_mask;
int quiet, highbit;
quiet = !!(sel & ATA_DNXFER_QUIET);
@@ -3069,7 +3039,7 @@ static int ata_dev_set_mode(struct ata_device *dev)
/* Early MWDMA devices do DMA but don't allow DMA mode setting.
Don't fail an MWDMA0 set IFF the device indicates it is in MWDMA0 */
- if (dev->xfer_shift == ATA_SHIFT_MWDMA &&
+ if (dev->xfer_shift == ATA_SHIFT_MWDMA &&
dev->dma_mode == XFER_MW_DMA_0 &&
(dev->id[63] >> 8) & 1)
err_mask &= ~AC_ERR_DEV;
@@ -3119,7 +3089,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
/* step 1: calculate xfer_mask */
ata_link_for_each_dev(dev, link) {
- unsigned long pio_mask, dma_mask;
+ unsigned int pio_mask, dma_mask;
unsigned int mode_mask;
if (!ata_dev_enabled(dev))
@@ -3145,7 +3115,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
dev->dma_mode = ata_xfer_mask2mode(dma_mask);
found = 1;
- if (dev->dma_mode != 0xff)
+ if (dev->dma_mode)
used_dma = 1;
}
if (!found)
@@ -3156,7 +3126,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
if (!ata_dev_enabled(dev))
continue;
- if (dev->pio_mode == 0xff) {
+ if (!dev->pio_mode) {
ata_dev_printk(dev, KERN_WARNING, "no PIO support\n");
rc = -EINVAL;
goto out;
@@ -3170,7 +3140,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
/* step 3: set host DMA timings */
ata_link_for_each_dev(dev, link) {
- if (!ata_dev_enabled(dev) || dev->dma_mode == 0xff)
+ if (!ata_dev_enabled(dev) || !dev->dma_mode)
continue;
dev->xfer_mode = dev->dma_mode;
@@ -3202,6 +3172,31 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
return rc;
}
+/**
+ * ata_set_mode - Program timings and issue SET FEATURES - XFER
+ * @link: link on which timings will be programmed
+ * @r_failed_dev: out paramter for failed device
+ *
+ * Set ATA device disk transfer mode (PIO3, UDMA6, etc.). If
+ * ata_set_mode() fails, pointer to the failing device is
+ * returned in @r_failed_dev.
+ *
+ * LOCKING:
+ * PCI/etc. bus probe sem.
+ *
+ * RETURNS:
+ * 0 on success, negative errno otherwise
+ */
+int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+{
+ struct ata_port *ap = link->ap;
+
+ /* has private set_mode? */
+ if (ap->ops->set_mode)
+ return ap->ops->set_mode(link, r_failed_dev);
+ return ata_do_set_mode(link, r_failed_dev);
+}
+
/**
* ata_tf_to_host - issue ATA taskfile to host controller
* @ap: port to which command is being issued
@@ -4368,14 +4363,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
tf.feature = SETFEATURES_XFER;
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_POLLING;
tf.protocol = ATA_PROT_NODATA;
- /* If we are using IORDY we must send the mode setting command */
- if (ata_pio_need_iordy(dev))
- tf.nsect = dev->xfer_mode;
- /* If the device has IORDY and the controller does not - turn it off */
- else if (ata_id_has_iordy(dev->id))
- tf.nsect = 0x01;
- else /* In the ancient relic department - skip all of this */
- return 0;
+ tf.nsect = dev->xfer_mode;
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
@@ -4474,13 +4462,17 @@ static unsigned int ata_dev_init_params(struct ata_device *dev,
void ata_sg_clean(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- struct scatterlist *sg = qc->sg;
+ struct scatterlist *sg = qc->__sg;
int dir = qc->dma_dir;
void *pad_buf = NULL;
+ WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
WARN_ON(sg == NULL);
- VPRINTK("unmapping %u sg elements\n", qc->mapped_n_elem);
+ if (qc->flags & ATA_QCFLAG_SINGLE)
+ WARN_ON(qc->n_elem > 1);
+
+ VPRINTK("unmapping %u sg elements\n", qc->n_elem);
/* if we padded the buffer out to 32-bit bound, and data
* xfer direction is from-device, we must copy from the
@@ -4489,20 +4481,31 @@ void ata_sg_clean(struct ata_queued_cmd *qc)
if (qc->pad_len && !(qc->tf.flags & ATA_TFLAG_WRITE))
pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
- if (qc->mapped_n_elem)
- dma_unmap_sg(ap->dev, sg, qc->mapped_n_elem, dir);
- /* restore last sg */
- if (qc->last_sg)
- *qc->last_sg = qc->saved_last_sg;
- if (pad_buf) {
- struct scatterlist *psg = &qc->extra_sg[1];
- void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
- memcpy(addr + psg->offset, pad_buf, qc->pad_len);
- kunmap_atomic(addr, KM_IRQ0);
+ if (qc->flags & ATA_QCFLAG_SG) {
+ if (qc->n_elem)
+ dma_unmap_sg(ap->dev, sg, qc->n_elem, dir);
+ /* restore last sg */
+ sg_last(sg, qc->orig_n_elem)->length += qc->pad_len;
+ if (pad_buf) {
+ struct scatterlist *psg = &qc->pad_sgent;
+ void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
+ memcpy(addr + psg->offset, pad_buf, qc->pad_len);
+ kunmap_atomic(addr, KM_IRQ0);
+ }
+ } else {
+ if (qc->n_elem)
+ dma_unmap_single(ap->dev,
+ sg_dma_address(&sg[0]), sg_dma_len(&sg[0]),
+ dir);
+ /* restore sg */
+ sg->length += qc->pad_len;
+ if (pad_buf)
+ memcpy(qc->buf_virt + sg->length - qc->pad_len,
+ pad_buf, qc->pad_len);
}
qc->flags &= ~ATA_QCFLAG_DMAMAP;
- qc->sg = NULL;
+ qc->__sg = NULL;
}
/**
@@ -4520,10 +4523,13 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct scatterlist *sg;
- unsigned int si, pi;
+ unsigned int idx;
- pi = 0;
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ WARN_ON(qc->__sg == NULL);
+ WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+
+ idx = 0;
+ ata_for_each_sg(sg, qc) {
u32 addr, offset;
u32 sg_len, len;
@@ -4540,17 +4546,18 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
if ((offset + sg_len) > 0x10000)
len = 0x10000 - offset;
- ap->prd[pi].addr = cpu_to_le32(addr);
- ap->prd[pi].flags_len = cpu_to_le32(len & 0xffff);
- VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
+ ap->prd[idx].addr = cpu_to_le32(addr);
+ ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff);
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
- pi++;
+ idx++;
sg_len -= len;
addr += len;
}
}
- ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+ if (idx)
+ ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
}
/**
@@ -4570,10 +4577,13 @@ static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct scatterlist *sg;
- unsigned int si, pi;
+ unsigned int idx;
+
+ WARN_ON(qc->__sg == NULL);
+ WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
- pi = 0;
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ idx = 0;
+ ata_for_each_sg(sg, qc) {
u32 addr, offset;
u32 sg_len, len, blen;
@@ -4591,24 +4601,25 @@ static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
len = 0x10000 - offset;
blen = len & 0xffff;
- ap->prd[pi].addr = cpu_to_le32(addr);
+ ap->prd[idx].addr = cpu_to_le32(addr);
if (blen == 0) {
/* Some PATA chipsets like the CS5530 can't
cope with 0x0000 meaning 64K as the spec says */
- ap->prd[pi].flags_len = cpu_to_le32(0x8000);
+ ap->prd[idx].flags_len = cpu_to_le32(0x8000);
blen = 0x8000;
- ap->prd[++pi].addr = cpu_to_le32(addr + 0x8000);
+ ap->prd[++idx].addr = cpu_to_le32(addr + 0x8000);
}
- ap->prd[pi].flags_len = cpu_to_le32(blen);
- VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
+ ap->prd[idx].flags_len = cpu_to_le32(blen);
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
- pi++;
+ idx++;
sg_len -= len;
addr += len;
}
}
- ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+ if (idx)
+ ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
}
/**
@@ -4658,8 +4669,8 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
*/
static int atapi_qc_may_overflow(struct ata_queued_cmd *qc)
{
- if (qc->tf.protocol != ATAPI_PROT_PIO &&
- qc->tf.protocol != ATAPI_PROT_DMA)
+ if (qc->tf.protocol != ATA_PROT_ATAPI &&
+ qc->tf.protocol != ATA_PROT_ATAPI_DMA)
return 0;
if (qc->tf.flags & ATA_TFLAG_WRITE)
@@ -4744,6 +4755,33 @@ void ata_dumb_qc_prep(struct ata_queued_cmd *qc)
void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
+/**
+ * ata_sg_init_one - Associate command with memory buffer
+ * @qc: Command to be associated
+ * @buf: Memory buffer
+ * @buflen: Length of memory buffer, in bytes.
+ *
+ * Initialize the data-related elements of queued_cmd @qc
+ * to point to a single memory buffer, @buf of byte length @buflen.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+
+void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
+{
+ qc->flags |= ATA_QCFLAG_SINGLE;
+
+ qc->__sg = &qc->sgent;
+ qc->n_elem = 1;
+ qc->orig_n_elem = 1;
+ qc->buf_virt = buf;
+ qc->nbytes = buflen;
+ qc->cursg = qc->__sg;
+
+ sg_init_one(&qc->sgent, buf, buflen);
+}
+
/**
* ata_sg_init - Associate command with scatter-gather table.
* @qc: Command to be associated
@@ -4757,103 +4795,84 @@ void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
* LOCKING:
* spin_lock_irqsave(host lock)
*/
+
void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
unsigned int n_elem)
{
- qc->sg = sg;
+ qc->flags |= ATA_QCFLAG_SG;
+ qc->__sg = sg;
qc->n_elem = n_elem;
- qc->cursg = qc->sg;
+ qc->orig_n_elem = n_elem;
+ qc->cursg = qc->__sg;
}
-static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc,
- unsigned int *n_elem_extra,
- unsigned int *nbytes_extra)
+/**
+ * ata_sg_setup_one - DMA-map the memory buffer associated with a command.
+ * @qc: Command with memory buffer to be mapped.
+ *
+ * DMA-map the memory buffer associated with queued_cmd @qc.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ *
+ * RETURNS:
+ * Zero on success, negative on error.
+ */
+
+static int ata_sg_setup_one(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- unsigned int n_elem = qc->n_elem;
- struct scatterlist *lsg, *copy_lsg = NULL, *tsg = NULL, *esg = NULL;
-
- *n_elem_extra = 0;
- *nbytes_extra = 0;
-
- /* needs padding? */
- qc->pad_len = qc->nbytes & 3;
-
- if (likely(!qc->pad_len))
- return n_elem;
-
- /* locate last sg and save it */
- lsg = sg_last(qc->sg, n_elem);
- qc->last_sg = lsg;
- qc->saved_last_sg = *lsg;
-
- sg_init_table(qc->extra_sg, ARRAY_SIZE(qc->extra_sg));
+ int dir = qc->dma_dir;
+ struct scatterlist *sg = qc->__sg;
+ dma_addr_t dma_address;
+ int trim_sg = 0;
+ /* we must lengthen transfers to end on a 32-bit boundary */
+ qc->pad_len = sg->length & 3;
if (qc->pad_len) {
- struct scatterlist *psg = &qc->extra_sg[1];
void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
- unsigned int offset;
+ struct scatterlist *psg = &qc->pad_sgent;
WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
memset(pad_buf, 0, ATA_DMA_PAD_SZ);
- /* psg->page/offset are used to copy to-be-written
- * data in this function or read data in ata_sg_clean.
- */
- offset = lsg->offset + lsg->length - qc->pad_len;
- sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT),
- qc->pad_len, offset_in_page(offset));
-
- if (qc->tf.flags & ATA_TFLAG_WRITE) {
- void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
- memcpy(pad_buf, addr + psg->offset, qc->pad_len);
- kunmap_atomic(addr, KM_IRQ0);
- }
+ if (qc->tf.flags & ATA_TFLAG_WRITE)
+ memcpy(pad_buf, qc->buf_virt + sg->length - qc->pad_len,
+ qc->pad_len);
sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
sg_dma_len(psg) = ATA_DMA_PAD_SZ;
+ /* trim sg */
+ sg->length -= qc->pad_len;
+ if (sg->length == 0)
+ trim_sg = 1;
- /* Trim the last sg entry and chain the original and
- * padding sg lists.
- *
- * Because chaining consumes one sg entry, one extra
- * sg entry is allocated and the last sg entry is
- * copied to it if the length isn't zero after padded
- * amount is removed.
- *
- * If the last sg entry is completely replaced by
- * padding sg entry, the first sg entry is skipped
- * while chaining.
- */
- lsg->length -= qc->pad_len;
- if (lsg->length) {
- copy_lsg = &qc->extra_sg[0];
- tsg = &qc->extra_sg[0];
- } else {
- n_elem--;
- tsg = &qc->extra_sg[1];
- }
-
- esg = &qc->extra_sg[1];
+ DPRINTK("padding done, sg->length=%u pad_len=%u\n",
+ sg->length, qc->pad_len);
+ }
- (*n_elem_extra)++;
- (*nbytes_extra) += 4 - qc->pad_len;
+ if (trim_sg) {
+ qc->n_elem--;
+ goto skip_map;
}
- if (copy_lsg)
- sg_set_page(copy_lsg, sg_page(lsg), lsg->length, lsg->offset);
+ dma_address = dma_map_single(ap->dev, qc->buf_virt,
+ sg->length, dir);
+ if (dma_mapping_error(dma_address)) {
+ /* restore sg */
+ sg->length += qc->pad_len;
+ return -1;
+ }
- sg_chain(lsg, 1, tsg);
- sg_mark_end(esg);
+ sg_dma_address(sg) = dma_address;
+ sg_dma_len(sg) = sg->length;
- /* sglist can't start with chaining sg entry, fast forward */
- if (qc->sg == lsg) {
- qc->sg = tsg;
- qc->cursg = tsg;
- }
+skip_map:
+ DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
+ qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
- return n_elem;
+ return 0;
}
/**
@@ -4869,30 +4888,75 @@ static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc,
* Zero on success, negative on error.
*
*/
+
static int ata_sg_setup(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- unsigned int n_elem, n_elem_extra, nbytes_extra;
+ struct scatterlist *sg = qc->__sg;
+ struct scatterlist *lsg = sg_last(qc->__sg, qc->n_elem);
+ int n_elem, pre_n_elem, dir, trim_sg = 0;
VPRINTK("ENTER, ata%u\n", ap->print_id);
+ WARN_ON(!(qc->flags & ATA_QCFLAG_SG));
- n_elem = ata_sg_setup_extra(qc, &n_elem_extra, &nbytes_extra);
+ /* we must lengthen transfers to end on a 32-bit boundary */
+ qc->pad_len = lsg->length & 3;
+ if (qc->pad_len) {
+ void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
+ struct scatterlist *psg = &qc->pad_sgent;
+ unsigned int offset;
- if (n_elem) {
- n_elem = dma_map_sg(ap->dev, qc->sg, n_elem, qc->dma_dir);
- if (n_elem < 1) {
- /* restore last sg */
- if (qc->last_sg)
- *qc->last_sg = qc->saved_last_sg;
- return -1;
+ WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
+
+ memset(pad_buf, 0, ATA_DMA_PAD_SZ);
+
+ /*
+ * psg->page/offset are used to copy to-be-written
+ * data in this function or read data in ata_sg_clean.
+ */
+ offset = lsg->offset + lsg->length - qc->pad_len;
+ sg_init_table(psg, 1);
+ sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT),
+ qc->pad_len, offset_in_page(offset));
+
+ if (qc->tf.flags & ATA_TFLAG_WRITE) {
+ void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
+ memcpy(pad_buf, addr + psg->offset, qc->pad_len);
+ kunmap_atomic(addr, KM_IRQ0);
}
- DPRINTK("%d sg elements mapped\n", n_elem);
+
+ sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
+ sg_dma_len(psg) = ATA_DMA_PAD_SZ;
+ /* trim last sg */
+ lsg->length -= qc->pad_len;
+ if (lsg->length == 0)
+ trim_sg = 1;
+
+ DPRINTK("padding done, sg[%d].length=%u pad_len=%u\n",
+ qc->n_elem - 1, lsg->length, qc->pad_len);
+ }
+
+ pre_n_elem = qc->n_elem;
+ if (trim_sg && pre_n_elem)
+ pre_n_elem--;
+
+ if (!pre_n_elem) {
+ n_elem = 0;
+ goto skip_map;
+ }
+
+ dir = qc->dma_dir;
+ n_elem = dma_map_sg(ap->dev, sg, pre_n_elem, dir);
+ if (n_elem < 1) {
+ /* restore last sg */
+ lsg->length += qc->pad_len;
+ return -1;
}
- qc->n_elem = qc->mapped_n_elem = n_elem;
- qc->n_elem += n_elem_extra;
- qc->nbytes += nbytes_extra;
- qc->flags |= ATA_QCFLAG_DMAMAP;
+ DPRINTK("%d sg elements mapped\n", n_elem);
+
+skip_map:
+ qc->n_elem = n_elem;
return 0;
}
@@ -4921,7 +4985,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
/**
* ata_data_xfer - Transfer data by PIO
- * @dev: device to target
+ * @adev: device to target
* @buf: data buffer
* @buflen: buffer length
* @write_data: read/write
@@ -4930,44 +4994,37 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
*
* LOCKING:
* Inherited from caller.
- *
- * RETURNS:
- * Bytes consumed.
*/
-unsigned int ata_data_xfer(struct ata_device *dev, unsigned char *buf,
- unsigned int buflen, int rw)
+void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
+ unsigned int buflen, int write_data)
{
- struct ata_port *ap = dev->link->ap;
- void __iomem *data_addr = ap->ioaddr.data_addr;
+ struct ata_port *ap = adev->link->ap;
unsigned int words = buflen >> 1;
/* Transfer multiple of 2 bytes */
- if (rw == READ)
- ioread16_rep(data_addr, buf, words);
+ if (write_data)
+ iowrite16_rep(ap->ioaddr.data_addr, buf, words);
else
- iowrite16_rep(data_addr, buf, words);
+ ioread16_rep(ap->ioaddr.data_addr, buf, words);
/* Transfer trailing 1 byte, if any. */
if (unlikely(buflen & 0x01)) {
- __le16 align_buf[1] = { 0 };
+ u16 align_buf[1] = { 0 };
unsigned char *trailing_buf = buf + buflen - 1;
- if (rw == READ) {
- align_buf[0] = cpu_to_le16(ioread16(data_addr));
- memcpy(trailing_buf, align_buf, 1);
- } else {
+ if (write_data) {
memcpy(align_buf, trailing_buf, 1);
- iowrite16(le16_to_cpu(align_buf[0]), data_addr);
+ iowrite16(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
+ } else {
+ align_buf[0] = cpu_to_le16(ioread16(ap->ioaddr.data_addr));
+ memcpy(trailing_buf, align_buf, 1);
}
- words++;
}
-
- return words << 1;
}
/**
* ata_data_xfer_noirq - Transfer data by PIO
- * @dev: device to target
+ * @adev: device to target
* @buf: data buffer
* @buflen: buffer length
* @write_data: read/write
@@ -4977,21 +5034,14 @@ unsigned int ata_data_xfer(struct ata_device *dev, unsigned char *buf,
*
* LOCKING:
* Inherited from caller.
- *
- * RETURNS:
- * Bytes consumed.
*/
-unsigned int ata_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,
- unsigned int buflen, int rw)
+void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
+ unsigned int buflen, int write_data)
{
unsigned long flags;
- unsigned int consumed;
-
local_irq_save(flags);
- consumed = ata_data_xfer(dev, buf, buflen, rw);
+ ata_data_xfer(adev, buf, buflen, write_data);
local_irq_restore(flags);
-
- return consumed;
}
@@ -5102,13 +5152,13 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
ata_altstatus(ap); /* flush */
switch (qc->tf.protocol) {
- case ATAPI_PROT_PIO:
+ case ATA_PROT_ATAPI:
ap->hsm_task_state = HSM_ST;
break;
- case ATAPI_PROT_NODATA:
+ case ATA_PROT_ATAPI_NODATA:
ap->hsm_task_state = HSM_ST_LAST;
break;
- case ATAPI_PROT_DMA:
+ case ATA_PROT_ATAPI_DMA:
ap->hsm_task_state = HSM_ST_LAST;
/* initiate bmdma */
ap->ops->bmdma_start(qc);
@@ -5250,15 +5300,12 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
bytes = (bc_hi << 8) | bc_lo;
/* shall be cleared to zero, indicating xfer of data */
- if (unlikely(ireason & (1 << 0)))
+ if (ireason & (1 << 0))
goto err_out;
/* make sure transfer direction matches expected */
i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
- if (unlikely(do_write != i_write))
- goto err_out;
-
- if (unlikely(!bytes))
+ if (do_write != i_write)
goto err_out;
VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);
@@ -5294,7 +5341,7 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *q
(qc->tf.flags & ATA_TFLAG_WRITE))
return 1;
- if (ata_is_atapi(qc->tf.protocol) &&
+ if (is_atapi_taskfile(&qc->tf) &&
!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
return 1;
}
@@ -5459,7 +5506,7 @@ int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
case HSM_ST:
/* complete command or read/write the data register */
- if (qc->tf.protocol == ATAPI_PROT_PIO) {
+ if (qc->tf.protocol == ATA_PROT_ATAPI) {
/* ATAPI PIO protocol */
if ((status & ATA_DRQ) == 0) {
/* No more data to transfer or device error.
@@ -5617,7 +5664,7 @@ static void ata_pio_task(struct work_struct *work)
msleep(2);
status = ata_busy_wait(ap, ATA_BUSY, 10);
if (status & ATA_BUSY) {
- ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
+ ata_port_queue_task(ap, ata_pio_task, qc, ATA_SHORT_PAUSE);
return;
}
}
@@ -5758,22 +5805,6 @@ static void fill_result_tf(struct ata_queued_cmd *qc)
ap->ops->tf_read(ap, &qc->result_tf);
}
-static void ata_verify_xfer(struct ata_queued_cmd *qc)
-{
- struct ata_device *dev = qc->dev;
-
- if (ata_tag_internal(qc->tag))
- return;
-
- if (ata_is_nodata(qc->tf.protocol))
- return;
-
- if ((dev->mwdma_mask || dev->udma_mask) && ata_is_pio(qc->tf.protocol))
- return;
-
- dev->flags &= ~ATA_DFLAG_DUBIOUS_XFER;
-}
-
/**
* ata_qc_complete - Complete an active ATA command
* @qc: Command to complete
@@ -5845,9 +5876,6 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
break;
}
- if (unlikely(dev->flags & ATA_DFLAG_DUBIOUS_XFER))
- ata_verify_xfer(qc);
-
__ata_qc_complete(qc);
} else {
if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)
@@ -5910,6 +5938,30 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
return nr_done;
}
+static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_NCQ:
+ case ATA_PROT_DMA:
+ case ATA_PROT_ATAPI_DMA:
+ return 1;
+
+ case ATA_PROT_ATAPI:
+ case ATA_PROT_PIO:
+ if (ap->flags & ATA_FLAG_PIO_DMA)
+ return 1;
+
+ /* fall through */
+
+ default:
+ return 0;
+ }
+
+ /* never reached */
+}
+
/**
* ata_qc_issue - issue taskfile to device
* @qc: command to issue to device
@@ -5926,7 +5978,6 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct ata_link *link = qc->dev->link;
- u8 prot = qc->tf.protocol;
/* Make sure only one non-NCQ command is outstanding. The
* check is skipped for old EH because it reuses active qc to
@@ -5934,7 +5985,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
*/
WARN_ON(ap->ops->error_handler && ata_tag_valid(link->active_tag));
- if (ata_is_ncq(prot)) {
+ if (qc->tf.protocol == ATA_PROT_NCQ) {
WARN_ON(link->sactive & (1 << qc->tag));
if (!link->sactive)
@@ -5950,18 +6001,17 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
qc->flags |= ATA_QCFLAG_ACTIVE;
ap->qc_active |= 1 << qc->tag;
- /* We guarantee to LLDs that they will have at least one
- * non-zero sg if the command is a data command.
- */
- BUG_ON(ata_is_data(prot) && (!qc->sg || !qc->n_elem || !qc->nbytes));
-
- /* ata_sg_setup() may update nbytes */
- qc->raw_nbytes = qc->nbytes;
-
- if (ata_is_dma(prot) || (ata_is_pio(prot) &&
- (ap->flags & ATA_FLAG_PIO_DMA)))
- if (ata_sg_setup(qc))
- goto sg_err;
+ if (ata_should_dma_map(qc)) {
+ if (qc->flags & ATA_QCFLAG_SG) {
+ if (ata_sg_setup(qc))
+ goto sg_err;
+ } else if (qc->flags & ATA_QCFLAG_SINGLE) {
+ if (ata_sg_setup_one(qc))
+ goto sg_err;
+ }
+ } else {
+ qc->flags &= ~ATA_QCFLAG_DMAMAP;
+ }
/* if device is sleeping, schedule softreset and abort the link */
if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) {
@@ -5979,6 +6029,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
return;
sg_err:
+ qc->flags &= ~ATA_QCFLAG_DMAMAP;
qc->err_mask |= AC_ERR_SYSTEM;
err:
ata_qc_complete(qc);
@@ -6013,11 +6064,11 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
switch (qc->tf.protocol) {
case ATA_PROT_PIO:
case ATA_PROT_NODATA:
- case ATAPI_PROT_PIO:
- case ATAPI_PROT_NODATA:
+ case ATA_PROT_ATAPI:
+ case ATA_PROT_ATAPI_NODATA:
qc->tf.flags |= ATA_TFLAG_POLLING;
break;
- case ATAPI_PROT_DMA:
+ case ATA_PROT_ATAPI_DMA:
if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
/* see ata_dma_blacklisted() */
BUG();
@@ -6040,7 +6091,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
ap->hsm_task_state = HSM_ST_LAST;
if (qc->tf.flags & ATA_TFLAG_POLLING)
- ata_pio_queue_task(ap, qc, 0);
+ ata_port_queue_task(ap, ata_pio_task, qc, 0);
break;
@@ -6062,7 +6113,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
if (qc->tf.flags & ATA_TFLAG_WRITE) {
/* PIO data out protocol */
ap->hsm_task_state = HSM_ST_FIRST;
- ata_pio_queue_task(ap, qc, 0);
+ ata_port_queue_task(ap, ata_pio_task, qc, 0);
/* always send first data block using
* the ata_pio_task() codepath.
@@ -6072,7 +6123,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
ap->hsm_task_state = HSM_ST;
if (qc->tf.flags & ATA_TFLAG_POLLING)
- ata_pio_queue_task(ap, qc, 0);
+ ata_port_queue_task(ap, ata_pio_task, qc, 0);
/* if polling, ata_pio_task() handles the rest.
* otherwise, interrupt handler takes over from here.
@@ -6081,8 +6132,8 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
break;
- case ATAPI_PROT_PIO:
- case ATAPI_PROT_NODATA:
+ case ATA_PROT_ATAPI:
+ case ATA_PROT_ATAPI_NODATA:
if (qc->tf.flags & ATA_TFLAG_POLLING)
ata_qc_set_polling(qc);
@@ -6093,10 +6144,10 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
/* send cdb by polling if no cdb interrupt */
if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
(qc->tf.flags & ATA_TFLAG_POLLING))
- ata_pio_queue_task(ap, qc, 0);
+ ata_port_queue_task(ap, ata_pio_task, qc, 0);
break;
- case ATAPI_PROT_DMA:
+ case ATA_PROT_ATAPI_DMA:
WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
ap->ops->tf_load(ap, &qc->tf); /* load tf registers */
@@ -6105,7 +6156,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
/* send cdb by polling if no cdb interrupt */
if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
- ata_pio_queue_task(ap, qc, 0);
+ ata_port_queue_task(ap, ata_pio_task, qc, 0);
break;
default:
@@ -6149,15 +6200,15 @@ inline unsigned int ata_host_intr(struct ata_port *ap,
*/
/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
- * The flag was turned on only for atapi devices. No
- * need to check ata_is_atapi(qc->tf.protocol) again.
+ * The flag was turned on only for atapi devices.
+ * No need to check is_atapi_taskfile(&qc->tf) again.
*/
if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
goto idle_irq;
break;
case HSM_ST_LAST:
if (qc->tf.protocol == ATA_PROT_DMA ||
- qc->tf.protocol == ATAPI_PROT_DMA) {
+ qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
/* check status of DMA engine */
host_stat = ap->ops->bmdma_status(ap);
VPRINTK("ata%u: host_stat 0x%X\n",
@@ -6199,7 +6250,7 @@ inline unsigned int ata_host_intr(struct ata_port *ap,
ata_hsm_move(ap, qc, status, 0);
if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
- qc->tf.protocol == ATAPI_PROT_DMA))
+ qc->tf.protocol == ATA_PROT_ATAPI_DMA))
ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
return 1; /* irq handled */
@@ -6721,7 +6772,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
#endif
- INIT_DELAYED_WORK(&ap->port_task, ata_pio_task);
+ INIT_DELAYED_WORK(&ap->port_task, NULL);
INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
INIT_LIST_HEAD(&ap->eh_done_q);
@@ -7538,6 +7589,7 @@ EXPORT_SYMBOL_GPL(ata_host_register);
EXPORT_SYMBOL_GPL(ata_host_activate);
EXPORT_SYMBOL_GPL(ata_host_detach);
EXPORT_SYMBOL_GPL(ata_sg_init);
+EXPORT_SYMBOL_GPL(ata_sg_init_one);
EXPORT_SYMBOL_GPL(ata_hsm_move);
EXPORT_SYMBOL_GPL(ata_qc_complete);
EXPORT_SYMBOL_GPL(ata_qc_complete_multiple);
@@ -7549,13 +7601,6 @@ EXPORT_SYMBOL_GPL(ata_std_dev_select);
EXPORT_SYMBOL_GPL(sata_print_link_status);
EXPORT_SYMBOL_GPL(ata_tf_to_fis);
EXPORT_SYMBOL_GPL(ata_tf_from_fis);
-EXPORT_SYMBOL_GPL(ata_pack_xfermask);
-EXPORT_SYMBOL_GPL(ata_unpack_xfermask);
-EXPORT_SYMBOL_GPL(ata_xfer_mask2mode);
-EXPORT_SYMBOL_GPL(ata_xfer_mode2mask);
-EXPORT_SYMBOL_GPL(ata_xfer_mode2shift);
-EXPORT_SYMBOL_GPL(ata_mode_string);
-EXPORT_SYMBOL_GPL(ata_id_xfermask);
EXPORT_SYMBOL_GPL(ata_check_status);
EXPORT_SYMBOL_GPL(ata_altstatus);
EXPORT_SYMBOL_GPL(ata_exec_command);
@@ -7598,6 +7643,7 @@ EXPORT_SYMBOL_GPL(ata_wait_register);
EXPORT_SYMBOL_GPL(ata_busy_sleep);
EXPORT_SYMBOL_GPL(ata_wait_after_reset);
EXPORT_SYMBOL_GPL(ata_wait_ready);
+EXPORT_SYMBOL_GPL(ata_port_queue_task);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
@@ -7616,20 +7662,18 @@ EXPORT_SYMBOL_GPL(ata_host_resume);
#endif /* CONFIG_PM */
EXPORT_SYMBOL_GPL(ata_id_string);
EXPORT_SYMBOL_GPL(ata_id_c_string);
+EXPORT_SYMBOL_GPL(ata_id_to_dma_mode);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
-EXPORT_SYMBOL_GPL(ata_timing_find_mode);
EXPORT_SYMBOL_GPL(ata_timing_compute);
EXPORT_SYMBOL_GPL(ata_timing_merge);
-EXPORT_SYMBOL_GPL(ata_timing_cycle2mode);
#ifdef CONFIG_PCI
EXPORT_SYMBOL_GPL(pci_test_config_bits);
EXPORT_SYMBOL_GPL(ata_pci_init_sff_host);
EXPORT_SYMBOL_GPL(ata_pci_init_bmdma);
EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host);
-EXPORT_SYMBOL_GPL(ata_pci_activate_sff_host);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
EXPORT_SYMBOL_GPL(ata_pci_remove_one);
#ifdef CONFIG_PM
@@ -7671,5 +7715,4 @@ EXPORT_SYMBOL_GPL(ata_dev_try_classify);
EXPORT_SYMBOL_GPL(ata_cable_40wire);
EXPORT_SYMBOL_GPL(ata_cable_80wire);
EXPORT_SYMBOL_GPL(ata_cable_unknown);
-EXPORT_SYMBOL_GPL(ata_cable_ignore);
EXPORT_SYMBOL_GPL(ata_cable_sata);
diff --git a/trunk/drivers/ata/libata-eh.c b/trunk/drivers/ata/libata-eh.c
index 4e31071acc02..21a81cd148e4 100644
--- a/trunk/drivers/ata/libata-eh.c
+++ b/trunk/drivers/ata/libata-eh.c
@@ -46,26 +46,9 @@
#include "libata.h"
enum {
- /* speed down verdicts */
ATA_EH_SPDN_NCQ_OFF = (1 << 0),
ATA_EH_SPDN_SPEED_DOWN = (1 << 1),
ATA_EH_SPDN_FALLBACK_TO_PIO = (1 << 2),
- ATA_EH_SPDN_KEEP_ERRORS = (1 << 3),
-
- /* error flags */
- ATA_EFLAG_IS_IO = (1 << 0),
- ATA_EFLAG_DUBIOUS_XFER = (1 << 1),
-
- /* error categories */
- ATA_ECAT_NONE = 0,
- ATA_ECAT_ATA_BUS = 1,
- ATA_ECAT_TOUT_HSM = 2,
- ATA_ECAT_UNK_DEV = 3,
- ATA_ECAT_DUBIOUS_NONE = 4,
- ATA_ECAT_DUBIOUS_ATA_BUS = 5,
- ATA_ECAT_DUBIOUS_TOUT_HSM = 6,
- ATA_ECAT_DUBIOUS_UNK_DEV = 7,
- ATA_ECAT_NR = 8,
};
/* Waiting in ->prereset can never be reliable. It's sometimes nice
@@ -230,13 +213,12 @@ void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset,
if (offset < 0)
ata_port_desc(ap, "%s %s%llu@0x%llx", name, type, len, start);
else
- ata_port_desc(ap, "%s 0x%llx", name,
- start + (unsigned long long)offset);
+ ata_port_desc(ap, "%s 0x%llx", name, start + offset);
}
#endif /* CONFIG_PCI */
-static void ata_ering_record(struct ata_ering *ering, unsigned int eflags,
+static void ata_ering_record(struct ata_ering *ering, int is_io,
unsigned int err_mask)
{
struct ata_ering_entry *ent;
@@ -247,20 +229,11 @@ static void ata_ering_record(struct ata_ering *ering, unsigned int eflags,
ering->cursor %= ATA_ERING_SIZE;
ent = &ering->ring[ering->cursor];
- ent->eflags = eflags;
+ ent->is_io = is_io;
ent->err_mask = err_mask;
ent->timestamp = get_jiffies_64();
}
-static struct ata_ering_entry *ata_ering_top(struct ata_ering *ering)
-{
- struct ata_ering_entry *ent = &ering->ring[ering->cursor];
-
- if (ent->err_mask)
- return ent;
- return NULL;
-}
-
static void ata_ering_clear(struct ata_ering *ering)
{
memset(ering, 0, sizeof(*ering));
@@ -472,20 +445,9 @@ void ata_scsi_error(struct Scsi_Host *host)
spin_lock_irqsave(ap->lock, flags);
__ata_port_for_each_link(link, ap) {
- struct ata_eh_context *ehc = &link->eh_context;
- struct ata_device *dev;
-
memset(&link->eh_context, 0, sizeof(link->eh_context));
link->eh_context.i = link->eh_info;
memset(&link->eh_info, 0, sizeof(link->eh_info));
-
- ata_link_for_each_dev(dev, link) {
- int devno = dev->devno;
-
- ehc->saved_xfer_mode[devno] = dev->xfer_mode;
- if (ata_ncq_enabled(dev))
- ehc->saved_ncq_enabled |= 1 << devno;
- }
}
ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
@@ -1298,10 +1260,10 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc)
/* is it pointless to prefer PIO for "safety reasons"? */
if (ap->flags & ATA_FLAG_PIO_DMA) {
- tf.protocol = ATAPI_PROT_DMA;
+ tf.protocol = ATA_PROT_ATAPI_DMA;
tf.feature |= ATAPI_PKT_DMA;
} else {
- tf.protocol = ATAPI_PROT_PIO;
+ tf.protocol = ATA_PROT_ATAPI;
tf.lbam = SCSI_SENSE_BUFFERSIZE;
tf.lbah = 0;
}
@@ -1489,29 +1451,20 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
return action;
}
-static int ata_eh_categorize_error(unsigned int eflags, unsigned int err_mask,
- int *xfer_ok)
+static int ata_eh_categorize_error(int is_io, unsigned int err_mask)
{
- int base = 0;
-
- if (!(eflags & ATA_EFLAG_DUBIOUS_XFER))
- *xfer_ok = 1;
-
- if (!*xfer_ok)
- base = ATA_ECAT_DUBIOUS_NONE;
-
if (err_mask & AC_ERR_ATA_BUS)
- return base + ATA_ECAT_ATA_BUS;
+ return 1;
if (err_mask & AC_ERR_TIMEOUT)
- return base + ATA_ECAT_TOUT_HSM;
+ return 2;
- if (eflags & ATA_EFLAG_IS_IO) {
+ if (is_io) {
if (err_mask & AC_ERR_HSM)
- return base + ATA_ECAT_TOUT_HSM;
+ return 2;
if ((err_mask &
(AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
- return base + ATA_ECAT_UNK_DEV;
+ return 3;
}
return 0;
@@ -1519,22 +1472,18 @@ static int ata_eh_categorize_error(unsigned int eflags, unsigned int err_mask,
struct speed_down_verdict_arg {
u64 since;
- int xfer_ok;
- int nr_errors[ATA_ECAT_NR];
+ int nr_errors[4];
};
static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
{
struct speed_down_verdict_arg *arg = void_arg;
- int cat;
+ int cat = ata_eh_categorize_error(ent->is_io, ent->err_mask);
if (ent->timestamp < arg->since)
return -1;
- cat = ata_eh_categorize_error(ent->eflags, ent->err_mask,
- &arg->xfer_ok);
arg->nr_errors[cat]++;
-
return 0;
}
@@ -1546,48 +1495,22 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
* whether NCQ needs to be turned off, transfer speed should be
* stepped down, or falling back to PIO is necessary.
*
- * ECAT_ATA_BUS : ATA_BUS error for any command
- *
- * ECAT_TOUT_HSM : TIMEOUT for any command or HSM violation for
- * IO commands
- *
- * ECAT_UNK_DEV : Unknown DEV error for IO commands
- *
- * ECAT_DUBIOUS_* : Identical to above three but occurred while
- * data transfer hasn't been verified.
- *
- * Verdicts are
- *
- * NCQ_OFF : Turn off NCQ.
- *
- * SPEED_DOWN : Speed down transfer speed but don't fall back
- * to PIO.
- *
- * FALLBACK_TO_PIO : Fall back to PIO.
- *
- * Even if multiple verdicts are returned, only one action is
- * taken per error. An action triggered by non-DUBIOUS errors
- * clears ering, while one triggered by DUBIOUS_* errors doesn't.
- * This is to expedite speed down decisions right after device is
- * initially configured.
+ * Cat-1 is ATA_BUS error for any command.
*
- * The followings are speed down rules. #1 and #2 deal with
- * DUBIOUS errors.
+ * Cat-2 is TIMEOUT for any command or HSM violation for known
+ * supported commands.
*
- * 1. If more than one DUBIOUS_ATA_BUS or DUBIOUS_TOUT_HSM errors
- * occurred during last 5 mins, SPEED_DOWN and FALLBACK_TO_PIO.
+ * Cat-3 is is unclassified DEV error for known supported
+ * command.
*
- * 2. If more than one DUBIOUS_TOUT_HSM or DUBIOUS_UNK_DEV errors
- * occurred during last 5 mins, NCQ_OFF.
+ * NCQ needs to be turned off if there have been more than 3
+ * Cat-2 + Cat-3 errors during last 10 minutes.
*
- * 3. If more than 8 ATA_BUS, TOUT_HSM or UNK_DEV errors
- * ocurred during last 5 mins, FALLBACK_TO_PIO
+ * Speed down is necessary if there have been more than 3 Cat-1 +
+ * Cat-2 errors or 10 Cat-3 errors during last 10 minutes.
*
- * 4. If more than 3 TOUT_HSM or UNK_DEV errors occurred
- * during last 10 mins, NCQ_OFF.
- *
- * 5. If more than 3 ATA_BUS or TOUT_HSM errors, or more than 6
- * UNK_DEV errors occurred during last 10 mins, SPEED_DOWN.
+ * Falling back to PIO mode is necessary if there have been more
+ * than 10 Cat-1 + Cat-2 + Cat-3 errors during last 5 minutes.
*
* LOCKING:
* Inherited from caller.
@@ -1602,46 +1525,31 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev)
struct speed_down_verdict_arg arg;
unsigned int verdict = 0;
- /* scan past 5 mins of error history */
- memset(&arg, 0, sizeof(arg));
- arg.since = j64 - min(j64, j5mins);
- ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
-
- if (arg.nr_errors[ATA_ECAT_DUBIOUS_ATA_BUS] +
- arg.nr_errors[ATA_ECAT_DUBIOUS_TOUT_HSM] > 1)
- verdict |= ATA_EH_SPDN_SPEED_DOWN |
- ATA_EH_SPDN_FALLBACK_TO_PIO | ATA_EH_SPDN_KEEP_ERRORS;
-
- if (arg.nr_errors[ATA_ECAT_DUBIOUS_TOUT_HSM] +
- arg.nr_errors[ATA_ECAT_DUBIOUS_UNK_DEV] > 1)
- verdict |= ATA_EH_SPDN_NCQ_OFF | ATA_EH_SPDN_KEEP_ERRORS;
-
- if (arg.nr_errors[ATA_ECAT_ATA_BUS] +
- arg.nr_errors[ATA_ECAT_TOUT_HSM] +
- arg.nr_errors[ATA_ECAT_UNK_DEV] > 6)
- verdict |= ATA_EH_SPDN_FALLBACK_TO_PIO;
-
/* scan past 10 mins of error history */
memset(&arg, 0, sizeof(arg));
arg.since = j64 - min(j64, j10mins);
ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
- if (arg.nr_errors[ATA_ECAT_TOUT_HSM] +
- arg.nr_errors[ATA_ECAT_UNK_DEV] > 3)
+ if (arg.nr_errors[2] + arg.nr_errors[3] > 3)
verdict |= ATA_EH_SPDN_NCQ_OFF;
-
- if (arg.nr_errors[ATA_ECAT_ATA_BUS] +
- arg.nr_errors[ATA_ECAT_TOUT_HSM] > 3 ||
- arg.nr_errors[ATA_ECAT_UNK_DEV] > 6)
+ if (arg.nr_errors[1] + arg.nr_errors[2] > 3 || arg.nr_errors[3] > 10)
verdict |= ATA_EH_SPDN_SPEED_DOWN;
+ /* scan past 3 mins of error history */
+ memset(&arg, 0, sizeof(arg));
+ arg.since = j64 - min(j64, j5mins);
+ ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
+
+ if (arg.nr_errors[1] + arg.nr_errors[2] + arg.nr_errors[3] > 10)
+ verdict |= ATA_EH_SPDN_FALLBACK_TO_PIO;
+
return verdict;
}
/**
* ata_eh_speed_down - record error and speed down if necessary
* @dev: Failed device
- * @eflags: mask of ATA_EFLAG_* flags
+ * @is_io: Did the device fail during normal IO?
* @err_mask: err_mask of the error
*
* Record error and examine error history to determine whether
@@ -1655,20 +1563,18 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev)
* RETURNS:
* Determined recovery action.
*/
-static unsigned int ata_eh_speed_down(struct ata_device *dev,
- unsigned int eflags, unsigned int err_mask)
+static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
+ unsigned int err_mask)
{
- struct ata_link *link = dev->link;
- int xfer_ok = 0;
unsigned int verdict;
unsigned int action = 0;
/* don't bother if Cat-0 error */
- if (ata_eh_categorize_error(eflags, err_mask, &xfer_ok) == 0)
+ if (ata_eh_categorize_error(is_io, err_mask) == 0)
return 0;
/* record error and determine whether speed down is necessary */
- ata_ering_record(&dev->ering, eflags, err_mask);
+ ata_ering_record(&dev->ering, is_io, err_mask);
verdict = ata_eh_speed_down_verdict(dev);
/* turn off NCQ? */
@@ -1684,7 +1590,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
/* speed down? */
if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
/* speed down SATA link speed if possible */
- if (sata_down_spd_limit(link) == 0) {
+ if (sata_down_spd_limit(dev->link) == 0) {
action |= ATA_EH_HARDRESET;
goto done;
}
@@ -1712,10 +1618,10 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
}
/* Fall back to PIO? Slowing down to PIO is meaningless for
- * SATA ATA devices. Consider it only for PATA and SATAPI.
+ * SATA. Consider it only for PATA.
*/
if ((verdict & ATA_EH_SPDN_FALLBACK_TO_PIO) && (dev->spdn_cnt >= 2) &&
- (link->ap->cbl != ATA_CBL_SATA || dev->class == ATA_DEV_ATAPI) &&
+ (dev->link->ap->cbl != ATA_CBL_SATA) &&
(dev->xfer_shift != ATA_SHIFT_PIO)) {
if (ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO) == 0) {
dev->spdn_cnt = 0;
@@ -1727,8 +1633,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
return 0;
done:
/* device has been slowed down, blow error history */
- if (!(verdict & ATA_EH_SPDN_KEEP_ERRORS))
- ata_ering_clear(&dev->ering);
+ ata_ering_clear(&dev->ering);
return action;
}
@@ -1748,8 +1653,8 @@ static void ata_eh_link_autopsy(struct ata_link *link)
struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context;
struct ata_device *dev;
- unsigned int all_err_mask = 0, eflags = 0;
- int tag;
+ unsigned int all_err_mask = 0;
+ int tag, is_io = 0;
u32 serror;
int rc;
@@ -1808,15 +1713,15 @@ static void ata_eh_link_autopsy(struct ata_link *link)
ehc->i.dev = qc->dev;
all_err_mask |= qc->err_mask;
if (qc->flags & ATA_QCFLAG_IO)
- eflags |= ATA_EFLAG_IS_IO;
+ is_io = 1;
}
/* enforce default EH actions */
if (ap->pflags & ATA_PFLAG_FROZEN ||
all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
ehc->i.action |= ATA_EH_SOFTRESET;
- else if (((eflags & ATA_EFLAG_IS_IO) && all_err_mask) ||
- (!(eflags & ATA_EFLAG_IS_IO) && (all_err_mask & ~AC_ERR_DEV)))
+ else if ((is_io && all_err_mask) ||
+ (!is_io && (all_err_mask & ~AC_ERR_DEV)))
ehc->i.action |= ATA_EH_REVALIDATE;
/* If we have offending qcs and the associated failed device,
@@ -1838,11 +1743,8 @@ static void ata_eh_link_autopsy(struct ata_link *link)
ata_dev_enabled(link->device))))
dev = link->device;
- if (dev) {
- if (dev->flags & ATA_DFLAG_DUBIOUS_XFER)
- eflags |= ATA_EFLAG_DUBIOUS_XFER;
- ehc->i.action |= ata_eh_speed_down(dev, eflags, all_err_mask);
- }
+ if (dev)
+ ehc->i.action |= ata_eh_speed_down(dev, is_io, all_err_mask);
DPRINTK("EXIT\n");
}
@@ -1978,8 +1880,8 @@ static void ata_eh_link_report(struct ata_link *link)
[ATA_PROT_PIO] = "pio",
[ATA_PROT_DMA] = "dma",
[ATA_PROT_NCQ] = "ncq",
- [ATAPI_PROT_PIO] = "pio",
- [ATAPI_PROT_DMA] = "dma",
+ [ATA_PROT_ATAPI] = "pio",
+ [ATA_PROT_ATAPI_DMA] = "dma",
};
snprintf(data_buf, sizeof(data_buf), " %s %u %s",
@@ -1987,7 +1889,7 @@ static void ata_eh_link_report(struct ata_link *link)
dma_str[qc->dma_dir]);
}
- if (ata_is_atapi(qc->tf.protocol))
+ if (is_atapi_taskfile(&qc->tf))
snprintf(cdb_buf, sizeof(cdb_buf),
"cdb %02x %02x %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x\n ",
@@ -2427,58 +2329,6 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
return rc;
}
-/**
- * ata_set_mode - Program timings and issue SET FEATURES - XFER
- * @link: link on which timings will be programmed
- * @r_failed_dev: out paramter for failed device
- *
- * Set ATA device disk transfer mode (PIO3, UDMA6, etc.). If
- * ata_set_mode() fails, pointer to the failing device is
- * returned in @r_failed_dev.
- *
- * LOCKING:
- * PCI/etc. bus probe sem.
- *
- * RETURNS:
- * 0 on success, negative errno otherwise
- */
-int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
-{
- struct ata_port *ap = link->ap;
- struct ata_device *dev;
- int rc;
-
- /* if data transfer is verified, clear DUBIOUS_XFER on ering top */
- ata_link_for_each_dev(dev, link) {
- if (!(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) {
- struct ata_ering_entry *ent;
-
- ent = ata_ering_top(&dev->ering);
- if (ent)
- ent->eflags &= ~ATA_EFLAG_DUBIOUS_XFER;
- }
- }
-
- /* has private set_mode? */
- if (ap->ops->set_mode)
- rc = ap->ops->set_mode(link, r_failed_dev);
- else
- rc = ata_do_set_mode(link, r_failed_dev);
-
- /* if transfer mode has changed, set DUBIOUS_XFER on device */
- ata_link_for_each_dev(dev, link) {
- struct ata_eh_context *ehc = &link->eh_context;
- u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno];
- u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno));
-
- if (dev->xfer_mode != saved_xfer_mode ||
- ata_ncq_enabled(dev) != saved_ncq)
- dev->flags |= ATA_DFLAG_DUBIOUS_XFER;
- }
-
- return rc;
-}
-
static int ata_link_nr_enabled(struct ata_link *link)
{
struct ata_device *dev;
@@ -2525,24 +2375,6 @@ static int ata_eh_skip_recovery(struct ata_link *link)
return 1;
}
-static int ata_eh_schedule_probe(struct ata_device *dev)
-{
- struct ata_eh_context *ehc = &dev->link->eh_context;
-
- if (!(ehc->i.probe_mask & (1 << dev->devno)) ||
- (ehc->did_probe_mask & (1 << dev->devno)))
- return 0;
-
- ata_eh_detach_dev(dev);
- ata_dev_init(dev);
- ehc->did_probe_mask |= (1 << dev->devno);
- ehc->i.action |= ATA_EH_SOFTRESET;
- ehc->saved_xfer_mode[dev->devno] = 0;
- ehc->saved_ncq_enabled &= ~(1 << dev->devno);
-
- return 1;
-}
-
static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
@@ -2574,9 +2406,16 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
if (ata_link_offline(dev->link))
ata_eh_detach_dev(dev);
- /* schedule probe if necessary */
- if (ata_eh_schedule_probe(dev))
+ /* probe if requested */
+ if ((ehc->i.probe_mask & (1 << dev->devno)) &&
+ !(ehc->did_probe_mask & (1 << dev->devno))) {
+ ata_eh_detach_dev(dev);
+ ata_dev_init(dev);
+
ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+ ehc->did_probe_mask |= (1 << dev->devno);
+ ehc->i.action |= ATA_EH_SOFTRESET;
+ }
return 1;
} else {
@@ -2653,9 +2492,14 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
if (dev->flags & ATA_DFLAG_DETACH)
ata_eh_detach_dev(dev);
- /* schedule probe if necessary */
- if (!ata_dev_enabled(dev))
- ata_eh_schedule_probe(dev);
+ if (!ata_dev_enabled(dev) &&
+ ((ehc->i.probe_mask & (1 << dev->devno)) &&
+ !(ehc->did_probe_mask & (1 << dev->devno)))) {
+ ata_eh_detach_dev(dev);
+ ata_dev_init(dev);
+ ehc->did_probe_mask |= (1 << dev->devno);
+ ehc->i.action |= ATA_EH_SOFTRESET;
+ }
}
}
@@ -2903,7 +2747,6 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
if (ap->ops->port_suspend)
rc = ap->ops->port_suspend(ap, ap->pm_mesg);
- ata_acpi_set_state(ap, PMSG_SUSPEND);
out:
/* report result */
spin_lock_irqsave(ap->lock, flags);
@@ -2949,8 +2792,6 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
WARN_ON(!(ap->pflags & ATA_PFLAG_SUSPENDED));
- ata_acpi_set_state(ap, PMSG_ON);
-
if (ap->ops->port_resume)
rc = ap->ops->port_resume(ap);
diff --git a/trunk/drivers/ata/libata-scsi.c b/trunk/drivers/ata/libata-scsi.c
index 3fd08201bef4..14daf4848f09 100644
--- a/trunk/drivers/ata/libata-scsi.c
+++ b/trunk/drivers/ata/libata-scsi.c
@@ -517,7 +517,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
qc->scsicmd = cmd;
qc->scsidone = done;
- qc->sg = scsi_sglist(cmd);
+ qc->__sg = scsi_sglist(cmd);
qc->n_elem = scsi_sg_count(cmd);
} else {
cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1);
@@ -2210,7 +2210,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
/* sector size */
ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8);
- ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE & 0xff);
+ ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE);
} else {
/* sector count, 64-bit */
ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7));
@@ -2224,7 +2224,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
/* sector size */
ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8);
- ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE & 0xff);
+ ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE);
}
return 0;
@@ -2331,7 +2331,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
DPRINTK("ATAPI request sense\n");
/* FIXME: is this needed? */
- memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+ memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
ap->ops->tf_read(ap, &qc->tf);
@@ -2341,9 +2341,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
ata_qc_reinit(qc);
- /* setup sg table and init transfer direction */
- sg_init_one(&qc->sgent, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
- ata_sg_init(qc, &qc->sgent, 1);
+ ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
qc->dma_dir = DMA_FROM_DEVICE;
memset(&qc->cdb, 0, qc->dev->cdb_len);
@@ -2354,10 +2352,10 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
qc->tf.command = ATA_CMD_PACKET;
if (ata_pio_use_silly(ap)) {
- qc->tf.protocol = ATAPI_PROT_DMA;
+ qc->tf.protocol = ATA_PROT_ATAPI_DMA;
qc->tf.feature |= ATAPI_PKT_DMA;
} else {
- qc->tf.protocol = ATAPI_PROT_PIO;
+ qc->tf.protocol = ATA_PROT_ATAPI;
qc->tf.lbam = SCSI_SENSE_BUFFERSIZE;
qc->tf.lbah = 0;
}
@@ -2528,12 +2526,12 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
if (using_pio || nodata) {
/* no data, or PIO data xfer */
if (nodata)
- qc->tf.protocol = ATAPI_PROT_NODATA;
+ qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
else
- qc->tf.protocol = ATAPI_PROT_PIO;
+ qc->tf.protocol = ATA_PROT_ATAPI;
} else {
/* DMA data xfer */
- qc->tf.protocol = ATAPI_PROT_DMA;
+ qc->tf.protocol = ATA_PROT_ATAPI_DMA;
qc->tf.feature |= ATAPI_PKT_DMA;
if (atapi_dmadir && (scmd->sc_data_direction != DMA_TO_DEVICE))
@@ -2692,24 +2690,6 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN)
goto invalid_fld;
- /*
- * Filter TPM commands by default. These provide an
- * essentially uncontrolled encrypted "back door" between
- * applications and the disk. Set libata.allow_tpm=1 if you
- * have a real reason for wanting to use them. This ensures
- * that installed software cannot easily mess stuff up without
- * user intent. DVR type users will probably ship with this enabled
- * for movie content management.
- *
- * Note that for ATA8 we can issue a DCS change and DCS freeze lock
- * for this and should do in future but that it is not sufficient as
- * DCS is an optional feature set. Thus we also do the software filter
- * so that we comply with the TC consortium stated goal that the user
- * can turn off TC features of their system.
- */
- if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm)
- goto invalid_fld;
-
/* We may not issue DMA commands if no DMA mode is set */
if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
goto invalid_fld;
diff --git a/trunk/drivers/ata/libata-sff.c b/trunk/drivers/ata/libata-sff.c
index 60cd4b179766..b7ac80b4b1fb 100644
--- a/trunk/drivers/ata/libata-sff.c
+++ b/trunk/drivers/ata/libata-sff.c
@@ -147,9 +147,7 @@ void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
* @tf: ATA taskfile register set for storing input
*
* Reads ATA taskfile registers for currently-selected device
- * into @tf. Assumes the device has a fully SFF compliant task file
- * layout and behaviour. If you device does not (eg has a different
- * status method) then you will need to provide a replacement tf_read
+ * into @tf.
*
* LOCKING:
* Inherited from caller.
@@ -158,7 +156,7 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
- tf->command = ata_check_status(ap);
+ tf->command = ata_chk_status(ap);
tf->feature = ioread8(ioaddr->error_addr);
tf->nsect = ioread8(ioaddr->nsect_addr);
tf->lbal = ioread8(ioaddr->lbal_addr);
@@ -417,7 +415,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
ap->hsm_task_state = HSM_ST_IDLE;
if (qc && (qc->tf.protocol == ATA_PROT_DMA ||
- qc->tf.protocol == ATAPI_PROT_DMA)) {
+ qc->tf.protocol == ATA_PROT_ATAPI_DMA)) {
u8 host_stat;
host_stat = ap->ops->bmdma_status(ap);
@@ -551,7 +549,7 @@ int ata_pci_init_bmdma(struct ata_host *host)
return rc;
/* request and iomap DMA region */
- rc = pcim_iomap_regions(pdev, 1 << 4, dev_driver_string(gdev));
+ rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME);
if (rc) {
dev_printk(KERN_ERR, gdev, "failed to request/iomap BAR4\n");
return -ENOMEM;
@@ -621,8 +619,7 @@ int ata_pci_init_sff_host(struct ata_host *host)
continue;
}
- rc = pcim_iomap_regions(pdev, 0x3 << base,
- dev_driver_string(gdev));
+ rc = pcim_iomap_regions(pdev, 0x3 << base, DRV_NAME);
if (rc) {
dev_printk(KERN_WARNING, gdev,
"failed to request/iomap BARs for port %d "
@@ -713,99 +710,6 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
return rc;
}
-/**
- * ata_pci_activate_sff_host - start SFF host, request IRQ and register it
- * @host: target SFF ATA host
- * @irq_handler: irq_handler used when requesting IRQ(s)
- * @sht: scsi_host_template to use when registering the host
- *
- * This is the counterpart of ata_host_activate() for SFF ATA
- * hosts. This separate helper is necessary because SFF hosts
- * use two separate interrupts in legacy mode.
- *
- * LOCKING:
- * Inherited from calling layer (may sleep).
- *
- * RETURNS:
- * 0 on success, -errno otherwise.
- */
-int ata_pci_activate_sff_host(struct ata_host *host,
- irq_handler_t irq_handler,
- struct scsi_host_template *sht)
-{
- struct device *dev = host->dev;
- struct pci_dev *pdev = to_pci_dev(dev);
- const char *drv_name = dev_driver_string(host->dev);
- int legacy_mode = 0, rc;
-
- rc = ata_host_start(host);
- if (rc)
- return rc;
-
- if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
- u8 tmp8, mask;
-
- /* TODO: What if one channel is in native mode ... */
- pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
- mask = (1 << 2) | (1 << 0);
- if ((tmp8 & mask) != mask)
- legacy_mode = 1;
-#if defined(CONFIG_NO_ATA_LEGACY)
- /* Some platforms with PCI limits cannot address compat
- port space. In that case we punt if their firmware has
- left a device in compatibility mode */
- if (legacy_mode) {
- printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n");
- return -EOPNOTSUPP;
- }
-#endif
- }
-
- if (!devres_open_group(dev, NULL, GFP_KERNEL))
- return -ENOMEM;
-
- if (!legacy_mode && pdev->irq) {
- rc = devm_request_irq(dev, pdev->irq, irq_handler,
- IRQF_SHARED, drv_name, host);
- if (rc)
- goto out;
-
- ata_port_desc(host->ports[0], "irq %d", pdev->irq);
- ata_port_desc(host->ports[1], "irq %d", pdev->irq);
- } else if (legacy_mode) {
- if (!ata_port_is_dummy(host->ports[0])) {
- rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev),
- irq_handler, IRQF_SHARED,
- drv_name, host);
- if (rc)
- goto out;
-
- ata_port_desc(host->ports[0], "irq %d",
- ATA_PRIMARY_IRQ(pdev));
- }
-
- if (!ata_port_is_dummy(host->ports[1])) {
- rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev),
- irq_handler, IRQF_SHARED,
- drv_name, host);
- if (rc)
- goto out;
-
- ata_port_desc(host->ports[1], "irq %d",
- ATA_SECONDARY_IRQ(pdev));
- }
- }
-
- rc = ata_host_register(host, sht);
- out:
- if (rc == 0)
- devres_remove_group(dev, NULL);
- else
- devres_release_group(dev, NULL);
-
- return rc;
-}
-
/**
* ata_pci_init_one - Initialize/register PCI IDE host controller
* @pdev: Controller to be initialized
@@ -835,6 +739,8 @@ int ata_pci_init_one(struct pci_dev *pdev,
struct device *dev = &pdev->dev;
const struct ata_port_info *pi = NULL;
struct ata_host *host = NULL;
+ u8 mask;
+ int legacy_mode = 0;
int i, rc;
DPRINTK("ENTER\n");
@@ -856,24 +762,95 @@ int ata_pci_init_one(struct pci_dev *pdev,
if (!devres_open_group(dev, NULL, GFP_KERNEL))
return -ENOMEM;
+ /* FIXME: Really for ATA it isn't safe because the device may be
+ multi-purpose and we want to leave it alone if it was already
+ enabled. Secondly for shared use as Arjan says we want refcounting
+
+ Checking dev->is_enabled is insufficient as this is not set at
+ boot for the primary video which is BIOS enabled
+ */
+
rc = pcim_enable_device(pdev);
if (rc)
- goto out;
+ goto err_out;
- /* prepare and activate SFF host */
+ if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
+ u8 tmp8;
+
+ /* TODO: What if one channel is in native mode ... */
+ pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
+ mask = (1 << 2) | (1 << 0);
+ if ((tmp8 & mask) != mask)
+ legacy_mode = 1;
+#if defined(CONFIG_NO_ATA_LEGACY)
+ /* Some platforms with PCI limits cannot address compat
+ port space. In that case we punt if their firmware has
+ left a device in compatibility mode */
+ if (legacy_mode) {
+ printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n");
+ rc = -EOPNOTSUPP;
+ goto err_out;
+ }
+#endif
+ }
+
+ /* prepare host */
rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
if (rc)
- goto out;
+ goto err_out;
pci_set_master(pdev);
- rc = ata_pci_activate_sff_host(host, pi->port_ops->irq_handler,
- pi->sht);
- out:
- if (rc == 0)
- devres_remove_group(&pdev->dev, NULL);
- else
- devres_release_group(&pdev->dev, NULL);
+ /* start host and request IRQ */
+ rc = ata_host_start(host);
+ if (rc)
+ goto err_out;
+
+ if (!legacy_mode && pdev->irq) {
+ /* We may have no IRQ assigned in which case we can poll. This
+ shouldn't happen on a sane system but robustness is cheap
+ in this case */
+ rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler,
+ IRQF_SHARED, DRV_NAME, host);
+ if (rc)
+ goto err_out;
+
+ ata_port_desc(host->ports[0], "irq %d", pdev->irq);
+ ata_port_desc(host->ports[1], "irq %d", pdev->irq);
+ } else if (legacy_mode) {
+ if (!ata_port_is_dummy(host->ports[0])) {
+ rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev),
+ pi->port_ops->irq_handler,
+ IRQF_SHARED, DRV_NAME, host);
+ if (rc)
+ goto err_out;
+
+ ata_port_desc(host->ports[0], "irq %d",
+ ATA_PRIMARY_IRQ(pdev));
+ }
+
+ if (!ata_port_is_dummy(host->ports[1])) {
+ rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev),
+ pi->port_ops->irq_handler,
+ IRQF_SHARED, DRV_NAME, host);
+ if (rc)
+ goto err_out;
+
+ ata_port_desc(host->ports[1], "irq %d",
+ ATA_SECONDARY_IRQ(pdev));
+ }
+ }
+
+ /* register */
+ rc = ata_host_register(host, pi->sht);
+ if (rc)
+ goto err_out;
+
+ devres_remove_group(dev, NULL);
+ return 0;
+
+err_out:
+ devres_release_group(dev, NULL);
return rc;
}
diff --git a/trunk/drivers/ata/libata.h b/trunk/drivers/ata/libata.h
index 409ffb9af163..bbe59c2fd1e2 100644
--- a/trunk/drivers/ata/libata.h
+++ b/trunk/drivers/ata/libata.h
@@ -60,7 +60,6 @@ extern int atapi_dmadir;
extern int atapi_passthru16;
extern int libata_fua;
extern int libata_noacpi;
-extern int libata_allow_tpm;
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
u64 block, u32 n_block, unsigned int tf_flags,
@@ -86,6 +85,7 @@ extern int ata_dev_configure(struct ata_device *dev);
extern int sata_down_spd_limit(struct ata_link *link);
extern int sata_set_spd_needed(struct ata_link *link);
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
+extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
extern void ata_sg_clean(struct ata_queued_cmd *qc);
extern void ata_qc_free(struct ata_queued_cmd *qc);
extern void ata_qc_issue(struct ata_queued_cmd *qc);
@@ -113,7 +113,6 @@ extern int ata_acpi_on_suspend(struct ata_port *ap);
extern void ata_acpi_on_resume(struct ata_port *ap);
extern int ata_acpi_on_devcfg(struct ata_device *dev);
extern void ata_acpi_on_disable(struct ata_device *dev);
-extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state);
#else
static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { }
static inline void ata_acpi_associate(struct ata_host *host) { }
@@ -122,8 +121,6 @@ static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
static inline void ata_acpi_on_resume(struct ata_port *ap) { }
static inline int ata_acpi_on_devcfg(struct ata_device *dev) { return 0; }
static inline void ata_acpi_on_disable(struct ata_device *dev) { }
-static inline void ata_acpi_set_state(struct ata_port *ap,
- pm_message_t state) { }
#endif
/* libata-scsi.c */
@@ -186,7 +183,6 @@ extern void ata_eh_report(struct ata_port *ap);
extern int ata_eh_reset(struct ata_link *link, int classify,
ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
ata_reset_fn_t hardreset, ata_postreset_fn_t postreset);
-extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
ata_postreset_fn_t postreset,
diff --git a/trunk/drivers/ata/pata_acpi.c b/trunk/drivers/ata/pata_acpi.c
index 244098a80ce4..e4542ab9c7f8 100644
--- a/trunk/drivers/ata/pata_acpi.c
+++ b/trunk/drivers/ata/pata_acpi.c
@@ -81,6 +81,17 @@ static void pacpi_error_handler(struct ata_port *ap)
NULL, ata_std_postreset);
}
+/* Welcome to ACPI, bring a bucket */
+static const unsigned int pio_cycle[7] = {
+ 600, 383, 240, 180, 120, 100, 80
+};
+static const unsigned int mwdma_cycle[5] = {
+ 480, 150, 120, 100, 80
+};
+static const unsigned int udma_cycle[7] = {
+ 120, 80, 60, 45, 30, 20, 15
+};
+
/**
* pacpi_discover_modes - filter non ACPI modes
* @adev: ATA device
@@ -92,20 +103,56 @@ static void pacpi_error_handler(struct ata_port *ap)
static unsigned long pacpi_discover_modes(struct ata_port *ap, struct ata_device *adev)
{
+ int unit = adev->devno;
struct pata_acpi *acpi = ap->private_data;
+ int i;
+ u32 t;
+ unsigned long mask = (0x7f << ATA_SHIFT_UDMA) | (0x7 << ATA_SHIFT_MWDMA) | (0x1F << ATA_SHIFT_PIO);
+
struct ata_acpi_gtm probe;
- unsigned int xfer_mask;
probe = acpi->gtm;
+ /* We always use the 0 slot for crap hardware */
+ if (!(probe.flags & 0x10))
+ unit = 0;
+
ata_acpi_gtm(ap, &probe);
- xfer_mask = ata_acpi_gtm_xfermask(adev, &probe);
+ /* Start by scanning for PIO modes */
+ for (i = 0; i < 7; i++) {
+ t = probe.drive[unit].pio;
+ if (t <= pio_cycle[i]) {
+ mask |= (2 << (ATA_SHIFT_PIO + i)) - 1;
+ break;
+ }
+ }
- if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))
+ /* See if we have MWDMA or UDMA data. We don't bother with MWDMA
+ if UDMA is availabe as this means the BIOS set UDMA and our
+ error changedown if it works is UDMA to PIO anyway */
+ if (probe.flags & (1 << (2 * unit))) {
+ /* MWDMA */
+ for (i = 0; i < 5; i++) {
+ t = probe.drive[unit].dma;
+ if (t <= mwdma_cycle[i]) {
+ mask |= (2 << (ATA_SHIFT_MWDMA + i)) - 1;
+ break;
+ }
+ }
+ } else {
+ /* UDMA */
+ for (i = 0; i < 7; i++) {
+ t = probe.drive[unit].dma;
+ if (t <= udma_cycle[i]) {
+ mask |= (2 << (ATA_SHIFT_UDMA + i)) - 1;
+ break;
+ }
+ }
+ }
+ if (mask & (0xF8 << ATA_SHIFT_UDMA))
ap->cbl = ATA_CBL_PATA80;
-
- return xfer_mask;
+ return mask;
}
/**
@@ -133,14 +180,12 @@ static void pacpi_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
int unit = adev->devno;
struct pata_acpi *acpi = ap->private_data;
- const struct ata_timing *t;
if (!(acpi->gtm.flags & 0x10))
unit = 0;
/* Now stuff the nS values into the structure */
- t = ata_timing_find_mode(adev->pio_mode);
- acpi->gtm.drive[unit].pio = t->cycle;
+ acpi->gtm.drive[unit].pio = pio_cycle[adev->pio_mode - XFER_PIO_0];
ata_acpi_stm(ap, &acpi->gtm);
/* See what mode we actually got */
ata_acpi_gtm(ap, &acpi->gtm);
@@ -156,18 +201,16 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
int unit = adev->devno;
struct pata_acpi *acpi = ap->private_data;
- const struct ata_timing *t;
if (!(acpi->gtm.flags & 0x10))
unit = 0;
/* Now stuff the nS values into the structure */
- t = ata_timing_find_mode(adev->dma_mode);
if (adev->dma_mode >= XFER_UDMA_0) {
- acpi->gtm.drive[unit].dma = t->udma;
+ acpi->gtm.drive[unit].dma = udma_cycle[adev->dma_mode - XFER_UDMA_0];
acpi->gtm.flags |= (1 << (2 * unit));
} else {
- acpi->gtm.drive[unit].dma = t->cycle;
+ acpi->gtm.drive[unit].dma = mwdma_cycle[adev->dma_mode - XFER_MW_DMA_0];
acpi->gtm.flags &= ~(1 << (2 * unit));
}
ata_acpi_stm(ap, &acpi->gtm);
diff --git a/trunk/drivers/ata/pata_ali.c b/trunk/drivers/ata/pata_ali.c
index 7e68edf3c0f3..8caf9afc8b90 100644
--- a/trunk/drivers/ata/pata_ali.c
+++ b/trunk/drivers/ata/pata_ali.c
@@ -64,7 +64,7 @@ static int ali_cable_override(struct pci_dev *pdev)
if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF)
return 1;
/* Mitac 8317 (Winbook-A) and relatives */
- if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317)
+ if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317)
return 1;
/* Systems by DMI */
if (dmi_check_system(cable_dmi_table))
diff --git a/trunk/drivers/ata/pata_amd.c b/trunk/drivers/ata/pata_amd.c
index 761a66608d7b..3cc27b514654 100644
--- a/trunk/drivers/ata/pata_amd.c
+++ b/trunk/drivers/ata/pata_amd.c
@@ -220,62 +220,6 @@ static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
timing_setup(ap, adev, 0x40, adev->dma_mode, 4);
}
-/* Both host-side and drive-side detection results are worthless on NV
- * PATAs. Ignore them and just follow what BIOS configured. Both the
- * current configuration in PCI config reg and ACPI GTM result are
- * cached during driver attach and are consulted to select transfer
- * mode.
- */
-static unsigned long nv_mode_filter(struct ata_device *dev,
- unsigned long xfer_mask)
-{
- static const unsigned int udma_mask_map[] =
- { ATA_UDMA2, ATA_UDMA1, ATA_UDMA0, 0,
- ATA_UDMA3, ATA_UDMA4, ATA_UDMA5, ATA_UDMA6 };
- struct ata_port *ap = dev->link->ap;
- char acpi_str[32] = "";
- u32 saved_udma, udma;
- const struct ata_acpi_gtm *gtm;
- unsigned long bios_limit = 0, acpi_limit = 0, limit;
-
- /* find out what BIOS configured */
- udma = saved_udma = (unsigned long)ap->host->private_data;
-
- if (ap->port_no == 0)
- udma >>= 16;
- if (dev->devno == 0)
- udma >>= 8;
-
- if ((udma & 0xc0) == 0xc0)
- bios_limit = ata_pack_xfermask(0, 0, udma_mask_map[udma & 0x7]);
-
- /* consult ACPI GTM too */
- gtm = ata_acpi_init_gtm(ap);
- if (gtm) {
- acpi_limit = ata_acpi_gtm_xfermask(dev, gtm);
-
- snprintf(acpi_str, sizeof(acpi_str), " (%u:%u:0x%x)",
- gtm->drive[0].dma, gtm->drive[1].dma, gtm->flags);
- }
-
- /* be optimistic, EH can take care of things if something goes wrong */
- limit = bios_limit | acpi_limit;
-
- /* If PIO or DMA isn't configured at all, don't limit. Let EH
- * handle it.
- */
- if (!(limit & ATA_MASK_PIO))
- limit |= ATA_MASK_PIO;
- if (!(limit & (ATA_MASK_MWDMA | ATA_MASK_UDMA)))
- limit |= ATA_MASK_MWDMA | ATA_MASK_UDMA;
-
- ata_port_printk(ap, KERN_DEBUG, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, "
- "BIOS=0x%lx (0x%x) ACPI=0x%lx%s\n",
- xfer_mask, limit, xfer_mask & limit, bios_limit,
- saved_udma, acpi_limit, acpi_str);
-
- return xfer_mask & limit;
-}
/**
* nv_probe_init - cable detection
@@ -308,6 +252,31 @@ static void nv_error_handler(struct ata_port *ap)
ata_std_postreset);
}
+static int nv_cable_detect(struct ata_port *ap)
+{
+ static const u8 bitmask[2] = {0x03, 0x0C};
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u8 ata66;
+ u16 udma;
+ int cbl;
+
+ pci_read_config_byte(pdev, 0x52, &ata66);
+ if (ata66 & bitmask[ap->port_no])
+ cbl = ATA_CBL_PATA80;
+ else
+ cbl = ATA_CBL_PATA40;
+
+ /* We now have to double check because the Nvidia boxes BIOS
+ doesn't always set the cable bits but does set mode bits */
+ pci_read_config_word(pdev, 0x62 - 2 * ap->port_no, &udma);
+ if ((udma & 0xC4) == 0xC4 || (udma & 0xC400) == 0xC400)
+ cbl = ATA_CBL_PATA80;
+ /* And a triple check across suspend/resume with ACPI around */
+ if (ata_acpi_cbl_80wire(ap))
+ cbl = ATA_CBL_PATA80;
+ return cbl;
+}
+
/**
* nv100_set_piomode - set initial PIO mode data
* @ap: ATA interface
@@ -345,14 +314,6 @@ static void nv133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
timing_setup(ap, adev, 0x50, adev->dma_mode, 4);
}
-static void nv_host_stop(struct ata_host *host)
-{
- u32 udma = (unsigned long)host->private_data;
-
- /* restore PCI config register 0x60 */
- pci_write_config_dword(to_pci_dev(host->dev), 0x60, udma);
-}
-
static struct scsi_host_template amd_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
@@ -517,8 +478,7 @@ static struct ata_port_operations nv100_port_ops = {
.thaw = ata_bmdma_thaw,
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .cable_detect = ata_cable_ignore,
- .mode_filter = nv_mode_filter,
+ .cable_detect = nv_cable_detect,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
@@ -535,7 +495,6 @@ static struct ata_port_operations nv100_port_ops = {
.irq_on = ata_irq_on,
.port_start = ata_sff_port_start,
- .host_stop = nv_host_stop,
};
static struct ata_port_operations nv133_port_ops = {
@@ -552,8 +511,7 @@ static struct ata_port_operations nv133_port_ops = {
.thaw = ata_bmdma_thaw,
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .cable_detect = ata_cable_ignore,
- .mode_filter = nv_mode_filter,
+ .cable_detect = nv_cable_detect,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
@@ -570,7 +528,6 @@ static struct ata_port_operations nv133_port_ops = {
.irq_on = ata_irq_on,
.port_start = ata_sff_port_start,
- .host_stop = nv_host_stop,
};
static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -657,8 +614,7 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
.port_ops = &amd100_port_ops
}
};
- struct ata_port_info pi;
- const struct ata_port_info *ppi[] = { &pi, NULL };
+ const struct ata_port_info *ppi[] = { NULL, NULL };
static int printed_version;
int type = id->driver_data;
u8 fifo;
@@ -672,19 +628,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (type == 1 && pdev->revision > 0x7)
type = 2;
- /* Serenade ? */
- if (type == 5 && pdev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
- pdev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
- type = 6; /* UDMA 100 only */
-
- /*
- * Okay, type is determined now. Apply type-specific workarounds.
- */
- pi = info[type];
-
- if (type < 3)
- ata_pci_clear_simplex(pdev);
-
/* Check for AMD7411 */
if (type == 3)
/* FIFO is broken */
@@ -692,17 +635,16 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
else
pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
- /* Cable detection on Nvidia chips doesn't work too well,
- * cache BIOS programmed UDMA mode.
- */
- if (type == 7 || type == 8) {
- u32 udma;
+ /* Serenade ? */
+ if (type == 5 && pdev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
+ pdev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
+ type = 6; /* UDMA 100 only */
- pci_read_config_dword(pdev, 0x60, &udma);
- pi.private_data = (void *)(unsigned long)udma;
- }
+ if (type < 3)
+ ata_pci_clear_simplex(pdev);
/* And fire it up */
+ ppi[0] = &info[type];
return ata_pci_init_one(pdev, ppi);
}
diff --git a/trunk/drivers/ata/pata_bf54x.c b/trunk/drivers/ata/pata_bf54x.c
index a32e3c44a606..7842cc487359 100644
--- a/trunk/drivers/ata/pata_bf54x.c
+++ b/trunk/drivers/ata/pata_bf54x.c
@@ -832,7 +832,6 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
{
unsigned short config = WDSIZE_16;
struct scatterlist *sg;
- unsigned int si;
pr_debug("in atapi dma setup\n");
/* Program the ATA_CTRL register with dir */
@@ -840,7 +839,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
/* fill the ATAPI DMA controller */
set_dma_config(CH_ATAPI_TX, config);
set_dma_x_modify(CH_ATAPI_TX, 2);
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ata_for_each_sg(sg, qc) {
set_dma_start_addr(CH_ATAPI_TX, sg_dma_address(sg));
set_dma_x_count(CH_ATAPI_TX, sg_dma_len(sg) >> 1);
}
@@ -849,7 +848,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
/* fill the ATAPI DMA controller */
set_dma_config(CH_ATAPI_RX, config);
set_dma_x_modify(CH_ATAPI_RX, 2);
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ata_for_each_sg(sg, qc) {
set_dma_start_addr(CH_ATAPI_RX, sg_dma_address(sg));
set_dma_x_count(CH_ATAPI_RX, sg_dma_len(sg) >> 1);
}
@@ -868,7 +867,6 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap;
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
struct scatterlist *sg;
- unsigned int si;
pr_debug("in atapi dma start\n");
if (!(ap->udma_mask || ap->mwdma_mask))
@@ -883,7 +881,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
* data cache is enabled. Otherwise, this loop
* is an empty loop and optimized out.
*/
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ata_for_each_sg(sg, qc) {
flush_dcache_range(sg_dma_address(sg),
sg_dma_address(sg) + sg_dma_len(sg));
}
@@ -912,7 +910,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | TFRCNT_RST);
/* Set transfer length to buffer len */
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ata_for_each_sg(sg, qc) {
ATAPI_SET_XFER_LEN(base, (sg_dma_len(sg) >> 1));
}
@@ -934,7 +932,6 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct scatterlist *sg;
- unsigned int si;
pr_debug("in atapi dma stop\n");
if (!(ap->udma_mask || ap->mwdma_mask))
@@ -953,7 +950,7 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc)
* data cache is enabled. Otherwise, this loop
* is an empty loop and optimized out.
*/
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ata_for_each_sg(sg, qc) {
invalidate_dcache_range(
sg_dma_address(sg),
sg_dma_address(sg)
@@ -1170,36 +1167,34 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
* Note: Original code is ata_data_xfer().
*/
-static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf,
- unsigned int buflen, int rw)
+static void bfin_data_xfer(struct ata_device *adev, unsigned char *buf,
+ unsigned int buflen, int write_data)
{
- struct ata_port *ap = dev->link->ap;
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+ struct ata_port *ap = adev->link->ap;
unsigned int words = buflen >> 1;
- unsigned short *buf16 = (u16 *)buf;
+ unsigned short *buf16 = (u16 *) buf;
+ void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
/* Transfer multiple of 2 bytes */
- if (rw == READ)
- read_atapi_data(base, words, buf16);
- else
+ if (write_data) {
write_atapi_data(base, words, buf16);
+ } else {
+ read_atapi_data(base, words, buf16);
+ }
/* Transfer trailing 1 byte, if any. */
if (unlikely(buflen & 0x01)) {
unsigned short align_buf[1] = { 0 };
unsigned char *trailing_buf = buf + buflen - 1;
- if (rw == READ) {
- read_atapi_data(base, 1, align_buf);
- memcpy(trailing_buf, align_buf, 1);
- } else {
+ if (write_data) {
memcpy(align_buf, trailing_buf, 1);
write_atapi_data(base, 1, align_buf);
+ } else {
+ read_atapi_data(base, 1, align_buf);
+ memcpy(trailing_buf, align_buf, 1);
}
- words++;
}
-
- return words << 1;
}
/**
diff --git a/trunk/drivers/ata/pata_cs5520.c b/trunk/drivers/ata/pata_cs5520.c
index d4590f546c49..33f7f0843f4f 100644
--- a/trunk/drivers/ata/pata_cs5520.c
+++ b/trunk/drivers/ata/pata_cs5520.c
@@ -198,7 +198,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
};
const struct ata_port_info *ppi[2];
u8 pcicfg;
- void __iomem *iomap[5];
+ void *iomap[5];
struct ata_host *host;
struct ata_ioports *ioaddr;
int i, rc;
diff --git a/trunk/drivers/ata/pata_hpt37x.c b/trunk/drivers/ata/pata_hpt37x.c
index 68eb34929cec..c79f066c2bc9 100644
--- a/trunk/drivers/ata/pata_hpt37x.c
+++ b/trunk/drivers/ata/pata_hpt37x.c
@@ -847,16 +847,15 @@ static u32 hpt374_read_freq(struct pci_dev *pdev)
u32 freq;
unsigned long io_base = pci_resource_start(pdev, 4);
if (PCI_FUNC(pdev->devfn) & 1) {
- struct pci_dev *pdev_0;
-
- pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1);
+ struct pci_dev *pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1);
/* Someone hot plugged the controller on us ? */
if (pdev_0 == NULL)
return 0;
io_base = pci_resource_start(pdev_0, 4);
freq = inl(io_base + 0x90);
pci_dev_put(pdev_0);
- } else
+ }
+ else
freq = inl(io_base + 0x90);
return freq;
}
diff --git a/trunk/drivers/ata/pata_icside.c b/trunk/drivers/ata/pata_icside.c
index 5b8586dac63b..842fe08a3c13 100644
--- a/trunk/drivers/ata/pata_icside.c
+++ b/trunk/drivers/ata/pata_icside.c
@@ -224,7 +224,6 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
struct pata_icside_state *state = ap->host->private_data;
struct scatterlist *sg, *rsg = state->sg;
unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE;
- unsigned int si;
/*
* We are simplex; BUG if we try to fiddle with DMA
@@ -235,7 +234,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
/*
* Copy ATAs scattered sg list into a contiguous array of sg
*/
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ata_for_each_sg(sg, qc) {
memcpy(rsg, sg, sizeof(*sg));
rsg++;
}
diff --git a/trunk/drivers/ata/pata_it821x.c b/trunk/drivers/ata/pata_it821x.c
index 109ddd42c266..ca9aae09daed 100644
--- a/trunk/drivers/ata/pata_it821x.c
+++ b/trunk/drivers/ata/pata_it821x.c
@@ -430,7 +430,7 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
return ata_qc_issue_prot(qc);
}
printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command);
- return AC_ERR_DEV;
+ return AC_ERR_INVALID;
}
/**
@@ -516,37 +516,6 @@ static void it821x_dev_config(struct ata_device *adev)
printk("(%dK stripe)", adev->id[146]);
printk(".\n");
}
- /* This is a controller firmware triggered funny, don't
- report the drive faulty! */
- adev->horkage &= ~ATA_HORKAGE_DIAGNOSTIC;
-}
-
-/**
- * it821x_ident_hack - Hack identify data up
- * @ap: Port
- *
- * Walk the devices on this firmware driven port and slightly
- * mash the identify data to stop us and common tools trying to
- * use features not firmware supported. The firmware itself does
- * some masking (eg SMART) but not enough.
- *
- * This is a bit of an abuse of the cable method, but it is the
- * only method called at the right time. We could modify the libata
- * core specifically for ident hacking but while we have one offender
- * it seems better to keep the fallout localised.
- */
-
-static int it821x_ident_hack(struct ata_port *ap)
-{
- struct ata_device *adev;
- ata_link_for_each_dev(adev, &ap->link) {
- if (ata_dev_enabled(adev)) {
- adev->id[84] &= ~(1 << 6); /* No FUA */
- adev->id[85] &= ~(1 << 10); /* No HPA */
- adev->id[76] = 0; /* No NCQ/AN etc */
- }
- }
- return ata_cable_unknown(ap);
}
@@ -665,7 +634,7 @@ static struct ata_port_operations it821x_smart_port_ops = {
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .cable_detect = it821x_ident_hack,
+ .cable_detect = ata_cable_unknown,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
diff --git a/trunk/drivers/ata/pata_ixp4xx_cf.c b/trunk/drivers/ata/pata_ixp4xx_cf.c
index 030878fedeb5..120b5bfa7ce6 100644
--- a/trunk/drivers/ata/pata_ixp4xx_cf.c
+++ b/trunk/drivers/ata/pata_ixp4xx_cf.c
@@ -42,13 +42,13 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)
return 0;
}
-static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev,
- unsigned char *buf, unsigned int buflen, int rw)
+static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
+ unsigned int buflen, int write_data)
{
unsigned int i;
unsigned int words = buflen >> 1;
u16 *buf16 = (u16 *) buf;
- struct ata_port *ap = dev->link->ap;
+ struct ata_port *ap = adev->link->ap;
void __iomem *mmio = ap->ioaddr.data_addr;
struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
@@ -59,32 +59,30 @@ static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev,
udelay(100);
/* Transfer multiple of 2 bytes */
- if (rw == READ)
- for (i = 0; i < words; i++)
- buf16[i] = readw(mmio);
- else
+ if (write_data) {
for (i = 0; i < words; i++)
writew(buf16[i], mmio);
+ } else {
+ for (i = 0; i < words; i++)
+ buf16[i] = readw(mmio);
+ }
/* Transfer trailing 1 byte, if any. */
if (unlikely(buflen & 0x01)) {
u16 align_buf[1] = { 0 };
unsigned char *trailing_buf = buf + buflen - 1;
- if (rw == READ) {
- align_buf[0] = readw(mmio);
- memcpy(trailing_buf, align_buf, 1);
- } else {
+ if (write_data) {
memcpy(align_buf, trailing_buf, 1);
writew(align_buf[0], mmio);
+ } else {
+ align_buf[0] = readw(mmio);
+ memcpy(trailing_buf, align_buf, 1);
}
- words++;
}
udelay(100);
*data->cs0_cfg |= 0x01;
-
- return words << 1;
}
static struct scsi_host_template ixp4xx_sht = {
diff --git a/trunk/drivers/ata/pata_legacy.c b/trunk/drivers/ata/pata_legacy.c
index 333dc15f8ccf..17159b5e1e43 100644
--- a/trunk/drivers/ata/pata_legacy.c
+++ b/trunk/drivers/ata/pata_legacy.c
@@ -28,6 +28,7 @@
*
* Unsupported but docs exist:
* Appian/Adaptec AIC25VL01/Cirrus Logic PD7220
+ * Winbond W83759A
*
* This driver handles legacy (that is "ISA/VLB side") IDE ports found
* on PC class systems. There are three hybrid devices that are exceptions
@@ -35,7 +36,7 @@
* the MPIIX where the tuning is PCI side but the IDE is "ISA side".
*
* Specific support is included for the ht6560a/ht6560b/opti82c611a/
- * opti82c465mv/promise 20230c/20630/winbond83759A
+ * opti82c465mv/promise 20230c/20630
*
* Use the autospeed and pio_mask options with:
* Appian ADI/2 aka CLPD7220 or AIC25VL01.
@@ -46,6 +47,9 @@
* For now use autospeed and pio_mask as above with the W83759A. This may
* change.
*
+ * TODO
+ * Merge existing pata_qdi driver
+ *
*/
#include
@@ -60,13 +64,12 @@
#include
#define DRV_NAME "pata_legacy"
-#define DRV_VERSION "0.6.5"
+#define DRV_VERSION "0.5.5"
#define NR_HOST 6
-static int all;
-module_param(all, int, 0444);
-MODULE_PARM_DESC(all, "Grab all legacy port devices, even if PCI(0=off, 1=on)");
+static int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
+static int legacy_irq[NR_HOST] = { 14, 15, 11, 10, 8, 12 };
struct legacy_data {
unsigned long timing;
@@ -77,106 +80,20 @@ struct legacy_data {
};
-enum controller {
- BIOS = 0,
- SNOOP = 1,
- PDC20230 = 2,
- HT6560A = 3,
- HT6560B = 4,
- OPTI611A = 5,
- OPTI46X = 6,
- QDI6500 = 7,
- QDI6580 = 8,
- QDI6580DP = 9, /* Dual channel mode is different */
- W83759A = 10,
-
- UNKNOWN = -1
-};
-
-
-struct legacy_probe {
- unsigned char *name;
- unsigned long port;
- unsigned int irq;
- unsigned int slot;
- enum controller type;
- unsigned long private;
-};
-
-struct legacy_controller {
- const char *name;
- struct ata_port_operations *ops;
- unsigned int pio_mask;
- unsigned int flags;
- int (*setup)(struct platform_device *, struct legacy_probe *probe,
- struct legacy_data *data);
-};
-
-static int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
-
-static struct legacy_probe probe_list[NR_HOST];
static struct legacy_data legacy_data[NR_HOST];
static struct ata_host *legacy_host[NR_HOST];
static int nr_legacy_host;
-static int probe_all; /* Set to check all ISA port ranges */
-static int ht6560a; /* HT 6560A on primary 1, second 2, both 3 */
-static int ht6560b; /* HT 6560A on primary 1, second 2, both 3 */
-static int opti82c611a; /* Opti82c611A on primary 1, sec 2, both 3 */
-static int opti82c46x; /* Opti 82c465MV present(pri/sec autodetect) */
-static int qdi; /* Set to probe QDI controllers */
-static int winbond; /* Set to probe Winbond controllers,
- give I/O port if non stdanard */
-static int autospeed; /* Chip present which snoops speed changes */
-static int pio_mask = 0x1F; /* PIO range for autospeed devices */
+static int probe_all; /* Set to check all ISA port ranges */
+static int ht6560a; /* HT 6560A on primary 1, secondary 2, both 3 */
+static int ht6560b; /* HT 6560A on primary 1, secondary 2, both 3 */
+static int opti82c611a; /* Opti82c611A on primary 1, secondary 2, both 3 */
+static int opti82c46x; /* Opti 82c465MV present (pri/sec autodetect) */
+static int autospeed; /* Chip present which snoops speed changes */
+static int pio_mask = 0x1F; /* PIO range for autospeed devices */
static int iordy_mask = 0xFFFFFFFF; /* Use iordy if available */
-/**
- * legacy_probe_add - Add interface to probe list
- * @port: Controller port
- * @irq: IRQ number
- * @type: Controller type
- * @private: Controller specific info
- *
- * Add an entry into the probe list for ATA controllers. This is used
- * to add the default ISA slots and then to build up the table
- * further according to other ISA/VLB/Weird device scans
- *
- * An I/O port list is used to keep ordering stable and sane, as we
- * don't have any good way to talk about ordering otherwise
- */
-
-static int legacy_probe_add(unsigned long port, unsigned int irq,
- enum controller type, unsigned long private)
-{
- struct legacy_probe *lp = &probe_list[0];
- int i;
- struct legacy_probe *free = NULL;
-
- for (i = 0; i < NR_HOST; i++) {
- if (lp->port == 0 && free == NULL)
- free = lp;
- /* Matching port, or the correct slot for ordering */
- if (lp->port == port || legacy_port[i] == port) {
- free = lp;
- break;
- }
- lp++;
- }
- if (free == NULL) {
- printk(KERN_ERR "pata_legacy: Too many interfaces.\n");
- return -1;
- }
- /* Fill in the entry for later probing */
- free->port = port;
- free->irq = irq;
- free->type = type;
- free->private = private;
- return 0;
-}
-
-
/**
* legacy_set_mode - mode setting
* @link: IDE link
@@ -196,8 +113,7 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused)
ata_link_for_each_dev(dev, link) {
if (ata_dev_enabled(dev)) {
- ata_dev_printk(dev, KERN_INFO,
- "configured for PIO\n");
+ ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
dev->pio_mode = XFER_PIO_0;
dev->xfer_mode = XFER_PIO_0;
dev->xfer_shift = ATA_SHIFT_PIO;
@@ -255,7 +171,7 @@ static struct ata_port_operations simple_port_ops = {
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
- .port_start = ata_sff_port_start,
+ .port_start = ata_port_start,
};
static struct ata_port_operations legacy_port_ops = {
@@ -282,16 +198,15 @@ static struct ata_port_operations legacy_port_ops = {
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
- .port_start = ata_sff_port_start,
+ .port_start = ata_port_start,
};
/*
* Promise 20230C and 20620 support
*
- * This controller supports PIO0 to PIO2. We set PIO timings
- * conservatively to allow for 50MHz Vesa Local Bus. The 20620 DMA
- * support is weird being DMA to controller and PIO'd to the host
- * and not supported.
+ * This controller supports PIO0 to PIO2. We set PIO timings conservatively to
+ * allow for 50MHz Vesa Local Bus. The 20620 DMA support is weird being DMA to
+ * controller and PIO'd to the host and not supported.
*/
static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
@@ -306,7 +221,8 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
local_irq_save(flags);
/* Unlock the control interface */
- do {
+ do
+ {
inb(0x1F5);
outb(inb(0x1F2) | 0x80, 0x1F2);
inb(0x1F2);
@@ -315,7 +231,7 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
inb(0x1F2);
inb(0x1F2);
}
- while ((inb(0x1F2) & 0x80) && --tries);
+ while((inb(0x1F2) & 0x80) && --tries);
local_irq_restore(flags);
@@ -333,14 +249,13 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
}
-static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
- unsigned char *buf, unsigned int buflen, int rw)
+static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
{
- if (ata_id_has_dword_io(dev->id)) {
- struct ata_port *ap = dev->link->ap;
- int slop = buflen & 3;
- unsigned long flags;
+ struct ata_port *ap = adev->link->ap;
+ int slop = buflen & 3;
+ unsigned long flags;
+ if (ata_id_has_dword_io(adev->id)) {
local_irq_save(flags);
/* Perform the 32bit I/O synchronization sequence */
@@ -349,27 +264,26 @@ static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
ioread8(ap->ioaddr.nsect_addr);
/* Now the data */
- if (rw == READ)
- ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
- else
+
+ if (write_data)
iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+ else
+ ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
if (unlikely(slop)) {
- u32 pad;
- if (rw == READ) {
- pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
- memcpy(buf + buflen - slop, &pad, slop);
- } else {
+ __le32 pad = 0;
+ if (write_data) {
memcpy(&pad, buf + buflen - slop, slop);
iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
+ } else {
+ pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
+ memcpy(buf + buflen - slop, &pad, slop);
}
- buflen += 4 - slop;
}
local_irq_restore(flags);
- } else
- buflen = ata_data_xfer_noirq(dev, buf, buflen, rw);
-
- return buflen;
+ }
+ else
+ ata_data_xfer_noirq(adev, buf, buflen, write_data);
}
static struct ata_port_operations pdc20230_port_ops = {
@@ -396,14 +310,14 @@ static struct ata_port_operations pdc20230_port_ops = {
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
- .port_start = ata_sff_port_start,
+ .port_start = ata_port_start,
};
/*
* Holtek 6560A support
*
- * This controller supports PIO0 to PIO2 (no IORDY even though higher
- * timings can be loaded).
+ * This controller supports PIO0 to PIO2 (no IORDY even though higher timings
+ * can be loaded).
*/
static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
@@ -450,14 +364,14 @@ static struct ata_port_operations ht6560a_port_ops = {
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
- .port_start = ata_sff_port_start,
+ .port_start = ata_port_start,
};
/*
* Holtek 6560B support
*
- * This controller supports PIO0 to PIO4. We honour the BIOS/jumper FIFO
- * setting unless we see an ATAPI device in which case we force it off.
+ * This controller supports PIO0 to PIO4. We honour the BIOS/jumper FIFO setting
+ * unless we see an ATAPI device in which case we force it off.
*
* FIXME: need to implement 2nd channel support.
*/
@@ -484,7 +398,7 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
if (adev->class != ATA_DEV_ATA) {
u8 rconf = inb(0x3E6);
if (rconf & 0x24) {
- rconf &= ~0x24;
+ rconf &= ~ 0x24;
outb(rconf, 0x3E6);
}
}
@@ -509,13 +423,13 @@ static struct ata_port_operations ht6560b_port_ops = {
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
- .data_xfer = ata_data_xfer, /* FIXME: Check 32bit and noirq */
+ .data_xfer = ata_data_xfer, /* FIXME: Check 32bit and noirq */
.irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
- .port_start = ata_sff_port_start,
+ .port_start = ata_port_start,
};
/*
@@ -548,8 +462,7 @@ static u8 opti_syscfg(u8 reg)
* This controller supports PIO0 to PIO3.
*/
-static void opti82c611a_set_piomode(struct ata_port *ap,
- struct ata_device *adev)
+static void opti82c611a_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
u8 active, recover, setup;
struct ata_timing t;
@@ -636,7 +549,7 @@ static struct ata_port_operations opti82c611a_port_ops = {
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
- .port_start = ata_sff_port_start,
+ .port_start = ata_port_start,
};
/*
@@ -768,398 +681,77 @@ static struct ata_port_operations opti82c46x_port_ops = {
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
- .port_start = ata_sff_port_start,
+ .port_start = ata_port_start,
};
-static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
- struct ata_timing t;
- struct legacy_data *qdi = ap->host->private_data;
- int active, recovery;
- u8 timing;
-
- /* Get the timing data in cycles */
- ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
- if (qdi->fast) {
- active = 8 - FIT(t.active, 1, 8);
- recovery = 18 - FIT(t.recover, 3, 18);
- } else {
- active = 9 - FIT(t.active, 2, 9);
- recovery = 15 - FIT(t.recover, 0, 15);
- }
- timing = (recovery << 4) | active | 0x08;
-
- qdi->clock[adev->devno] = timing;
-
- outb(timing, qdi->timing);
-}
/**
- * qdi6580dp_set_piomode - PIO setup for dual channel
- * @ap: Port
- * @adev: Device
+ * legacy_init_one - attach a legacy interface
+ * @port: port number
+ * @io: I/O port start
+ * @ctrl: control port
* @irq: interrupt line
*
- * In dual channel mode the 6580 has one clock per channel and we have
- * to software clockswitch in qc_issue_prot.
+ * Register an ISA bus IDE interface. Such interfaces are PIO and we
+ * assume do not support IRQ sharing.
*/
-static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
+static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl, int irq)
{
- struct ata_timing t;
- struct legacy_data *qdi = ap->host->private_data;
- int active, recovery;
- u8 timing;
-
- /* Get the timing data in cycles */
- ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
- if (qdi->fast) {
- active = 8 - FIT(t.active, 1, 8);
- recovery = 18 - FIT(t.recover, 3, 18);
- } else {
- active = 9 - FIT(t.active, 2, 9);
- recovery = 15 - FIT(t.recover, 0, 15);
- }
- timing = (recovery << 4) | active | 0x08;
-
- qdi->clock[adev->devno] = timing;
+ struct legacy_data *ld = &legacy_data[nr_legacy_host];
+ struct ata_host *host;
+ struct ata_port *ap;
+ struct platform_device *pdev;
+ struct ata_port_operations *ops = &legacy_port_ops;
+ void __iomem *io_addr, *ctrl_addr;
+ int pio_modes = pio_mask;
+ u32 mask = (1 << port);
+ u32 iordy = (iordy_mask & mask) ? 0: ATA_FLAG_NO_IORDY;
+ int ret;
- outb(timing, qdi->timing + 2 * ap->port_no);
- /* Clear the FIFO */
- if (adev->class != ATA_DEV_ATA)
- outb(0x5F, qdi->timing + 3);
-}
+ pdev = platform_device_register_simple(DRV_NAME, nr_legacy_host, NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
-/**
- * qdi6580_set_piomode - PIO setup for single channel
- * @ap: Port
- * @adev: Device
- *
- * In single channel mode the 6580 has one clock per device and we can
- * avoid the requirement to clock switch. We also have to load the timing
- * into the right clock according to whether we are master or slave.
- */
+ ret = -EBUSY;
+ if (devm_request_region(&pdev->dev, io, 8, "pata_legacy") == NULL ||
+ devm_request_region(&pdev->dev, ctrl, 1, "pata_legacy") == NULL)
+ goto fail;
-static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
- struct ata_timing t;
- struct legacy_data *qdi = ap->host->private_data;
- int active, recovery;
- u8 timing;
+ ret = -ENOMEM;
+ io_addr = devm_ioport_map(&pdev->dev, io, 8);
+ ctrl_addr = devm_ioport_map(&pdev->dev, ctrl, 1);
+ if (!io_addr || !ctrl_addr)
+ goto fail;
- /* Get the timing data in cycles */
- ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
- if (qdi->fast) {
- active = 8 - FIT(t.active, 1, 8);
- recovery = 18 - FIT(t.recover, 3, 18);
- } else {
- active = 9 - FIT(t.active, 2, 9);
- recovery = 15 - FIT(t.recover, 0, 15);
+ if (ht6560a & mask) {
+ ops = &ht6560a_port_ops;
+ pio_modes = 0x07;
+ iordy = ATA_FLAG_NO_IORDY;
}
- timing = (recovery << 4) | active | 0x08;
- qdi->clock[adev->devno] = timing;
- outb(timing, qdi->timing + 2 * adev->devno);
- /* Clear the FIFO */
- if (adev->class != ATA_DEV_ATA)
- outb(0x5F, qdi->timing + 3);
-}
-
-/**
- * qdi_qc_issue_prot - command issue
- * @qc: command pending
- *
- * Called when the libata layer is about to issue a command. We wrap
- * this interface so that we can load the correct ATA timings.
- */
-
-static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- struct ata_device *adev = qc->dev;
- struct legacy_data *qdi = ap->host->private_data;
-
- if (qdi->clock[adev->devno] != qdi->last) {
- if (adev->pio_mode) {
- qdi->last = qdi->clock[adev->devno];
- outb(qdi->clock[adev->devno], qdi->timing +
- 2 * ap->port_no);
- }
+ if (ht6560b & mask) {
+ ops = &ht6560b_port_ops;
+ pio_modes = 0x1F;
+ }
+ if (opti82c611a & mask) {
+ ops = &opti82c611a_port_ops;
+ pio_modes = 0x0F;
+ }
+ if (opti82c46x & mask) {
+ ops = &opti82c46x_port_ops;
+ pio_modes = 0x0F;
}
- return ata_qc_issue_prot(qc);
-}
-
-static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
- unsigned int buflen, int rw)
-{
- struct ata_port *ap = adev->link->ap;
- int slop = buflen & 3;
-
- if (ata_id_has_dword_io(adev->id)) {
- if (rw == WRITE)
- iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
- else
- ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-
- if (unlikely(slop)) {
- u32 pad;
- if (rw == WRITE) {
- memcpy(&pad, buf + buflen - slop, slop);
- pad = le32_to_cpu(pad);
- iowrite32(pad, ap->ioaddr.data_addr);
- } else {
- pad = ioread32(ap->ioaddr.data_addr);
- pad = cpu_to_le32(pad);
- memcpy(buf + buflen - slop, &pad, slop);
- }
- }
- return (buflen + 3) & ~3;
- } else
- return ata_data_xfer(adev, buf, buflen, rw);
-}
-
-static int qdi_port(struct platform_device *dev,
- struct legacy_probe *lp, struct legacy_data *ld)
-{
- if (devm_request_region(&dev->dev, lp->private, 4, "qdi") == NULL)
- return -EBUSY;
- ld->timing = lp->private;
- return 0;
-}
-
-static struct ata_port_operations qdi6500_port_ops = {
- .set_piomode = qdi6500_set_piomode,
-
- .tf_load = ata_tf_load,
- .tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .exec_command = ata_exec_command,
- .dev_select = ata_std_dev_select,
-
- .freeze = ata_bmdma_freeze,
- .thaw = ata_bmdma_thaw,
- .error_handler = ata_bmdma_error_handler,
- .post_internal_cmd = ata_bmdma_post_internal_cmd,
- .cable_detect = ata_cable_40wire,
-
- .qc_prep = ata_qc_prep,
- .qc_issue = qdi_qc_issue_prot,
-
- .data_xfer = vlb32_data_xfer,
-
- .irq_handler = ata_interrupt,
- .irq_clear = ata_bmdma_irq_clear,
- .irq_on = ata_irq_on,
-
- .port_start = ata_sff_port_start,
-};
-
-static struct ata_port_operations qdi6580_port_ops = {
- .set_piomode = qdi6580_set_piomode,
-
- .tf_load = ata_tf_load,
- .tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .exec_command = ata_exec_command,
- .dev_select = ata_std_dev_select,
-
- .freeze = ata_bmdma_freeze,
- .thaw = ata_bmdma_thaw,
- .error_handler = ata_bmdma_error_handler,
- .post_internal_cmd = ata_bmdma_post_internal_cmd,
- .cable_detect = ata_cable_40wire,
-
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
-
- .data_xfer = vlb32_data_xfer,
-
- .irq_handler = ata_interrupt,
- .irq_clear = ata_bmdma_irq_clear,
- .irq_on = ata_irq_on,
-
- .port_start = ata_sff_port_start,
-};
-
-static struct ata_port_operations qdi6580dp_port_ops = {
- .set_piomode = qdi6580dp_set_piomode,
-
- .tf_load = ata_tf_load,
- .tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .exec_command = ata_exec_command,
- .dev_select = ata_std_dev_select,
-
- .freeze = ata_bmdma_freeze,
- .thaw = ata_bmdma_thaw,
- .error_handler = ata_bmdma_error_handler,
- .post_internal_cmd = ata_bmdma_post_internal_cmd,
- .cable_detect = ata_cable_40wire,
-
- .qc_prep = ata_qc_prep,
- .qc_issue = qdi_qc_issue_prot,
-
- .data_xfer = vlb32_data_xfer,
-
- .irq_handler = ata_interrupt,
- .irq_clear = ata_bmdma_irq_clear,
- .irq_on = ata_irq_on,
-
- .port_start = ata_sff_port_start,
-};
-
-static DEFINE_SPINLOCK(winbond_lock);
-
-static void winbond_writecfg(unsigned long port, u8 reg, u8 val)
-{
- unsigned long flags;
- spin_lock_irqsave(&winbond_lock, flags);
- outb(reg, port + 0x01);
- outb(val, port + 0x02);
- spin_unlock_irqrestore(&winbond_lock, flags);
-}
-
-static u8 winbond_readcfg(unsigned long port, u8 reg)
-{
- u8 val;
-
- unsigned long flags;
- spin_lock_irqsave(&winbond_lock, flags);
- outb(reg, port + 0x01);
- val = inb(port + 0x02);
- spin_unlock_irqrestore(&winbond_lock, flags);
-
- return val;
-}
-
-static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
- struct ata_timing t;
- struct legacy_data *winbond = ap->host->private_data;
- int active, recovery;
- u8 reg;
- int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2);
-
- reg = winbond_readcfg(winbond->timing, 0x81);
-
- /* Get the timing data in cycles */
- if (reg & 0x40) /* Fast VLB bus, assume 50MHz */
- ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
- else
- ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
- active = (FIT(t.active, 3, 17) - 1) & 0x0F;
- recovery = (FIT(t.recover, 1, 15) + 1) & 0x0F;
- timing = (active << 4) | recovery;
- winbond_writecfg(winbond->timing, timing, reg);
-
- /* Load the setup timing */
-
- reg = 0x35;
- if (adev->class != ATA_DEV_ATA)
- reg |= 0x08; /* FIFO off */
- if (!ata_pio_need_iordy(adev))
- reg |= 0x02; /* IORDY off */
- reg |= (FIT(t.setup, 0, 3) << 6);
- winbond_writecfg(winbond->timing, timing + 1, reg);
-}
-
-static int winbond_port(struct platform_device *dev,
- struct legacy_probe *lp, struct legacy_data *ld)
-{
- if (devm_request_region(&dev->dev, lp->private, 4, "winbond") == NULL)
- return -EBUSY;
- ld->timing = lp->private;
- return 0;
-}
-
-static struct ata_port_operations winbond_port_ops = {
- .set_piomode = winbond_set_piomode,
-
- .tf_load = ata_tf_load,
- .tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .exec_command = ata_exec_command,
- .dev_select = ata_std_dev_select,
-
- .freeze = ata_bmdma_freeze,
- .thaw = ata_bmdma_thaw,
- .error_handler = ata_bmdma_error_handler,
- .post_internal_cmd = ata_bmdma_post_internal_cmd,
- .cable_detect = ata_cable_40wire,
-
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
-
- .data_xfer = vlb32_data_xfer,
-
- .irq_clear = ata_bmdma_irq_clear,
- .irq_on = ata_irq_on,
-
- .port_start = ata_sff_port_start,
-};
-
-static struct legacy_controller controllers[] = {
- {"BIOS", &legacy_port_ops, 0x1F,
- ATA_FLAG_NO_IORDY, NULL },
- {"Snooping", &simple_port_ops, 0x1F,
- 0 , NULL },
- {"PDC20230", &pdc20230_port_ops, 0x7,
- ATA_FLAG_NO_IORDY, NULL },
- {"HT6560A", &ht6560a_port_ops, 0x07,
- ATA_FLAG_NO_IORDY, NULL },
- {"HT6560B", &ht6560b_port_ops, 0x1F,
- ATA_FLAG_NO_IORDY, NULL },
- {"OPTI82C611A", &opti82c611a_port_ops, 0x0F,
- 0 , NULL },
- {"OPTI82C46X", &opti82c46x_port_ops, 0x0F,
- 0 , NULL },
- {"QDI6500", &qdi6500_port_ops, 0x07,
- ATA_FLAG_NO_IORDY, qdi_port },
- {"QDI6580", &qdi6580_port_ops, 0x1F,
- 0 , qdi_port },
- {"QDI6580DP", &qdi6580dp_port_ops, 0x1F,
- 0 , qdi_port },
- {"W83759A", &winbond_port_ops, 0x1F,
- 0 , winbond_port }
-};
-/**
- * probe_chip_type - Discover controller
- * @probe: Probe entry to check
- *
- * Probe an ATA port and identify the type of controller. We don't
- * check if the controller appears to be driveless at this point.
- */
+ /* Probe for automatically detectable controllers */
-static __init int probe_chip_type(struct legacy_probe *probe)
-{
- int mask = 1 << probe->slot;
-
- if (winbond && (probe->port == 0x1F0 || probe->port == 0x170)) {
- u8 reg = winbond_readcfg(winbond, 0x81);
- reg |= 0x80; /* jumpered mode off */
- winbond_writecfg(winbond, 0x81, reg);
- reg = winbond_readcfg(winbond, 0x83);
- reg |= 0xF0; /* local control */
- winbond_writecfg(winbond, 0x83, reg);
- reg = winbond_readcfg(winbond, 0x85);
- reg |= 0xF0; /* programmable timing */
- winbond_writecfg(winbond, 0x85, reg);
-
- reg = winbond_readcfg(winbond, 0x81);
-
- if (reg & mask)
- return W83759A;
- }
- if (probe->port == 0x1F0) {
+ if (io == 0x1F0 && ops == &legacy_port_ops) {
unsigned long flags;
+
local_irq_save(flags);
+
/* Probes */
- outb(inb(0x1F2) | 0x80, 0x1F2);
inb(0x1F5);
+ outb(inb(0x1F2) | 0x80, 0x1F2);
inb(0x1F2);
inb(0x3F6);
inb(0x3F6);
@@ -1168,83 +760,29 @@ static __init int probe_chip_type(struct legacy_probe *probe)
if ((inb(0x1F2) & 0x80) == 0) {
/* PDC20230c or 20630 ? */
- printk(KERN_INFO "PDC20230-C/20630 VLB ATA controller"
- " detected.\n");
+ printk(KERN_INFO "PDC20230-C/20630 VLB ATA controller detected.\n");
+ pio_modes = 0x07;
+ ops = &pdc20230_port_ops;
+ iordy = ATA_FLAG_NO_IORDY;
udelay(100);
inb(0x1F5);
- local_irq_restore(flags);
- return PDC20230;
} else {
outb(0x55, 0x1F2);
inb(0x1F2);
inb(0x1F2);
- if (inb(0x1F2) == 0x00)
- printk(KERN_INFO "PDC20230-B VLB ATA "
- "controller detected.\n");
- local_irq_restore(flags);
- return BIOS;
+ if (inb(0x1F2) == 0x00) {
+ printk(KERN_INFO "PDC20230-B VLB ATA controller detected.\n");
+ }
}
local_irq_restore(flags);
}
- if (ht6560a & mask)
- return HT6560A;
- if (ht6560b & mask)
- return HT6560B;
- if (opti82c611a & mask)
- return OPTI611A;
- if (opti82c46x & mask)
- return OPTI46X;
- if (autospeed & mask)
- return SNOOP;
- return BIOS;
-}
-
-
-/**
- * legacy_init_one - attach a legacy interface
- * @pl: probe record
- *
- * Register an ISA bus IDE interface. Such interfaces are PIO and we
- * assume do not support IRQ sharing.
- */
-
-static __init int legacy_init_one(struct legacy_probe *probe)
-{
- struct legacy_controller *controller = &controllers[probe->type];
- int pio_modes = controller->pio_mask;
- unsigned long io = probe->port;
- u32 mask = (1 << probe->slot);
- struct ata_port_operations *ops = controller->ops;
- struct legacy_data *ld = &legacy_data[probe->slot];
- struct ata_host *host = NULL;
- struct ata_port *ap;
- struct platform_device *pdev;
- struct ata_device *dev;
- void __iomem *io_addr, *ctrl_addr;
- u32 iordy = (iordy_mask & mask) ? 0: ATA_FLAG_NO_IORDY;
- int ret;
- iordy |= controller->flags;
-
- pdev = platform_device_register_simple(DRV_NAME, probe->slot, NULL, 0);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
-
- ret = -EBUSY;
- if (devm_request_region(&pdev->dev, io, 8, "pata_legacy") == NULL ||
- devm_request_region(&pdev->dev, io + 0x0206, 1,
- "pata_legacy") == NULL)
- goto fail;
+ /* Chip does mode setting by command snooping */
+ if (ops == &legacy_port_ops && (autospeed & mask))
+ ops = &simple_port_ops;
ret = -ENOMEM;
- io_addr = devm_ioport_map(&pdev->dev, io, 8);
- ctrl_addr = devm_ioport_map(&pdev->dev, io + 0x0206, 1);
- if (!io_addr || !ctrl_addr)
- goto fail;
- if (controller->setup)
- if (controller->setup(pdev, probe, ld) < 0)
- goto fail;
host = ata_host_alloc(&pdev->dev, 1);
if (!host)
goto fail;
@@ -1257,29 +795,19 @@ static __init int legacy_init_one(struct legacy_probe *probe)
ap->ioaddr.altstatus_addr = ctrl_addr;
ap->ioaddr.ctl_addr = ctrl_addr;
ata_std_ports(&ap->ioaddr);
- ap->host->private_data = ld;
+ ap->private_data = ld;
- ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, io + 0x0206);
+ ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, ctrl);
- ret = ata_host_activate(host, probe->irq, ata_interrupt, 0,
- &legacy_sht);
+ ret = ata_host_activate(host, irq, ata_interrupt, 0, &legacy_sht);
if (ret)
goto fail;
- ld->platform_dev = pdev;
- /* Nothing found means we drop the port as its probably not there */
+ legacy_host[nr_legacy_host++] = dev_get_drvdata(&pdev->dev);
+ ld->platform_dev = pdev;
+ return 0;
- ret = -ENODEV;
- ata_link_for_each_dev(dev, &ap->link) {
- if (!ata_dev_absent(dev)) {
- legacy_host[probe->slot] = host;
- ld->platform_dev = pdev;
- return 0;
- }
- }
fail:
- if (host)
- ata_host_detach(host);
platform_device_unregister(pdev);
return ret;
}
@@ -1290,15 +818,13 @@ static __init int legacy_init_one(struct legacy_probe *probe)
* @master: set this if we find an ATA master
* @master: set this if we find an ATA secondary
*
- * A small number of vendors implemented early PCI ATA interfaces
- * on bridge logic without the ATA interface being PCI visible.
- * Where we have a matching PCI driver we must skip the relevant
- * device here. If we don't know about it then the legacy driver
- * is the right driver anyway.
+ * A small number of vendors implemented early PCI ATA interfaces on bridge logic
+ * without the ATA interface being PCI visible. Where we have a matching PCI driver
+ * we must skip the relevant device here. If we don't know about it then the legacy
+ * driver is the right driver anyway.
*/
-static void __init legacy_check_special_cases(struct pci_dev *p, int *primary,
- int *secondary)
+static void legacy_check_special_cases(struct pci_dev *p, int *primary, int *secondary)
{
/* Cyrix CS5510 pre SFF MWDMA ATA on the bridge */
if (p->vendor == 0x1078 && p->device == 0x0000) {
@@ -1314,8 +840,7 @@ static void __init legacy_check_special_cases(struct pci_dev *p, int *primary,
if (p->vendor == 0x8086 && p->device == 0x1234) {
u16 r;
pci_read_config_word(p, 0x6C, &r);
- if (r & 0x8000) {
- /* ATA port enabled */
+ if (r & 0x8000) { /* ATA port enabled */
if (r & 0x4000)
*secondary = 1;
else
@@ -1325,114 +850,6 @@ static void __init legacy_check_special_cases(struct pci_dev *p, int *primary,
}
}
-static __init void probe_opti_vlb(void)
-{
- /* If an OPTI 82C46X is present find out where the channels are */
- static const char *optis[4] = {
- "3/463MV", "5MV",
- "5MVA", "5MVB"
- };
- u8 chans = 1;
- u8 ctrl = (opti_syscfg(0x30) & 0xC0) >> 6;
-
- opti82c46x = 3; /* Assume master and slave first */
- printk(KERN_INFO DRV_NAME ": Opti 82C46%s chipset support.\n",
- optis[ctrl]);
- if (ctrl == 3)
- chans = (opti_syscfg(0x3F) & 0x20) ? 2 : 1;
- ctrl = opti_syscfg(0xAC);
- /* Check enabled and this port is the 465MV port. On the
- MVB we may have two channels */
- if (ctrl & 8) {
- if (chans == 2) {
- legacy_probe_add(0x1F0, 14, OPTI46X, 0);
- legacy_probe_add(0x170, 15, OPTI46X, 0);
- }
- if (ctrl & 4)
- legacy_probe_add(0x170, 15, OPTI46X, 0);
- else
- legacy_probe_add(0x1F0, 14, OPTI46X, 0);
- } else
- legacy_probe_add(0x1F0, 14, OPTI46X, 0);
-}
-
-static __init void qdi65_identify_port(u8 r, u8 res, unsigned long port)
-{
- static const unsigned long ide_port[2] = { 0x170, 0x1F0 };
- /* Check card type */
- if ((r & 0xF0) == 0xC0) {
- /* QD6500: single channel */
- if (r & 8)
- /* Disabled ? */
- return;
- legacy_probe_add(ide_port[r & 0x01], 14 + (r & 0x01),
- QDI6500, port);
- }
- if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) {
- /* QD6580: dual channel */
- if (!request_region(port + 2 , 2, "pata_qdi")) {
- release_region(port, 2);
- return;
- }
- res = inb(port + 3);
- /* Single channel mode ? */
- if (res & 1)
- legacy_probe_add(ide_port[r & 0x01], 14 + (r & 0x01),
- QDI6580, port);
- else { /* Dual channel mode */
- legacy_probe_add(0x1F0, 14, QDI6580DP, port);
- /* port + 0x02, r & 0x04 */
- legacy_probe_add(0x170, 15, QDI6580DP, port + 2);
- }
- release_region(port + 2, 2);
- }
-}
-
-static __init void probe_qdi_vlb(void)
-{
- unsigned long flags;
- static const unsigned long qd_port[2] = { 0x30, 0xB0 };
- int i;
-
- /*
- * Check each possible QD65xx base address
- */
-
- for (i = 0; i < 2; i++) {
- unsigned long port = qd_port[i];
- u8 r, res;
-
-
- if (request_region(port, 2, "pata_qdi")) {
- /* Check for a card */
- local_irq_save(flags);
- /* I have no h/w that needs this delay but it
- is present in the historic code */
- r = inb(port);
- udelay(1);
- outb(0x19, port);
- udelay(1);
- res = inb(port);
- udelay(1);
- outb(r, port);
- udelay(1);
- local_irq_restore(flags);
-
- /* Fail */
- if (res == 0x19) {
- release_region(port, 2);
- continue;
- }
- /* Passes the presence test */
- r = inb(port + 1);
- udelay(1);
- /* Check port agrees with port set */
- if ((r & 2) >> 1 == i)
- qdi65_identify_port(r, res, port);
- release_region(port, 2);
- }
- }
-}
/**
* legacy_init - attach legacy interfaces
@@ -1450,17 +867,15 @@ static __init int legacy_init(void)
int ct = 0;
int primary = 0;
int secondary = 0;
- int pci_present = 0;
- struct legacy_probe *pl = &probe_list[0];
- int slot = 0;
+ int last_port = NR_HOST;
struct pci_dev *p = NULL;
for_each_pci_dev(p) {
int r;
- /* Check for any overlap of the system ATA mappings. Native
- mode controllers stuck on these addresses or some devices
- in 'raid' mode won't be found by the storage class test */
+ /* Check for any overlap of the system ATA mappings. Native mode controllers
+ stuck on these addresses or some devices in 'raid' mode won't be found by
+ the storage class test */
for (r = 0; r < 6; r++) {
if (pci_resource_start(p, r) == 0x1f0)
primary = 1;
@@ -1470,39 +885,49 @@ static __init int legacy_init(void)
/* Check for special cases */
legacy_check_special_cases(p, &primary, &secondary);
- /* If PCI bus is present then don't probe for tertiary
- legacy ports */
- pci_present = 1;
+ /* If PCI bus is present then don't probe for tertiary legacy ports */
+ if (probe_all == 0)
+ last_port = 2;
}
- if (winbond == 1)
- winbond = 0x130; /* Default port, alt is 1B0 */
-
- if (primary == 0 || all)
- legacy_probe_add(0x1F0, 14, UNKNOWN, 0);
- if (secondary == 0 || all)
- legacy_probe_add(0x170, 15, UNKNOWN, 0);
-
- if (probe_all || !pci_present) {
- /* ISA/VLB extra ports */
- legacy_probe_add(0x1E8, 11, UNKNOWN, 0);
- legacy_probe_add(0x168, 10, UNKNOWN, 0);
- legacy_probe_add(0x1E0, 8, UNKNOWN, 0);
- legacy_probe_add(0x160, 12, UNKNOWN, 0);
+ /* If an OPTI 82C46X is present find out where the channels are */
+ if (opti82c46x) {
+ static const char *optis[4] = {
+ "3/463MV", "5MV",
+ "5MVA", "5MVB"
+ };
+ u8 chans = 1;
+ u8 ctrl = (opti_syscfg(0x30) & 0xC0) >> 6;
+
+ opti82c46x = 3; /* Assume master and slave first */
+ printk(KERN_INFO DRV_NAME ": Opti 82C46%s chipset support.\n", optis[ctrl]);
+ if (ctrl == 3)
+ chans = (opti_syscfg(0x3F) & 0x20) ? 2 : 1;
+ ctrl = opti_syscfg(0xAC);
+ /* Check enabled and this port is the 465MV port. On the
+ MVB we may have two channels */
+ if (ctrl & 8) {
+ if (ctrl & 4)
+ opti82c46x = 2; /* Slave */
+ else
+ opti82c46x = 1; /* Master */
+ if (chans == 2)
+ opti82c46x = 3; /* Master and Slave */
+ } /* Slave only */
+ else if (chans == 1)
+ opti82c46x = 1;
}
- if (opti82c46x)
- probe_opti_vlb();
- if (qdi)
- probe_qdi_vlb();
-
- for (i = 0; i < NR_HOST; i++, pl++) {
- if (pl->port == 0)
+ for (i = 0; i < last_port; i++) {
+ /* Skip primary if we have seen a PCI one */
+ if (i == 0 && primary == 1)
+ continue;
+ /* Skip secondary if we have seen a PCI one */
+ if (i == 1 && secondary == 1)
continue;
- if (pl->type == UNKNOWN)
- pl->type = probe_chip_type(pl);
- pl->slot = slot++;
- if (legacy_init_one(pl) == 0)
+ if (legacy_init_one(i, legacy_port[i],
+ legacy_port[i] + 0x0206,
+ legacy_irq[i]) == 0)
ct++;
}
if (ct != 0)
@@ -1516,8 +941,11 @@ static __exit void legacy_exit(void)
for (i = 0; i < nr_legacy_host; i++) {
struct legacy_data *ld = &legacy_data[i];
+
ata_host_detach(legacy_host[i]);
platform_device_unregister(ld->platform_dev);
+ if (ld->timing)
+ release_region(ld->timing, 2);
}
}
@@ -1532,9 +960,9 @@ module_param(ht6560a, int, 0);
module_param(ht6560b, int, 0);
module_param(opti82c611a, int, 0);
module_param(opti82c46x, int, 0);
-module_param(qdi, int, 0);
module_param(pio_mask, int, 0);
module_param(iordy_mask, int, 0);
module_init(legacy_init);
module_exit(legacy_exit);
+
diff --git a/trunk/drivers/ata/pata_mpc52xx.c b/trunk/drivers/ata/pata_mpc52xx.c
index dc401626cdb2..50c56e2814c1 100644
--- a/trunk/drivers/ata/pata_mpc52xx.c
+++ b/trunk/drivers/ata/pata_mpc52xx.c
@@ -364,7 +364,7 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match)
{
unsigned int ipb_freq;
struct resource res_mem;
- int ata_irq;
+ int ata_irq = NO_IRQ;
struct mpc52xx_ata __iomem *ata_regs;
struct mpc52xx_ata_priv *priv;
int rv;
diff --git a/trunk/drivers/ata/pata_ninja32.c b/trunk/drivers/ata/pata_ninja32.c
deleted file mode 100644
index 1c1b83541d13..000000000000
--- a/trunk/drivers/ata/pata_ninja32.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * pata_ninja32.c - Ninja32 PATA for new ATA layer
- * (C) 2007 Red Hat Inc
- * Alan Cox
- *
- * Note: The controller like many controllers has shared timings for
- * PIO and DMA. We thus flip to the DMA timings in dma_start and flip back
- * in the dma_stop function. Thus we actually don't need a set_dmamode
- * method as the PIO method is always called and will set the right PIO
- * timing parameters.
- *
- * The Ninja32 Cardbus is not a generic SFF controller. Instead it is
- * laid out as follows off BAR 0. This is based upon Mark Lord's delkin
- * driver and the extensive analysis done by the BSD developers, notably
- * ITOH Yasufumi.
- *
- * Base + 0x00 IRQ Status
- * Base + 0x01 IRQ control
- * Base + 0x02 Chipset control
- * Base + 0x04 VDMA and reset control + wait bits
- * Base + 0x08 BMIMBA
- * Base + 0x0C DMA Length
- * Base + 0x10 Taskfile
- * Base + 0x18 BMDMA Status ?
- * Base + 0x1C
- * Base + 0x1D Bus master control
- * bit 0 = enable
- * bit 1 = 0 write/1 read
- * bit 2 = 1 sgtable
- * bit 3 = go
- * bit 4-6 wait bits
- * bit 7 = done
- * Base + 0x1E AltStatus
- * Base + 0x1F timing register
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define DRV_NAME "pata_ninja32"
-#define DRV_VERSION "0.0.1"
-
-
-/**
- * ninja32_set_piomode - set initial PIO mode data
- * @ap: ATA interface
- * @adev: ATA device
- *
- * Called to do the PIO mode setup. Our timing registers are shared
- * but we want to set the PIO timing by default.
- */
-
-static void ninja32_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
- static u16 pio_timing[5] = {
- 0xd6, 0x85, 0x44, 0x33, 0x13
- };
- iowrite8(pio_timing[adev->pio_mode - XFER_PIO_0],
- ap->ioaddr.bmdma_addr + 0x1f);
- ap->private_data = adev;
-}
-
-
-static void ninja32_dev_select(struct ata_port *ap, unsigned int device)
-{
- struct ata_device *adev = &ap->link.device[device];
- if (ap->private_data != adev) {
- iowrite8(0xd6, ap->ioaddr.bmdma_addr + 0x1f);
- ata_std_dev_select(ap, device);
- ninja32_set_piomode(ap, adev);
- }
-}
-
-static struct scsi_host_template ninja32_sht = {
- .module = THIS_MODULE,
- .name = DRV_NAME,
- .ioctl = ata_scsi_ioctl,
- .queuecommand = ata_scsi_queuecmd,
- .can_queue = ATA_DEF_QUEUE,
- .this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = LIBATA_MAX_PRD,
- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
- .emulated = ATA_SHT_EMULATED,
- .use_clustering = ATA_SHT_USE_CLUSTERING,
- .proc_name = DRV_NAME,
- .dma_boundary = ATA_DMA_BOUNDARY,
- .slave_configure = ata_scsi_slave_config,
- .slave_destroy = ata_scsi_slave_destroy,
- .bios_param = ata_std_bios_param,
-};
-
-static struct ata_port_operations ninja32_port_ops = {
- .set_piomode = ninja32_set_piomode,
- .mode_filter = ata_pci_default_filter,
-
- .tf_load = ata_tf_load,
- .tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .exec_command = ata_exec_command,
- .dev_select = ninja32_dev_select,
-
- .freeze = ata_bmdma_freeze,
- .thaw = ata_bmdma_thaw,
- .error_handler = ata_bmdma_error_handler,
- .post_internal_cmd = ata_bmdma_post_internal_cmd,
- .cable_detect = ata_cable_40wire,
-
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
- .bmdma_stop = ata_bmdma_stop,
- .bmdma_status = ata_bmdma_status,
-
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
-
- .data_xfer = ata_data_xfer,
-
- .irq_handler = ata_interrupt,
- .irq_clear = ata_bmdma_irq_clear,
- .irq_on = ata_irq_on,
-
- .port_start = ata_sff_port_start,
-};
-
-static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
- struct ata_host *host;
- struct ata_port *ap;
- void __iomem *base;
- int rc;
-
- host = ata_host_alloc(&dev->dev, 1);
- if (!host)
- return -ENOMEM;
- ap = host->ports[0];
-
- /* Set up the PCI device */
- rc = pcim_enable_device(dev);
- if (rc)
- return rc;
- rc = pcim_iomap_regions(dev, 1 << 0, DRV_NAME);
- if (rc == -EBUSY)
- pcim_pin_device(dev);
- if (rc)
- return rc;
-
- host->iomap = pcim_iomap_table(dev);
- rc = pci_set_dma_mask(dev, ATA_DMA_MASK);
- if (rc)
- return rc;
- rc = pci_set_consistent_dma_mask(dev, ATA_DMA_MASK);
- if (rc)
- return rc;
- pci_set_master(dev);
-
- /* Set up the register mappings */
- base = host->iomap[0];
- if (!base)
- return -ENOMEM;
- ap->ops = &ninja32_port_ops;
- ap->pio_mask = 0x1F;
- ap->flags |= ATA_FLAG_SLAVE_POSS;
-
- ap->ioaddr.cmd_addr = base + 0x10;
- ap->ioaddr.ctl_addr = base + 0x1E;
- ap->ioaddr.altstatus_addr = base + 0x1E;
- ap->ioaddr.bmdma_addr = base;
- ata_std_ports(&ap->ioaddr);
-
- iowrite8(0x05, base + 0x01); /* Enable interrupt lines */
- iowrite8(0xB3, base + 0x02); /* Burst, ?? setup */
- iowrite8(0x00, base + 0x04); /* WAIT0 ? */
- /* FIXME: Should we disable them at remove ? */
- return ata_host_activate(host, dev->irq, ata_interrupt,
- IRQF_SHARED, &ninja32_sht);
-}
-
-static const struct pci_device_id ninja32[] = {
- { 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { },
-};
-
-static struct pci_driver ninja32_pci_driver = {
- .name = DRV_NAME,
- .id_table = ninja32,
- .probe = ninja32_init_one,
- .remove = ata_pci_remove_one
-};
-
-static int __init ninja32_init(void)
-{
- return pci_register_driver(&ninja32_pci_driver);
-}
-
-static void __exit ninja32_exit(void)
-{
- pci_unregister_driver(&ninja32_pci_driver);
-}
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("low-level driver for Ninja32 ATA");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, ninja32);
-MODULE_VERSION(DRV_VERSION);
-
-module_init(ninja32_init);
-module_exit(ninja32_exit);
diff --git a/trunk/drivers/ata/pata_pcmcia.c b/trunk/drivers/ata/pata_pcmcia.c
index 3e7f6a9da28b..fd36099428a4 100644
--- a/trunk/drivers/ata/pata_pcmcia.c
+++ b/trunk/drivers/ata/pata_pcmcia.c
@@ -42,7 +42,7 @@
#define DRV_NAME "pata_pcmcia"
-#define DRV_VERSION "0.3.3"
+#define DRV_VERSION "0.3.2"
/*
* Private data structure to glue stuff together
@@ -86,47 +86,6 @@ static int pcmcia_set_mode(struct ata_link *link, struct ata_device **r_failed_d
return ata_do_set_mode(link, r_failed_dev);
}
-/**
- * pcmcia_set_mode_8bit - PCMCIA specific mode setup
- * @link: link
- * @r_failed_dev: Return pointer for failed device
- *
- * For the simple emulated 8bit stuff the less we do the better.
- */
-
-static int pcmcia_set_mode_8bit(struct ata_link *link,
- struct ata_device **r_failed_dev)
-{
- return 0;
-}
-
-/**
- * ata_data_xfer_8bit - Transfer data by 8bit PIO
- * @dev: device to target
- * @buf: data buffer
- * @buflen: buffer length
- * @rw: read/write
- *
- * Transfer data from/to the device data register by 8 bit PIO.
- *
- * LOCKING:
- * Inherited from caller.
- */
-
-static unsigned int ata_data_xfer_8bit(struct ata_device *dev,
- unsigned char *buf, unsigned int buflen, int rw)
-{
- struct ata_port *ap = dev->link->ap;
-
- if (rw == READ)
- ioread8_rep(ap->ioaddr.data_addr, buf, buflen);
- else
- iowrite8_rep(ap->ioaddr.data_addr, buf, buflen);
-
- return buflen;
-}
-
-
static struct scsi_host_template pcmcia_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
@@ -170,31 +129,6 @@ static struct ata_port_operations pcmcia_port_ops = {
.port_start = ata_sff_port_start,
};
-static struct ata_port_operations pcmcia_8bit_port_ops = {
- .set_mode = pcmcia_set_mode_8bit,
- .tf_load = ata_tf_load,
- .tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .exec_command = ata_exec_command,
- .dev_select = ata_std_dev_select,
-
- .freeze = ata_bmdma_freeze,
- .thaw = ata_bmdma_thaw,
- .error_handler = ata_bmdma_error_handler,
- .post_internal_cmd = ata_bmdma_post_internal_cmd,
- .cable_detect = ata_cable_40wire,
-
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
-
- .data_xfer = ata_data_xfer_8bit,
-
- .irq_clear = ata_bmdma_irq_clear,
- .irq_on = ata_irq_on,
-
- .port_start = ata_sff_port_start,
-};
-
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
@@ -219,12 +153,9 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
cistpl_cftable_entry_t dflt;
} *stk = NULL;
cistpl_cftable_entry_t *cfg;
- int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM, p;
+ int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM;
unsigned long io_base, ctl_base;
void __iomem *io_addr, *ctl_addr;
- int n_ports = 1;
-
- struct ata_port_operations *ops = &pcmcia_port_ops;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL)
@@ -351,32 +282,27 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
/* FIXME: Could be more ports at base + 0x10 but we only deal with
one right now */
if (pdev->io.NumPorts1 >= 0x20)
- n_ports = 2;
+ printk(KERN_WARNING DRV_NAME ": second channel not yet supported.\n");
- if (pdev->manf_id == 0x0097 && pdev->card_id == 0x1620)
- ops = &pcmcia_8bit_port_ops;
/*
* Having done the PCMCIA plumbing the ATA side is relatively
* sane.
*/
ret = -ENOMEM;
- host = ata_host_alloc(&pdev->dev, n_ports);
+ host = ata_host_alloc(&pdev->dev, 1);
if (!host)
goto failed;
+ ap = host->ports[0];
- for (p = 0; p < n_ports; p++) {
- ap = host->ports[p];
+ ap->ops = &pcmcia_port_ops;
+ ap->pio_mask = 1; /* ISA so PIO 0 cycles */
+ ap->flags |= ATA_FLAG_SLAVE_POSS;
+ ap->ioaddr.cmd_addr = io_addr;
+ ap->ioaddr.altstatus_addr = ctl_addr;
+ ap->ioaddr.ctl_addr = ctl_addr;
+ ata_std_ports(&ap->ioaddr);
- ap->ops = ops;
- ap->pio_mask = 1; /* ISA so PIO 0 cycles */
- ap->flags |= ATA_FLAG_SLAVE_POSS;
- ap->ioaddr.cmd_addr = io_addr + 0x10 * p;
- ap->ioaddr.altstatus_addr = ctl_addr + 0x10 * p;
- ap->ioaddr.ctl_addr = ctl_addr + 0x10 * p;
- ata_std_ports(&ap->ioaddr);
-
- ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io_base, ctl_base);
- }
+ ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io_base, ctl_base);
/* activate */
ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_interrupt,
@@ -434,7 +360,6 @@ static struct pcmcia_device_id pcmcia_devices[] = {
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */
- PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */
PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */
diff --git a/trunk/drivers/ata/pata_pdc2027x.c b/trunk/drivers/ata/pata_pdc2027x.c
index 028af5dbeed6..2622577521a1 100644
--- a/trunk/drivers/ata/pata_pdc2027x.c
+++ b/trunk/drivers/ata/pata_pdc2027x.c
@@ -348,7 +348,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long
ata_id_c_string(pair->id, model_num, ATA_ID_PROD,
ATA_ID_PROD_LEN + 1);
/* If the master is a maxtor in UDMA6 then the slave should not use UDMA 6 */
- if (strstr(model_num, "Maxtor") == NULL && pair->dma_mode == XFER_UDMA_6)
+ if (strstr(model_num, "Maxtor") == 0 && pair->dma_mode == XFER_UDMA_6)
mask &= ~ (1 << (6 + ATA_SHIFT_UDMA));
return ata_pci_default_filter(adev, mask);
diff --git a/trunk/drivers/ata/pata_pdc202xx_old.c b/trunk/drivers/ata/pata_pdc202xx_old.c
index 3ed866723e0c..6c9689b59b06 100644
--- a/trunk/drivers/ata/pata_pdc202xx_old.c
+++ b/trunk/drivers/ata/pata_pdc202xx_old.c
@@ -168,7 +168,8 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc)
pdc202xx_set_dmamode(ap, qc->dev);
/* Cases the state machine will not complete correctly without help */
- if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATAPI_PROT_DMA) {
+ if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATA_PROT_ATAPI_DMA)
+ {
len = qc->nbytes / 2;
if (tf->flags & ATA_TFLAG_WRITE)
@@ -207,7 +208,7 @@ static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc)
void __iomem *atapi_reg = master + 0x20 + (4 * ap->port_no);
/* Cases the state machine will not complete correctly */
- if (tf->protocol == ATAPI_PROT_DMA || (tf->flags & ATA_TFLAG_LBA48)) {
+ if (tf->protocol == ATA_PROT_ATAPI_DMA || ( tf->flags & ATA_TFLAG_LBA48)) {
iowrite32(0, atapi_reg);
iowrite8(ioread8(clock) & ~sel66, clock);
}
diff --git a/trunk/drivers/ata/pata_qdi.c b/trunk/drivers/ata/pata_qdi.c
index 9f308ed76cc8..a4c0e502cb42 100644
--- a/trunk/drivers/ata/pata_qdi.c
+++ b/trunk/drivers/ata/pata_qdi.c
@@ -124,33 +124,29 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
return ata_qc_issue_prot(qc);
}
-static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
- unsigned int buflen, int rw)
+static void qdi_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
{
- if (ata_id_has_dword_io(dev->id)) {
- struct ata_port *ap = dev->link->ap;
- int slop = buflen & 3;
+ struct ata_port *ap = adev->link->ap;
+ int slop = buflen & 3;
- if (rw == READ)
- ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
- else
+ if (ata_id_has_dword_io(adev->id)) {
+ if (write_data)
iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+ else
+ ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
if (unlikely(slop)) {
- u32 pad;
- if (rw == READ) {
- pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
- memcpy(buf + buflen - slop, &pad, slop);
- } else {
+ __le32 pad = 0;
+ if (write_data) {
memcpy(&pad, buf + buflen - slop, slop);
iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
+ } else {
+ pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
+ memcpy(buf + buflen - slop, &pad, slop);
}
- buflen += 4 - slop;
}
} else
- buflen = ata_data_xfer(dev, buf, buflen, rw);
-
- return buflen;
+ ata_data_xfer(adev, buf, buflen, write_data);
}
static struct scsi_host_template qdi_sht = {
diff --git a/trunk/drivers/ata/pata_scc.c b/trunk/drivers/ata/pata_scc.c
index 55055b27524c..ea2ef9fc15be 100644
--- a/trunk/drivers/ata/pata_scc.c
+++ b/trunk/drivers/ata/pata_scc.c
@@ -768,47 +768,45 @@ static u8 scc_bmdma_status (struct ata_port *ap)
/**
* scc_data_xfer - Transfer data by PIO
- * @dev: device for this I/O
+ * @adev: device for this I/O
* @buf: data buffer
* @buflen: buffer length
- * @rw: read/write
+ * @write_data: read/write
*
* Note: Original code is ata_data_xfer().
*/
-static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,
- unsigned int buflen, int rw)
+static void scc_data_xfer (struct ata_device *adev, unsigned char *buf,
+ unsigned int buflen, int write_data)
{
- struct ata_port *ap = dev->link->ap;
+ struct ata_port *ap = adev->link->ap;
unsigned int words = buflen >> 1;
unsigned int i;
u16 *buf16 = (u16 *) buf;
void __iomem *mmio = ap->ioaddr.data_addr;
/* Transfer multiple of 2 bytes */
- if (rw == READ)
- for (i = 0; i < words; i++)
- buf16[i] = le16_to_cpu(in_be32(mmio));
- else
+ if (write_data) {
for (i = 0; i < words; i++)
out_be32(mmio, cpu_to_le16(buf16[i]));
+ } else {
+ for (i = 0; i < words; i++)
+ buf16[i] = le16_to_cpu(in_be32(mmio));
+ }
/* Transfer trailing 1 byte, if any. */
if (unlikely(buflen & 0x01)) {
u16 align_buf[1] = { 0 };
unsigned char *trailing_buf = buf + buflen - 1;
- if (rw == READ) {
- align_buf[0] = le16_to_cpu(in_be32(mmio));
- memcpy(trailing_buf, align_buf, 1);
- } else {
+ if (write_data) {
memcpy(align_buf, trailing_buf, 1);
out_be32(mmio, cpu_to_le16(align_buf[0]));
+ } else {
+ align_buf[0] = le16_to_cpu(in_be32(mmio));
+ memcpy(trailing_buf, align_buf, 1);
}
- words++;
}
-
- return words << 1;
}
/**
diff --git a/trunk/drivers/ata/pata_serverworks.c b/trunk/drivers/ata/pata_serverworks.c
index 9c523fbf529e..8bed88873720 100644
--- a/trunk/drivers/ata/pata_serverworks.c
+++ b/trunk/drivers/ata/pata_serverworks.c
@@ -41,7 +41,7 @@
#include
#define DRV_NAME "pata_serverworks"
-#define DRV_VERSION "0.4.3"
+#define DRV_VERSION "0.4.2"
#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
@@ -102,7 +102,7 @@ static int osb4_cable(struct ata_port *ap) {
}
/**
- * csb_cable - CSB5/6 cable detect
+ * csb4_cable - CSB5/6 cable detect
* @ap: ATA port to check
*
* Serverworks default arrangement is to use the drive side detection
@@ -110,7 +110,7 @@ static int osb4_cable(struct ata_port *ap) {
*/
static int csb_cable(struct ata_port *ap) {
- return ATA_CBL_PATA_UNK;
+ return ATA_CBL_PATA80;
}
struct sv_cable_table {
@@ -231,6 +231,7 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
return ata_pci_default_filter(adev, mask);
}
+
/**
* serverworks_set_piomode - set initial PIO mode data
* @ap: ATA interface
@@ -242,7 +243,7 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
static void serverworks_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
static const u8 pio_mode[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
- int offset = 1 + 2 * ap->port_no - adev->devno;
+ int offset = 1 + (2 * ap->port_no) - adev->devno;
int devbits = (2 * ap->port_no + adev->devno) * 4;
u16 csb5_pio;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
diff --git a/trunk/drivers/ata/pata_via.c b/trunk/drivers/ata/pata_via.c
index 39627ab684bf..453d72bf2598 100644
--- a/trunk/drivers/ata/pata_via.c
+++ b/trunk/drivers/ata/pata_via.c
@@ -185,8 +185,7 @@ static int via_cable_detect(struct ata_port *ap) {
if (ata66 & (0x10100000 >> (16 * ap->port_no)))
return ATA_CBL_PATA80;
/* Check with ACPI so we can spot BIOS reported SATA bridges */
- if (ata_acpi_init_gtm(ap) &&
- ata_acpi_cbl_80wire(ap, ata_acpi_init_gtm(ap)))
+ if (ata_acpi_cbl_80wire(ap))
return ATA_CBL_PATA80;
return ATA_CBL_PATA40;
}
diff --git a/trunk/drivers/ata/pata_winbond.c b/trunk/drivers/ata/pata_winbond.c
index 99c92eda217b..7116a9e7a8b2 100644
--- a/trunk/drivers/ata/pata_winbond.c
+++ b/trunk/drivers/ata/pata_winbond.c
@@ -92,33 +92,29 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
}
-static unsigned int winbond_data_xfer(struct ata_device *dev,
- unsigned char *buf, unsigned int buflen, int rw)
+static void winbond_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
{
- struct ata_port *ap = dev->link->ap;
+ struct ata_port *ap = adev->link->ap;
int slop = buflen & 3;
- if (ata_id_has_dword_io(dev->id)) {
- if (rw == READ)
- ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
- else
+ if (ata_id_has_dword_io(adev->id)) {
+ if (write_data)
iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+ else
+ ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
if (unlikely(slop)) {
- u32 pad;
- if (rw == READ) {
- pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
- memcpy(buf + buflen - slop, &pad, slop);
- } else {
+ __le32 pad = 0;
+ if (write_data) {
memcpy(&pad, buf + buflen - slop, slop);
iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
+ } else {
+ pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
+ memcpy(buf + buflen - slop, &pad, slop);
}
- buflen += 4 - slop;
}
} else
- buflen = ata_data_xfer(dev, buf, buflen, rw);
-
- return buflen;
+ ata_data_xfer(adev, buf, buflen, write_data);
}
static struct scsi_host_template winbond_sht = {
@@ -195,7 +191,7 @@ static __init int winbond_init_one(unsigned long port)
reg = winbond_readcfg(port, 0x81);
if (!(reg & 0x03)) /* Disabled */
- return -ENODEV;
+ return 0;
for (i = 0; i < 2 ; i ++) {
unsigned long cmd_port = 0x1F0 - (0x80 * i);
diff --git a/trunk/drivers/ata/pdc_adma.c b/trunk/drivers/ata/pdc_adma.c
index 8e1b7e9c0ae4..bd4c2a3c88d7 100644
--- a/trunk/drivers/ata/pdc_adma.c
+++ b/trunk/drivers/ata/pdc_adma.c
@@ -321,9 +321,8 @@ static int adma_fill_sg(struct ata_queued_cmd *qc)
u8 *buf = pp->pkt, *last_buf = NULL;
int i = (2 + buf[3]) * 8;
u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
- unsigned int si;
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ata_for_each_sg(sg, qc) {
u32 addr;
u32 len;
@@ -456,7 +455,7 @@ static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
adma_packet_start(qc);
return 0;
- case ATAPI_PROT_DMA:
+ case ATA_PROT_ATAPI_DMA:
BUG();
break;
diff --git a/trunk/drivers/ata/sata_fsl.c b/trunk/drivers/ata/sata_fsl.c
index 922d7b2efba8..d015b4adcfe0 100644
--- a/trunk/drivers/ata/sata_fsl.c
+++ b/trunk/drivers/ata/sata_fsl.c
@@ -333,14 +333,13 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
struct prde *prd_ptr_to_indirect_ext = NULL;
unsigned indirect_ext_segment_sz = 0;
dma_addr_t indirect_ext_segment_paddr;
- unsigned int si;
VPRINTK("SATA FSL : cd = 0x%x, prd = 0x%x\n", cmd_desc, prd);
indirect_ext_segment_paddr = cmd_desc_paddr +
SATA_FSL_CMD_DESC_OFFSET_TO_PRDT + SATA_FSL_MAX_PRD_DIRECT * 16;
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ata_for_each_sg(sg, qc) {
dma_addr_t sg_addr = sg_dma_address(sg);
u32 sg_len = sg_dma_len(sg);
@@ -418,7 +417,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
}
/* setup "ACMD - atapi command" in cmd. desc. if this is ATAPI cmd */
- if (ata_is_atapi(qc->tf.protocol)) {
+ if (is_atapi_taskfile(&qc->tf)) {
desc_info |= ATAPI_CMD;
memset((void *)&cd->acmd, 0, 32);
memcpy((void *)&cd->acmd, qc->cdb, qc->dev->cdb_len);
diff --git a/trunk/drivers/ata/sata_inic162x.c b/trunk/drivers/ata/sata_inic162x.c
index 96e614a1c169..323c087e8cc1 100644
--- a/trunk/drivers/ata/sata_inic162x.c
+++ b/trunk/drivers/ata/sata_inic162x.c
@@ -585,7 +585,7 @@ static struct ata_port_operations inic_port_ops = {
};
static struct ata_port_info inic_port_info = {
- /* For some reason, ATAPI_PROT_PIO is broken on this
+ /* For some reason, ATA_PROT_ATAPI is broken on this
* controller, and no, PIO_POLLING does't fix it. It somehow
* manages to report the wrong ireason and ignoring ireason
* results in machine lock up. Tell libata to always prefer
diff --git a/trunk/drivers/ata/sata_mv.c b/trunk/drivers/ata/sata_mv.c
index 7e72463a90eb..37b850ae0845 100644
--- a/trunk/drivers/ata/sata_mv.c
+++ b/trunk/drivers/ata/sata_mv.c
@@ -1136,10 +1136,9 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
struct mv_port_priv *pp = qc->ap->private_data;
struct scatterlist *sg;
struct mv_sg *mv_sg, *last_sg = NULL;
- unsigned int si;
mv_sg = pp->sg_tbl;
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ata_for_each_sg(sg, qc) {
dma_addr_t addr = sg_dma_address(sg);
u32 sg_len = sg_dma_len(sg);
diff --git a/trunk/drivers/ata/sata_nv.c b/trunk/drivers/ata/sata_nv.c
index a0f98fdab7a0..ed5dc7cb50cd 100644
--- a/trunk/drivers/ata/sata_nv.c
+++ b/trunk/drivers/ata/sata_nv.c
@@ -1336,18 +1336,21 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc,
static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
{
struct nv_adma_port_priv *pp = qc->ap->private_data;
+ unsigned int idx;
struct nv_adma_prd *aprd;
struct scatterlist *sg;
- unsigned int si;
VPRINTK("ENTER\n");
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
- aprd = (si < 5) ? &cpb->aprd[si] :
- &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (si-5)];
- nv_adma_fill_aprd(qc, sg, si, aprd);
+ idx = 0;
+
+ ata_for_each_sg(sg, qc) {
+ aprd = (idx < 5) ? &cpb->aprd[idx] :
+ &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)];
+ nv_adma_fill_aprd(qc, sg, idx, aprd);
+ idx++;
}
- if (si > 5)
+ if (idx > 5)
cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag)));
else
cpb->next_aprd = cpu_to_le64(0);
@@ -1992,14 +1995,17 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct scatterlist *sg;
+ unsigned int idx;
struct nv_swncq_port_priv *pp = ap->private_data;
struct ata_prd *prd;
- unsigned int si, idx;
+
+ WARN_ON(qc->__sg == NULL);
+ WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
prd = pp->prd + ATA_MAX_PRD * qc->tag;
idx = 0;
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ata_for_each_sg(sg, qc) {
u32 addr, offset;
u32 sg_len, len;
@@ -2021,7 +2027,8 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
}
}
- prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+ if (idx)
+ prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
}
static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap,
diff --git a/trunk/drivers/ata/sata_promise.c b/trunk/drivers/ata/sata_promise.c
index a07d319f6e8c..7914def54fa3 100644
--- a/trunk/drivers/ata/sata_promise.c
+++ b/trunk/drivers/ata/sata_promise.c
@@ -450,19 +450,19 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
struct pdc_port_priv *pp = ap->private_data;
u8 *buf = pp->pkt;
u32 *buf32 = (u32 *) buf;
- unsigned int dev_sel, feature;
+ unsigned int dev_sel, feature, nbytes;
/* set control bits (byte 0), zero delay seq id (byte 3),
* and seq id (byte 2)
*/
switch (qc->tf.protocol) {
- case ATAPI_PROT_DMA:
+ case ATA_PROT_ATAPI_DMA:
if (!(qc->tf.flags & ATA_TFLAG_WRITE))
buf32[0] = cpu_to_le32(PDC_PKT_READ);
else
buf32[0] = 0;
break;
- case ATAPI_PROT_NODATA:
+ case ATA_PROT_ATAPI_NODATA:
buf32[0] = cpu_to_le32(PDC_PKT_NODATA);
break;
default:
@@ -473,37 +473,45 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
buf32[2] = 0; /* no next-packet */
/* select drive */
- if (sata_scr_valid(&ap->link))
+ if (sata_scr_valid(&ap->link)) {
dev_sel = PDC_DEVICE_SATA;
- else
- dev_sel = qc->tf.device;
-
+ } else {
+ dev_sel = ATA_DEVICE_OBS;
+ if (qc->dev->devno != 0)
+ dev_sel |= ATA_DEV1;
+ }
buf[12] = (1 << 5) | ATA_REG_DEVICE;
buf[13] = dev_sel;
buf[14] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_CLEAR_BSY;
buf[15] = dev_sel; /* once more, waiting for BSY to clear */
buf[16] = (1 << 5) | ATA_REG_NSECT;
- buf[17] = qc->tf.nsect;
+ buf[17] = 0x00;
buf[18] = (1 << 5) | ATA_REG_LBAL;
- buf[19] = qc->tf.lbal;
+ buf[19] = 0x00;
/* set feature and byte counter registers */
- if (qc->tf.protocol != ATAPI_PROT_DMA)
+ if (qc->tf.protocol != ATA_PROT_ATAPI_DMA) {
feature = PDC_FEATURE_ATAPI_PIO;
- else
+ /* set byte counter register to real transfer byte count */
+ nbytes = qc->nbytes;
+ if (nbytes > 0xffff)
+ nbytes = 0xffff;
+ } else {
feature = PDC_FEATURE_ATAPI_DMA;
-
+ /* set byte counter register to 0 */
+ nbytes = 0;
+ }
buf[20] = (1 << 5) | ATA_REG_FEATURE;
buf[21] = feature;
buf[22] = (1 << 5) | ATA_REG_BYTEL;
- buf[23] = qc->tf.lbam;
+ buf[23] = nbytes & 0xFF;
buf[24] = (1 << 5) | ATA_REG_BYTEH;
- buf[25] = qc->tf.lbah;
+ buf[25] = (nbytes >> 8) & 0xFF;
/* send ATAPI packet command 0xA0 */
buf[26] = (1 << 5) | ATA_REG_CMD;
- buf[27] = qc->tf.command;
+ buf[27] = ATA_CMD_PACKET;
/* select drive and check DRQ */
buf[28] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_WAIT_DRDY;
@@ -533,15 +541,17 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct scatterlist *sg;
+ unsigned int idx;
const u32 SG_COUNT_ASIC_BUG = 41*4;
- unsigned int si, idx;
- u32 len;
if (!(qc->flags & ATA_QCFLAG_DMAMAP))
return;
+ WARN_ON(qc->__sg == NULL);
+ WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+
idx = 0;
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ata_for_each_sg(sg, qc) {
u32 addr, offset;
u32 sg_len, len;
@@ -568,27 +578,29 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc)
}
}
- len = le32_to_cpu(ap->prd[idx - 1].flags_len);
+ if (idx) {
+ u32 len = le32_to_cpu(ap->prd[idx - 1].flags_len);
- if (len > SG_COUNT_ASIC_BUG) {
- u32 addr;
+ if (len > SG_COUNT_ASIC_BUG) {
+ u32 addr;
- VPRINTK("Splitting last PRD.\n");
+ VPRINTK("Splitting last PRD.\n");
- addr = le32_to_cpu(ap->prd[idx - 1].addr);
- ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG);
- VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG);
+ addr = le32_to_cpu(ap->prd[idx - 1].addr);
+ ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG);
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG);
- addr = addr + len - SG_COUNT_ASIC_BUG;
- len = SG_COUNT_ASIC_BUG;
- ap->prd[idx].addr = cpu_to_le32(addr);
- ap->prd[idx].flags_len = cpu_to_le32(len);
- VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
+ addr = addr + len - SG_COUNT_ASIC_BUG;
+ len = SG_COUNT_ASIC_BUG;
+ ap->prd[idx].addr = cpu_to_le32(addr);
+ ap->prd[idx].flags_len = cpu_to_le32(len);
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
- idx++;
- }
+ idx++;
+ }
- ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+ ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+ }
}
static void pdc_qc_prep(struct ata_queued_cmd *qc)
@@ -615,14 +627,14 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
pdc_pkt_footer(&qc->tf, pp->pkt, i);
break;
- case ATAPI_PROT_PIO:
+ case ATA_PROT_ATAPI:
pdc_fill_sg(qc);
break;
- case ATAPI_PROT_DMA:
+ case ATA_PROT_ATAPI_DMA:
pdc_fill_sg(qc);
/*FALLTHROUGH*/
- case ATAPI_PROT_NODATA:
+ case ATA_PROT_ATAPI_NODATA:
pdc_atapi_pkt(qc);
break;
@@ -742,8 +754,8 @@ static inline unsigned int pdc_host_intr(struct ata_port *ap,
switch (qc->tf.protocol) {
case ATA_PROT_DMA:
case ATA_PROT_NODATA:
- case ATAPI_PROT_DMA:
- case ATAPI_PROT_NODATA:
+ case ATA_PROT_ATAPI_DMA:
+ case ATA_PROT_ATAPI_NODATA:
qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
ata_qc_complete(qc);
handled = 1;
@@ -888,7 +900,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
{
switch (qc->tf.protocol) {
- case ATAPI_PROT_NODATA:
+ case ATA_PROT_ATAPI_NODATA:
if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
break;
/*FALLTHROUGH*/
@@ -896,7 +908,7 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
if (qc->tf.flags & ATA_TFLAG_POLLING)
break;
/*FALLTHROUGH*/
- case ATAPI_PROT_DMA:
+ case ATA_PROT_ATAPI_DMA:
case ATA_PROT_DMA:
pdc_packet_start(qc);
return 0;
@@ -910,14 +922,16 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
- WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
+ WARN_ON(tf->protocol == ATA_PROT_DMA ||
+ tf->protocol == ATA_PROT_ATAPI_DMA);
ata_tf_load(ap, tf);
}
static void pdc_exec_command_mmio(struct ata_port *ap,
const struct ata_taskfile *tf)
{
- WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
+ WARN_ON(tf->protocol == ATA_PROT_DMA ||
+ tf->protocol == ATA_PROT_ATAPI_DMA);
ata_exec_command(ap, tf);
}
diff --git a/trunk/drivers/ata/sata_promise.h b/trunk/drivers/ata/sata_promise.h
index 00d6000e546f..6ee5e190262d 100644
--- a/trunk/drivers/ata/sata_promise.h
+++ b/trunk/drivers/ata/sata_promise.h
@@ -46,7 +46,7 @@ static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf,
unsigned int devno, u8 *buf)
{
u8 dev_reg;
- __le32 *buf32 = (__le32 *) buf;
+ u32 *buf32 = (u32 *) buf;
/* set control bits (byte 0), zero delay seq id (byte 3),
* and seq id (byte 2)
diff --git a/trunk/drivers/ata/sata_qstor.c b/trunk/drivers/ata/sata_qstor.c
index 91cc12c82040..c68b241805fd 100644
--- a/trunk/drivers/ata/sata_qstor.c
+++ b/trunk/drivers/ata/sata_qstor.c
@@ -287,10 +287,14 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
struct scatterlist *sg;
struct ata_port *ap = qc->ap;
struct qs_port_priv *pp = ap->private_data;
+ unsigned int nelem;
u8 *prd = pp->pkt + QS_CPB_BYTES;
- unsigned int si;
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ WARN_ON(qc->__sg == NULL);
+ WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+
+ nelem = 0;
+ ata_for_each_sg(sg, qc) {
u64 addr;
u32 len;
@@ -302,11 +306,12 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
*(__le32 *)prd = cpu_to_le32(len);
prd += sizeof(u64);
- VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", si,
+ VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", nelem,
(unsigned long long)addr, len);
+ nelem++;
}
- return si;
+ return nelem;
}
static void qs_qc_prep(struct ata_queued_cmd *qc)
@@ -371,7 +376,7 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
qs_packet_start(qc);
return 0;
- case ATAPI_PROT_DMA:
+ case ATA_PROT_ATAPI_DMA:
BUG();
break;
diff --git a/trunk/drivers/ata/sata_sil.c b/trunk/drivers/ata/sata_sil.c
index 0b8191b52f97..f5119bf40c24 100644
--- a/trunk/drivers/ata/sata_sil.c
+++ b/trunk/drivers/ata/sata_sil.c
@@ -416,14 +416,15 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
*/
/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
- * The flag was turned on only for atapi devices. No
- * need to check ata_is_atapi(qc->tf.protocol) again.
+ * The flag was turned on only for atapi devices.
+ * No need to check is_atapi_taskfile(&qc->tf) again.
*/
if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
goto err_hsm;
break;
case HSM_ST_LAST:
- if (ata_is_dma(qc->tf.protocol)) {
+ if (qc->tf.protocol == ATA_PROT_DMA ||
+ qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
/* clear DMA-Start bit */
ap->ops->bmdma_stop(qc);
@@ -450,7 +451,8 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
/* kick HSM in the ass */
ata_hsm_move(ap, qc, status, 0);
- if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol))
+ if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
+ qc->tf.protocol == ATA_PROT_ATAPI_DMA))
ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2);
return;
diff --git a/trunk/drivers/ata/sata_sil24.c b/trunk/drivers/ata/sata_sil24.c
index b4b1f91ea693..864c1c1b8511 100644
--- a/trunk/drivers/ata/sata_sil24.c
+++ b/trunk/drivers/ata/sata_sil24.c
@@ -813,9 +813,8 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
{
struct scatterlist *sg;
struct sil24_sge *last_sge = NULL;
- unsigned int si;
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ata_for_each_sg(sg, qc) {
sge->addr = cpu_to_le64(sg_dma_address(sg));
sge->cnt = cpu_to_le32(sg_dma_len(sg));
sge->flags = 0;
@@ -824,7 +823,8 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
sge++;
}
- last_sge->flags = cpu_to_le32(SGE_TRM);
+ if (likely(last_sge))
+ last_sge->flags = cpu_to_le32(SGE_TRM);
}
static int sil24_qc_defer(struct ata_queued_cmd *qc)
@@ -852,7 +852,9 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc)
* set.
*
*/
- int is_excl = (ata_is_atapi(prot) ||
+ int is_excl = (prot == ATA_PROT_ATAPI ||
+ prot == ATA_PROT_ATAPI_NODATA ||
+ prot == ATA_PROT_ATAPI_DMA ||
(qc->flags & ATA_QCFLAG_RESULT_TF));
if (unlikely(ap->excl_link)) {
@@ -883,21 +885,35 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
cb = &pp->cmd_block[sil24_tag(qc->tag)];
- if (!ata_is_atapi(qc->tf.protocol)) {
+ switch (qc->tf.protocol) {
+ case ATA_PROT_PIO:
+ case ATA_PROT_DMA:
+ case ATA_PROT_NCQ:
+ case ATA_PROT_NODATA:
prb = &cb->ata.prb;
sge = cb->ata.sge;
- } else {
+ break;
+
+ case ATA_PROT_ATAPI:
+ case ATA_PROT_ATAPI_DMA:
+ case ATA_PROT_ATAPI_NODATA:
prb = &cb->atapi.prb;
sge = cb->atapi.sge;
memset(cb->atapi.cdb, 0, 32);
memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len);
- if (ata_is_data(qc->tf.protocol)) {
+ if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
if (qc->tf.flags & ATA_TFLAG_WRITE)
ctrl = PRB_CTRL_PACKET_WRITE;
else
ctrl = PRB_CTRL_PACKET_READ;
}
+ break;
+
+ default:
+ prb = NULL; /* shut up, gcc */
+ sge = NULL;
+ BUG();
}
prb->ctrl = cpu_to_le16(ctrl);
diff --git a/trunk/drivers/ata/sata_sx4.c b/trunk/drivers/ata/sata_sx4.c
index e3d56bc6726d..4d857185f33b 100644
--- a/trunk/drivers/ata/sata_sx4.c
+++ b/trunk/drivers/ata/sata_sx4.c
@@ -334,7 +334,7 @@ static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
{
u32 addr;
unsigned int dw = PDC_DIMM_APKT_PRD >> 2;
- __le32 *buf32 = (__le32 *) buf;
+ u32 *buf32 = (u32 *) buf;
/* output ATA packet S/G table */
addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
@@ -356,7 +356,7 @@ static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf,
{
u32 addr;
unsigned int dw = PDC_DIMM_HPKT_PRD >> 2;
- __le32 *buf32 = (__le32 *) buf;
+ u32 *buf32 = (u32 *) buf;
/* output Host DMA packet S/G table */
addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
@@ -377,7 +377,7 @@ static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf,
unsigned int portno)
{
unsigned int i, dw;
- __le32 *buf32 = (__le32 *) buf;
+ u32 *buf32 = (u32 *) buf;
u8 dev_reg;
unsigned int dimm_sg = PDC_20621_DIMM_BASE +
@@ -429,8 +429,7 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
unsigned int portno)
{
unsigned int dw;
- u32 tmp;
- __le32 *buf32 = (__le32 *) buf;
+ u32 tmp, *buf32 = (u32 *) buf;
unsigned int host_sg = PDC_20621_DIMM_BASE +
(PDC_DIMM_WINDOW_STEP * portno) +
@@ -474,7 +473,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR];
void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
unsigned int portno = ap->port_no;
- unsigned int i, si, idx, total_len = 0, sgt_len;
+ unsigned int i, idx, total_len = 0, sgt_len;
u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
@@ -488,7 +487,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
* Build S/G table
*/
idx = 0;
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ ata_for_each_sg(sg, qc) {
buf[idx++] = cpu_to_le32(sg_dma_address(sg));
buf[idx++] = cpu_to_le32(sg_dma_len(sg));
total_len += sg_dma_len(sg);
@@ -701,7 +700,7 @@ static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
pdc20621_packet_start(qc);
return 0;
- case ATAPI_PROT_DMA:
+ case ATA_PROT_ATAPI_DMA:
BUG();
break;
diff --git a/trunk/drivers/ide/Kconfig b/trunk/drivers/ide/Kconfig
index ee01e273a537..fb06555708a8 100644
--- a/trunk/drivers/ide/Kconfig
+++ b/trunk/drivers/ide/Kconfig
@@ -374,6 +374,17 @@ comment "PCI IDE chipsets support"
config BLK_DEV_IDEPCI
bool
+config IDEPCI_SHARE_IRQ
+ bool "Sharing PCI IDE interrupts support"
+ depends on BLK_DEV_IDEPCI
+ help
+ Some ATA/IDE chipsets have hardware support which allows for
+ sharing a single IRQ with other cards. To enable support for
+ this in the ATA/IDE driver, say Y here.
+
+ It is safe to say Y to this question, in most cases.
+ If unsure, say N.
+
config IDEPCI_PCIBUS_ORDER
def_bool BLK_DEV_IDE=y && BLK_DEV_IDEPCI
@@ -696,6 +707,7 @@ config BLK_DEV_SVWKS
config BLK_DEV_SGIIOC4
tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support"
depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4
+ select IDEPCI_SHARE_IRQ
select BLK_DEV_IDEDMA_PCI
help
This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
diff --git a/trunk/drivers/ide/arm/icside.c b/trunk/drivers/ide/arm/icside.c
index 673402f4a295..93f71fcfc04d 100644
--- a/trunk/drivers/ide/arm/icside.c
+++ b/trunk/drivers/ide/arm/icside.c
@@ -272,6 +272,8 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
case XFER_SW_DMA_0:
cycle_time = 480;
break;
+ default:
+ return;
}
/*
diff --git a/trunk/drivers/ide/cris/ide-cris.c b/trunk/drivers/ide/cris/ide-cris.c
index 325e608d9e62..476e0d65ed43 100644
--- a/trunk/drivers/ide/cris/ide-cris.c
+++ b/trunk/drivers/ide/cris/ide-cris.c
@@ -747,6 +747,8 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed)
strobe = ATA_DMA2_STROBE;
hold = ATA_DMA2_HOLD;
break;
+ default:
+ return;
}
if (speed >= XFER_UDMA_0)
diff --git a/trunk/drivers/ide/ide-acpi.c b/trunk/drivers/ide/ide-acpi.c
index e0bb0cfa7bdd..899d56536e80 100644
--- a/trunk/drivers/ide/ide-acpi.c
+++ b/trunk/drivers/ide/ide-acpi.c
@@ -383,19 +383,27 @@ static int taskfile_load_raw(ide_drive_t *drive,
gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
memset(&args, 0, sizeof(ide_task_t));
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.data_phase = TASKFILE_NO_DATA;
+ args.handler = &task_no_data_intr;
/* convert gtf to IDE Taskfile */
- memcpy(&args.tf_array[7], >f->tfa, 7);
- args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
+ args.tfRegister[1] = gtf->tfa[0]; /* 0x1f1 */
+ args.tfRegister[2] = gtf->tfa[1]; /* 0x1f2 */
+ args.tfRegister[3] = gtf->tfa[2]; /* 0x1f3 */
+ args.tfRegister[4] = gtf->tfa[3]; /* 0x1f4 */
+ args.tfRegister[5] = gtf->tfa[4]; /* 0x1f5 */
+ args.tfRegister[6] = gtf->tfa[5]; /* 0x1f6 */
+ args.tfRegister[7] = gtf->tfa[6]; /* 0x1f7 */
if (ide_noacpitfs) {
DEBPRINT("_GTF execution disabled\n");
return err;
}
- err = ide_no_data_taskfile(drive, &args);
+ err = ide_raw_taskfile(drive, &args, NULL);
if (err)
- printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n",
+ printk(KERN_ERR "%s: ide_raw_taskfile failed: %u\n",
__FUNCTION__, err);
return err;
diff --git a/trunk/drivers/ide/ide-cd.c b/trunk/drivers/ide/ide-cd.c
index 44b033ec0ab0..c7d77f0ad892 100644
--- a/trunk/drivers/ide/ide-cd.c
+++ b/trunk/drivers/ide/ide-cd.c
@@ -917,13 +917,19 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
return startstop;
- /* FIXME: for Virtual DMA we must check harder */
if (info->dma)
info->dma = !hwif->dma_setup(drive);
/* Set up the controller registers. */
- ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
- IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
+ /* FIXME: for Virtual DMA we must check harder */
+ HWIF(drive)->OUTB(info->dma, IDE_FEATURE_REG);
+ HWIF(drive)->OUTB(0, IDE_IREASON_REG);
+ HWIF(drive)->OUTB(0, IDE_SECTOR_REG);
+
+ HWIF(drive)->OUTB(xferlen & 0xff, IDE_BCOUNTL_REG);
+ HWIF(drive)->OUTB(xferlen >> 8 , IDE_BCOUNTH_REG);
+ if (IDE_CONTROL_REG)
+ HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
/* waiting for CDB interrupt, not DMA yet. */
diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c
index d8fdd865dea9..b1781908e1f2 100644
--- a/trunk/drivers/ide/ide-disk.c
+++ b/trunk/drivers/ide/ide-disk.c
@@ -129,50 +129,6 @@ static int lba_capacity_is_ok (struct hd_driveid *id)
return 0; /* lba_capacity value may be bad */
}
-static const u8 ide_rw_cmds[] = {
- WIN_MULTREAD,
- WIN_MULTWRITE,
- WIN_MULTREAD_EXT,
- WIN_MULTWRITE_EXT,
- WIN_READ,
- WIN_WRITE,
- WIN_READ_EXT,
- WIN_WRITE_EXT,
- WIN_READDMA,
- WIN_WRITEDMA,
- WIN_READDMA_EXT,
- WIN_WRITEDMA_EXT,
-};
-
-static const u8 ide_data_phases[] = {
- TASKFILE_MULTI_IN,
- TASKFILE_MULTI_OUT,
- TASKFILE_IN,
- TASKFILE_OUT,
- TASKFILE_IN_DMA,
- TASKFILE_OUT_DMA,
-};
-
-static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
-{
- u8 index, lba48, write;
-
- lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
- write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
-
- if (dma)
- index = drive->vdma ? 4 : 8;
- else
- index = drive->mult_count ? 0 : 4;
-
- task->tf.command = ide_rw_cmds[index + lba48 + write];
-
- if (dma)
- index = 8; /* fixup index */
-
- task->data_phase = ide_data_phases[index / 2 + write];
-}
-
/*
* __ide_do_rw_disk() issues READ and WRITE commands to a disk,
* using LBA if supported, or CHS otherwise, to address sectors.
@@ -181,11 +137,11 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
{
ide_hwif_t *hwif = HWIF(drive);
unsigned int dma = drive->using_dma;
- u16 nsectors = (u16)rq->nr_sectors;
u8 lba48 = (drive->addressing == 1) ? 1 : 0;
- ide_task_t task;
- struct ide_taskfile *tf = &task.tf;
- ide_startstop_t rc;
+ task_ioreg_t command = WIN_NOP;
+ ata_nsector_t nsectors;
+
+ nsectors.all = (u16) rq->nr_sectors;
if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
if (block + rq->nr_sectors > 1ULL << 28)
@@ -199,76 +155,121 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
ide_map_sg(drive, rq);
}
- memset(&task, 0, sizeof(task));
- task.tf_flags = IDE_TFLAG_NO_SELECT_MASK; /* FIXME? */
- task.tf_flags |= (IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE);
+ if (IDE_CONTROL_REG)
+ hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+
+ /* FIXME: SELECT_MASK(drive, 0) ? */
if (drive->select.b.lba) {
if (lba48) {
+ task_ioreg_t tasklets[10];
+
pr_debug("%s: LBA=0x%012llx\n", drive->name,
(unsigned long long)block);
- tf->hob_nsect = (nsectors >> 8) & 0xff;
- tf->hob_lbal = (u8)(block >> 24);
- if (sizeof(block) != 4) {
- tf->hob_lbam = (u8)((u64)block >> 32);
- tf->hob_lbah = (u8)((u64)block >> 40);
+ tasklets[0] = 0;
+ tasklets[1] = 0;
+ tasklets[2] = nsectors.b.low;
+ tasklets[3] = nsectors.b.high;
+ tasklets[4] = (task_ioreg_t) block;
+ tasklets[5] = (task_ioreg_t) (block>>8);
+ tasklets[6] = (task_ioreg_t) (block>>16);
+ tasklets[7] = (task_ioreg_t) (block>>24);
+ if (sizeof(block) == 4) {
+ tasklets[8] = (task_ioreg_t) 0;
+ tasklets[9] = (task_ioreg_t) 0;
+ } else {
+ tasklets[8] = (task_ioreg_t)((u64)block >> 32);
+ tasklets[9] = (task_ioreg_t)((u64)block >> 40);
}
-
- tf->nsect = nsectors & 0xff;
- tf->lbal = (u8) block;
- tf->lbam = (u8)(block >> 8);
- tf->lbah = (u8)(block >> 16);
#ifdef DEBUG
printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n",
- drive->name, tf->hob_nsect, tf->nsect,
- tf->hob_lbah, tf->hob_lbam, tf->hob_lbal,
- tf->lbah, tf->lbam, tf->lbal);
+ drive->name, tasklets[3], tasklets[2],
+ tasklets[9], tasklets[8], tasklets[7],
+ tasklets[6], tasklets[5], tasklets[4]);
#endif
- task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_OUT_HOB);
+ hwif->OUTB(tasklets[1], IDE_FEATURE_REG);
+ hwif->OUTB(tasklets[3], IDE_NSECTOR_REG);
+ hwif->OUTB(tasklets[7], IDE_SECTOR_REG);
+ hwif->OUTB(tasklets[8], IDE_LCYL_REG);
+ hwif->OUTB(tasklets[9], IDE_HCYL_REG);
+
+ hwif->OUTB(tasklets[0], IDE_FEATURE_REG);
+ hwif->OUTB(tasklets[2], IDE_NSECTOR_REG);
+ hwif->OUTB(tasklets[4], IDE_SECTOR_REG);
+ hwif->OUTB(tasklets[5], IDE_LCYL_REG);
+ hwif->OUTB(tasklets[6], IDE_HCYL_REG);
+ hwif->OUTB(0x00|drive->select.all,IDE_SELECT_REG);
} else {
- tf->nsect = nsectors & 0xff;
- tf->lbal = block;
- tf->lbam = block >>= 8;
- tf->lbah = block >>= 8;
- tf->device = (block >> 8) & 0xf;
+ hwif->OUTB(0x00, IDE_FEATURE_REG);
+ hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG);
+ hwif->OUTB(block, IDE_SECTOR_REG);
+ hwif->OUTB(block>>=8, IDE_LCYL_REG);
+ hwif->OUTB(block>>=8, IDE_HCYL_REG);
+ hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
}
} else {
unsigned int sect,head,cyl,track;
track = (int)block / drive->sect;
sect = (int)block % drive->sect + 1;
+ hwif->OUTB(sect, IDE_SECTOR_REG);
head = track % drive->head;
cyl = track / drive->head;
pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);
- tf->nsect = nsectors & 0xff;
- tf->lbal = sect;
- tf->lbam = cyl;
- tf->lbah = cyl >> 8;
- tf->device = head;
+ hwif->OUTB(0x00, IDE_FEATURE_REG);
+ hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG);
+ hwif->OUTB(cyl, IDE_LCYL_REG);
+ hwif->OUTB(cyl>>8, IDE_HCYL_REG);
+ hwif->OUTB(head|drive->select.all,IDE_SELECT_REG);
}
- if (rq_data_dir(rq))
- task.tf_flags |= IDE_TFLAG_WRITE;
-
- ide_tf_set_cmd(drive, &task, dma);
- if (!dma)
- hwif->data_phase = task.data_phase;
- task.rq = rq;
-
- rc = do_rw_taskfile(drive, &task);
-
- if (rc == ide_stopped && dma) {
+ if (dma) {
+ if (!hwif->dma_setup(drive)) {
+ if (rq_data_dir(rq)) {
+ command = lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
+ if (drive->vdma)
+ command = lba48 ? WIN_WRITE_EXT: WIN_WRITE;
+ } else {
+ command = lba48 ? WIN_READDMA_EXT : WIN_READDMA;
+ if (drive->vdma)
+ command = lba48 ? WIN_READ_EXT: WIN_READ;
+ }
+ hwif->dma_exec_cmd(drive, command);
+ hwif->dma_start(drive);
+ return ide_started;
+ }
/* fallback to PIO */
- task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
- ide_tf_set_cmd(drive, &task, 0);
- hwif->data_phase = task.data_phase;
ide_init_sg_cmd(drive, rq);
- rc = do_rw_taskfile(drive, &task);
}
- return rc;
+ if (rq_data_dir(rq) == READ) {
+
+ if (drive->mult_count) {
+ hwif->data_phase = TASKFILE_MULTI_IN;
+ command = lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD;
+ } else {
+ hwif->data_phase = TASKFILE_IN;
+ command = lba48 ? WIN_READ_EXT : WIN_READ;
+ }
+
+ ide_execute_command(drive, command, &task_in_intr, WAIT_CMD, NULL);
+ return ide_started;
+ } else {
+ if (drive->mult_count) {
+ hwif->data_phase = TASKFILE_MULTI_OUT;
+ command = lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
+ } else {
+ hwif->data_phase = TASKFILE_OUT;
+ command = lba48 ? WIN_WRITE_EXT : WIN_WRITE;
+ }
+
+ /* FIXME: ->OUTBSYNC ? */
+ hwif->OUTB(command, IDE_COMMAND_REG);
+
+ return pre_task_out_intr(drive, rq);
+ }
}
/*
@@ -306,29 +307,57 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s
* Queries for true maximum capacity of the drive.
* Returns maximum LBA address (> 0) of the drive, 0 if failed.
*/
-static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
+static unsigned long idedisk_read_native_max_address(ide_drive_t *drive)
{
ide_task_t args;
- struct ide_taskfile *tf = &args.tf;
- u64 addr = 0;
+ unsigned long addr = 0;
/* Create IDE/ATA command request structure */
memset(&args, 0, sizeof(ide_task_t));
- if (lba48)
- tf->command = WIN_READ_NATIVE_MAX_EXT;
- else
- tf->command = WIN_READ_NATIVE_MAX;
- tf->device = ATA_LBA;
- args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
- if (lba48)
- args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_OUT_HOB);
+ args.tfRegister[IDE_SELECT_OFFSET] = 0x40;
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX;
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.handler = &task_no_data_intr;
/* submit command request */
- ide_no_data_taskfile(drive, &args);
+ ide_raw_taskfile(drive, &args, NULL);
/* if OK, compute maximum address value */
- if ((tf->status & 0x01) == 0)
- addr = ide_get_lba_addr(tf, lba48) + 1;
+ if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
+ addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
+ | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16)
+ | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8)
+ | ((args.tfRegister[IDE_SECTOR_OFFSET] ));
+ addr++; /* since the return value is (maxlba - 1), we add 1 */
+ }
+ return addr;
+}
+
+static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive)
+{
+ ide_task_t args;
+ unsigned long long addr = 0;
+
+ /* Create IDE/ATA command request structure */
+ memset(&args, 0, sizeof(ide_task_t));
+ args.tfRegister[IDE_SELECT_OFFSET] = 0x40;
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT;
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.handler = &task_no_data_intr;
+ /* submit command request */
+ ide_raw_taskfile(drive, &args, NULL);
+
+ /* if OK, compute maximum address value */
+ if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
+ u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) |
+ (args.hobRegister[IDE_LCYL_OFFSET] << 8) |
+ args.hobRegister[IDE_SECTOR_OFFSET];
+ u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
+ ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
+ (args.tfRegister[IDE_SECTOR_OFFSET]);
+ addr = ((__u64)high << 24) | low;
+ addr++; /* since the return value is (maxlba - 1), we add 1 */
+ }
return addr;
}
@@ -336,37 +365,67 @@ static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
* Sets maximum virtual LBA address of the drive.
* Returns new maximum virtual LBA address (> 0) or 0 on failure.
*/
-static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
+static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req)
{
ide_task_t args;
- struct ide_taskfile *tf = &args.tf;
- u64 addr_set = 0;
-
+ unsigned long addr_set = 0;
+
addr_req--;
/* Create IDE/ATA command request structure */
memset(&args, 0, sizeof(ide_task_t));
- tf->lbal = (addr_req >> 0) & 0xff;
- tf->lbam = (addr_req >>= 8) & 0xff;
- tf->lbah = (addr_req >>= 8) & 0xff;
- if (lba48) {
- tf->hob_lbal = (addr_req >>= 8) & 0xff;
- tf->hob_lbam = (addr_req >>= 8) & 0xff;
- tf->hob_lbah = (addr_req >>= 8) & 0xff;
- tf->command = WIN_SET_MAX_EXT;
- } else {
- tf->device = (addr_req >>= 8) & 0x0f;
- tf->command = WIN_SET_MAX;
+ args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff);
+ args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >> 8) & 0xff);
+ args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >> 16) & 0xff);
+ args.tfRegister[IDE_SELECT_OFFSET] = ((addr_req >> 24) & 0x0f) | 0x40;
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX;
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.handler = &task_no_data_intr;
+ /* submit command request */
+ ide_raw_taskfile(drive, &args, NULL);
+ /* if OK, read new maximum address value */
+ if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
+ addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
+ | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16)
+ | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8)
+ | ((args.tfRegister[IDE_SECTOR_OFFSET] ));
+ addr_set++;
}
- tf->device |= ATA_LBA;
- args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
- if (lba48)
- args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_OUT_HOB);
+ return addr_set;
+}
+
+static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req)
+{
+ ide_task_t args;
+ unsigned long long addr_set = 0;
+
+ addr_req--;
+ /* Create IDE/ATA command request structure */
+ memset(&args, 0, sizeof(ide_task_t));
+ args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff);
+ args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >>= 8) & 0xff);
+ args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >>= 8) & 0xff);
+ args.tfRegister[IDE_SELECT_OFFSET] = 0x40;
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX_EXT;
+ args.hobRegister[IDE_SECTOR_OFFSET] = (addr_req >>= 8) & 0xff;
+ args.hobRegister[IDE_LCYL_OFFSET] = (addr_req >>= 8) & 0xff;
+ args.hobRegister[IDE_HCYL_OFFSET] = (addr_req >>= 8) & 0xff;
+ args.hobRegister[IDE_SELECT_OFFSET] = 0x40;
+ args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.handler = &task_no_data_intr;
/* submit command request */
- ide_no_data_taskfile(drive, &args);
+ ide_raw_taskfile(drive, &args, NULL);
/* if OK, compute maximum address value */
- if ((tf->status & 0x01) == 0)
- addr_set = ide_get_lba_addr(tf, lba48) + 1;
-
+ if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
+ u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) |
+ (args.hobRegister[IDE_LCYL_OFFSET] << 8) |
+ args.hobRegister[IDE_SECTOR_OFFSET];
+ u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
+ ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
+ (args.tfRegister[IDE_SECTOR_OFFSET]);
+ addr_set = ((__u64)high << 24) | low;
+ addr_set++;
+ }
return addr_set;
}
@@ -412,8 +471,10 @@ static void idedisk_check_hpa(ide_drive_t *drive)
int lba48 = idedisk_supports_lba48(drive->id);
capacity = drive->capacity64;
-
- set_max = idedisk_read_native_max_address(drive, lba48);
+ if (lba48)
+ set_max = idedisk_read_native_max_address_ext(drive);
+ else
+ set_max = idedisk_read_native_max_address(drive);
if (ide_in_drive_list(drive->id, hpa_list)) {
/*
@@ -434,8 +495,10 @@ static void idedisk_check_hpa(ide_drive_t *drive)
capacity, sectors_to_MB(capacity),
set_max, sectors_to_MB(set_max));
- set_max = idedisk_set_max_address(drive, set_max, lba48);
-
+ if (lba48)
+ set_max = idedisk_set_max_address_ext(drive, set_max);
+ else
+ set_max = idedisk_set_max_address(drive, set_max);
if (set_max) {
drive->capacity64 = set_max;
printk(KERN_INFO "%s: Host Protected Area disabled.\n",
@@ -493,32 +556,32 @@ static sector_t idedisk_capacity (ide_drive_t *drive)
static int smart_enable(ide_drive_t *drive)
{
ide_task_t args;
- struct ide_taskfile *tf = &args.tf;
memset(&args, 0, sizeof(ide_task_t));
- tf->feature = SMART_ENABLE;
- tf->lbam = SMART_LCYL_PASS;
- tf->lbah = SMART_HCYL_PASS;
- tf->command = WIN_SMART;
- args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
- return ide_no_data_taskfile(drive, &args);
+ args.tfRegister[IDE_FEATURE_OFFSET] = SMART_ENABLE;
+ args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS;
+ args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS;
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART;
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.handler = &task_no_data_intr;
+ return ide_raw_taskfile(drive, &args, NULL);
}
static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
{
ide_task_t args;
- struct ide_taskfile *tf = &args.tf;
memset(&args, 0, sizeof(ide_task_t));
- tf->feature = sub_cmd;
- tf->nsect = 0x01;
- tf->lbam = SMART_LCYL_PASS;
- tf->lbah = SMART_HCYL_PASS;
- tf->command = WIN_SMART;
- args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
- args.data_phase = TASKFILE_IN;
+ args.tfRegister[IDE_FEATURE_OFFSET] = sub_cmd;
+ args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01;
+ args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS;
+ args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS;
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART;
+ args.command_type = IDE_DRIVE_TASK_IN;
+ args.data_phase = TASKFILE_IN;
+ args.handler = &task_in_intr;
(void) smart_enable(drive);
- return ide_raw_taskfile(drive, &args, buf, 1);
+ return ide_raw_taskfile(drive, &args, buf);
}
static int proc_idedisk_read_cache
@@ -596,20 +659,19 @@ static ide_proc_entry_t idedisk_proc[] = {
static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
{
ide_drive_t *drive = q->queuedata;
- ide_task_t task;
- memset(&task, 0, sizeof(task));
+ memset(rq->cmd, 0, sizeof(rq->cmd));
+
if (ide_id_has_flush_cache_ext(drive->id) &&
(drive->capacity64 >= (1UL << 28)))
- task.tf.command = WIN_FLUSH_CACHE_EXT;
+ rq->cmd[0] = WIN_FLUSH_CACHE_EXT;
else
- task.tf.command = WIN_FLUSH_CACHE;
- task.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
- task.data_phase = TASKFILE_NO_DATA;
+ rq->cmd[0] = WIN_FLUSH_CACHE;
+
- rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
+ rq->cmd_type = REQ_TYPE_ATA_TASK;
rq->cmd_flags |= REQ_SOFTBARRIER;
- rq->special = &task;
+ rq->buffer = rq->cmd;
}
/*
@@ -691,11 +753,12 @@ static int write_cache(ide_drive_t *drive, int arg)
if (ide_id_has_flush_cache(drive->id)) {
memset(&args, 0, sizeof(ide_task_t));
- args.tf.feature = arg ?
+ args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ?
SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
- args.tf.command = WIN_SETFEATURES;
- args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
- err = ide_no_data_taskfile(drive, &args);
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES;
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.handler = &task_no_data_intr;
+ err = ide_raw_taskfile(drive, &args, NULL);
if (err == 0)
drive->wcache = arg;
}
@@ -711,11 +774,12 @@ static int do_idedisk_flushcache (ide_drive_t *drive)
memset(&args, 0, sizeof(ide_task_t));
if (ide_id_has_flush_cache_ext(drive->id))
- args.tf.command = WIN_FLUSH_CACHE_EXT;
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
else
- args.tf.command = WIN_FLUSH_CACHE;
- args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
- return ide_no_data_taskfile(drive, &args);
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.handler = &task_no_data_intr;
+ return ide_raw_taskfile(drive, &args, NULL);
}
static int set_acoustic (ide_drive_t *drive, int arg)
@@ -726,11 +790,13 @@ static int set_acoustic (ide_drive_t *drive, int arg)
return -EINVAL;
memset(&args, 0, sizeof(ide_task_t));
- args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM;
- args.tf.nsect = arg;
- args.tf.command = WIN_SETFEATURES;
- args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
- ide_no_data_taskfile(drive, &args);
+ args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM :
+ SETFEATURES_DIS_AAM;
+ args.tfRegister[IDE_NSECTOR_OFFSET] = arg;
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES;
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.handler = &task_no_data_intr;
+ ide_raw_taskfile(drive, &args, NULL);
drive->acoustic = arg;
return 0;
}
@@ -991,15 +1057,16 @@ static int idedisk_open(struct inode *inode, struct file *filp)
if (drive->removable && idkp->openers == 1) {
ide_task_t args;
memset(&args, 0, sizeof(ide_task_t));
- args.tf.command = WIN_DOORLOCK;
- args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK;
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.handler = &task_no_data_intr;
check_disk_change(inode->i_bdev);
/*
* Ignore the return code from door_lock,
* since the open() has already succeeded,
* and the door_lock is irrelevant at this point.
*/
- if (drive->doorlocking && ide_no_data_taskfile(drive, &args))
+ if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
drive->doorlocking = 0;
}
return 0;
@@ -1017,9 +1084,10 @@ static int idedisk_release(struct inode *inode, struct file *filp)
if (drive->removable && idkp->openers == 1) {
ide_task_t args;
memset(&args, 0, sizeof(ide_task_t));
- args.tf.command = WIN_DOORUNLOCK;
- args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
- if (drive->doorlocking && ide_no_data_taskfile(drive, &args))
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK;
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.handler = &task_no_data_intr;
+ if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
drive->doorlocking = 0;
}
diff --git a/trunk/drivers/ide/ide-dma.c b/trunk/drivers/ide/ide-dma.c
index 18c78ad2b31e..4703837bf1fc 100644
--- a/trunk/drivers/ide/ide-dma.c
+++ b/trunk/drivers/ide/ide-dma.c
@@ -491,6 +491,10 @@ EXPORT_SYMBOL(ide_dma_host_on);
int __ide_dma_on (ide_drive_t *drive)
{
+ /* consult the list of known "bad" drives */
+ if (__ide_dma_bad_drive(drive))
+ return 1;
+
drive->using_dma = 1;
ide_toggle_bounce(drive, 1);
@@ -823,19 +827,22 @@ int ide_set_dma(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
int rc;
- /*
- * Force DMAing for the beginning of the check.
- * Some chipsets appear to do interesting
- * things, if not checked and cleared.
- * PARANOIA!!!
- */
- hwif->dma_off_quietly(drive);
-
rc = ide_dma_check(drive);
- if (rc)
- return rc;
- return hwif->ide_dma_on(drive);
+ switch(rc) {
+ case -1: /* DMA needs to be disabled */
+ hwif->dma_off_quietly(drive);
+ return -1;
+ case 0: /* DMA needs to be enabled */
+ return hwif->ide_dma_on(drive);
+ case 1: /* DMA setting cannot be changed */
+ break;
+ default:
+ BUG();
+ break;
+ }
+
+ return rc;
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
@@ -961,6 +968,11 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
hwif->dma_base = base;
+ if (hwif->mate)
+ hwif->dma_master = hwif->channel ? hwif->mate->dma_base : base;
+ else
+ hwif->dma_master = base;
+
if (!(hwif->dma_command))
hwif->dma_command = hwif->dma_base;
if (!(hwif->dma_vendor1))
@@ -1002,6 +1014,8 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
}
printk("\n");
+
+ BUG_ON(!hwif->dma_master);
}
EXPORT_SYMBOL_GPL(ide_setup_dma);
diff --git a/trunk/drivers/ide/ide-floppy.c b/trunk/drivers/ide/ide-floppy.c
index ff8232ef9659..04a357808f2e 100644
--- a/trunk/drivers/ide/ide-floppy.c
+++ b/trunk/drivers/ide/ide-floppy.c
@@ -369,6 +369,27 @@ typedef struct ide_floppy_obj {
#define IDEFLOPPY_IOCTL_FORMAT_START 0x4602
#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603
+#if 0
+/*
+ * Special requests for our block device strategy routine.
+ */
+#define IDEFLOPPY_FIRST_RQ 90
+
+/*
+ * IDEFLOPPY_PC_RQ is used to queue a packet command in the request queue.
+ */
+#define IDEFLOPPY_PC_RQ 90
+
+#define IDEFLOPPY_LAST_RQ 90
+
+/*
+ * A macro which can be used to check if a given request command
+ * originated in the driver or in the buffer cache layer.
+ */
+#define IDEFLOPPY_RQ_CMD(cmd) ((cmd >= IDEFLOPPY_FIRST_RQ) && (cmd <= IDEFLOPPY_LAST_RQ))
+
+#endif
+
/*
* Error codes which are returned in rq->errors to the higher part
* of the driver.
@@ -772,8 +793,9 @@ static void idefloppy_retry_pc (ide_drive_t *drive)
{
idefloppy_pc_t *pc;
struct request *rq;
+ atapi_error_t error;
- (void)drive->hwif->INB(IDE_ERROR_REG);
+ error.all = HWIF(drive)->INB(IDE_ERROR_REG);
pc = idefloppy_next_pc_storage(drive);
rq = idefloppy_next_rq_storage(drive);
idefloppy_create_request_sense_cmd(pc);
@@ -787,12 +809,12 @@ static void idefloppy_retry_pc (ide_drive_t *drive)
static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
- ide_hwif_t *hwif = drive->hwif;
+ atapi_status_t status;
+ atapi_bcount_t bcount;
+ atapi_ireason_t ireason;
idefloppy_pc_t *pc = floppy->pc;
struct request *rq = pc->rq;
unsigned int temp;
- u16 bcount;
- u8 stat, ireason;
debug_log(KERN_INFO "ide-floppy: Reached %s interrupt handler\n",
__FUNCTION__);
@@ -808,16 +830,16 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
}
/* Clear the interrupt */
- stat = drive->hwif->INB(IDE_STATUS_REG);
+ status.all = HWIF(drive)->INB(IDE_STATUS_REG);
- if ((stat & DRQ_STAT) == 0) { /* No more interrupts */
+ if (!status.b.drq) { /* No more interrupts */
debug_log(KERN_INFO "Packet command completed, %d bytes "
"transferred\n", pc->actually_transferred);
clear_bit(PC_DMA_IN_PROGRESS, &pc->flags);
local_irq_enable_in_hardirq();
- if ((stat & ERR_STAT) || test_bit(PC_DMA_ERROR, &pc->flags)) {
+ if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) {
/* Error detected */
debug_log(KERN_INFO "ide-floppy: %s: I/O error\n",
drive->name);
@@ -848,32 +870,32 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
}
/* Get the number of bytes to transfer */
- bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
- hwif->INB(IDE_BCOUNTL_REG);
+ bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG);
+ bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG);
/* on this interrupt */
- ireason = hwif->INB(IDE_IREASON_REG);
+ ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
- if (ireason & CD) {
+ if (ireason.b.cod) {
printk(KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n");
return ide_do_reset(drive);
}
- if (((ireason & IO) == IO) == test_bit(PC_WRITING, &pc->flags)) {
+ if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) {
/* Hopefully, we will never get here */
printk(KERN_ERR "ide-floppy: We wanted to %s, ",
- (ireason & IO) ? "Write" : "Read");
+ ireason.b.io ? "Write":"Read");
printk(KERN_ERR "but the floppy wants us to %s !\n",
- (ireason & IO) ? "Read" : "Write");
+ ireason.b.io ? "Read":"Write");
return ide_do_reset(drive);
}
if (!test_bit(PC_WRITING, &pc->flags)) {
/* Reading - Check that we have enough space */
- temp = pc->actually_transferred + bcount;
+ temp = pc->actually_transferred + bcount.all;
if (temp > pc->request_transfer) {
if (temp > pc->buffer_size) {
printk(KERN_ERR "ide-floppy: The floppy wants "
"to send us more data than expected "
"- discarding data\n");
- idefloppy_discard_data(drive, bcount);
+ idefloppy_discard_data(drive,bcount.all);
BUG_ON(HWGROUP(drive)->handler != NULL);
ide_set_handler(drive,
&idefloppy_pc_intr,
@@ -889,21 +911,23 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
if (test_bit(PC_WRITING, &pc->flags)) {
if (pc->buffer != NULL)
/* Write the current buffer */
- hwif->atapi_output_bytes(drive, pc->current_position,
- bcount);
+ HWIF(drive)->atapi_output_bytes(drive,
+ pc->current_position,
+ bcount.all);
else
- idefloppy_output_buffers(drive, pc, bcount);
+ idefloppy_output_buffers(drive, pc, bcount.all);
} else {
if (pc->buffer != NULL)
/* Read the current buffer */
- hwif->atapi_input_bytes(drive, pc->current_position,
- bcount);
+ HWIF(drive)->atapi_input_bytes(drive,
+ pc->current_position,
+ bcount.all);
else
- idefloppy_input_buffers(drive, pc, bcount);
+ idefloppy_input_buffers(drive, pc, bcount.all);
}
/* Update the current position */
- pc->actually_transferred += bcount;
- pc->current_position += bcount;
+ pc->actually_transferred += bcount.all;
+ pc->current_position += bcount.all;
BUG_ON(HWGROUP(drive)->handler != NULL);
ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */
@@ -919,15 +943,15 @@ static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive)
{
ide_startstop_t startstop;
idefloppy_floppy_t *floppy = drive->driver_data;
- u8 ireason;
+ atapi_ireason_t ireason;
if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
printk(KERN_ERR "ide-floppy: Strange, packet command "
"initiated yet DRQ isn't asserted\n");
return startstop;
}
- ireason = drive->hwif->INB(IDE_IREASON_REG);
- if ((ireason & CD) == 0 || (ireason & IO)) {
+ ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
+ if (!ireason.b.cod || ireason.b.io) {
printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while "
"issuing a packet command\n");
return ide_do_reset(drive);
@@ -967,15 +991,15 @@ static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
ide_startstop_t startstop;
- u8 ireason;
+ atapi_ireason_t ireason;
if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
printk(KERN_ERR "ide-floppy: Strange, packet command "
"initiated yet DRQ isn't asserted\n");
return startstop;
}
- ireason = drive->hwif->INB(IDE_IREASON_REG);
- if ((ireason & CD) == 0 || (ireason & IO)) {
+ ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
+ if (!ireason.b.cod || ireason.b.io) {
printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) "
"while issuing a packet command\n");
return ide_do_reset(drive);
@@ -1017,9 +1041,21 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
{
idefloppy_floppy_t *floppy = drive->driver_data;
ide_hwif_t *hwif = drive->hwif;
+ atapi_feature_t feature;
+ atapi_bcount_t bcount;
ide_handler_t *pkt_xfer_routine;
- u16 bcount;
- u8 dma;
+
+#if 0 /* Accessing floppy->pc is not valid here, the previous pc may be gone
+ and have lived on another thread's stack; that stack may have become
+ unmapped meanwhile (CONFIG_DEBUG_PAGEALLOC). */
+#if IDEFLOPPY_DEBUG_BUGS
+ if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD &&
+ pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
+ printk(KERN_ERR "ide-floppy: possible ide-floppy.c bug - "
+ "Two request sense in serial were issued\n");
+ }
+#endif /* IDEFLOPPY_DEBUG_BUGS */
+#endif
if (floppy->failed_pc == NULL &&
pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD)
@@ -1057,20 +1093,25 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
/* We haven't transferred any data yet */
pc->actually_transferred = 0;
pc->current_position = pc->buffer;
- bcount = min(pc->request_transfer, 63 * 1024);
+ bcount.all = min(pc->request_transfer, 63 * 1024);
if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags))
ide_dma_off(drive);
- dma = 0;
+ feature.all = 0;
if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
- dma = !hwif->dma_setup(drive);
+ feature.b.dma = !hwif->dma_setup(drive);
- ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
- IDE_TFLAG_OUT_DEVICE, bcount, dma);
+ if (IDE_CONTROL_REG)
+ HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
+ /* Use PIO/DMA */
+ HWIF(drive)->OUTB(feature.all, IDE_FEATURE_REG);
+ HWIF(drive)->OUTB(bcount.b.high, IDE_BCOUNTH_REG);
+ HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG);
+ HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG);
- if (dma) { /* Begin DMA, if necessary */
+ if (feature.b.dma) { /* Begin DMA, if necessary */
set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
hwif->dma_start(drive);
}
@@ -1624,14 +1665,14 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
/* Else assume format_unit has finished, and we're
** at 0x10000 */
} else {
+ atapi_status_t status;
unsigned long flags;
- u8 stat;
local_irq_save(flags);
- stat = drive->hwif->INB(IDE_STATUS_REG);
+ status.all = HWIF(drive)->INB(IDE_STATUS_REG);
local_irq_restore(flags);
- progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000;
+ progress_indication = !status.b.dsc ? 0 : 0x10000;
}
if (put_user(progress_indication, arg))
return (-EFAULT);
diff --git a/trunk/drivers/ide/ide-io.c b/trunk/drivers/ide/ide-io.c
index 2711b5a6962d..bef781fec500 100644
--- a/trunk/drivers/ide/ide-io.c
+++ b/trunk/drivers/ide/ide-io.c
@@ -189,14 +189,18 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
return ide_stopped;
}
if (ide_id_has_flush_cache_ext(drive->id))
- args->tf.command = WIN_FLUSH_CACHE_EXT;
+ args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
else
- args->tf.command = WIN_FLUSH_CACHE;
- goto out_do_tf;
+ args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
+ args->command_type = IDE_DRIVE_TASK_NO_DATA;
+ args->handler = &task_no_data_intr;
+ return do_rw_taskfile(drive, args);
case idedisk_pm_standby: /* Suspend step 2 (standby) */
- args->tf.command = WIN_STANDBYNOW1;
- goto out_do_tf;
+ args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1;
+ args->command_type = IDE_DRIVE_TASK_NO_DATA;
+ args->handler = &task_no_data_intr;
+ return do_rw_taskfile(drive, args);
case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */
ide_set_max_pio(drive);
@@ -210,8 +214,10 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
return ide_stopped;
case idedisk_pm_idle: /* Resume step 2 (idle) */
- args->tf.command = WIN_IDLEIMMEDIATE;
- goto out_do_tf;
+ args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE;
+ args->command_type = IDE_DRIVE_TASK_NO_DATA;
+ args->handler = task_no_data_intr;
+ return do_rw_taskfile(drive, args);
case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */
/*
@@ -221,6 +227,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
*/
if (drive->hwif->ide_dma_on == NULL)
break;
+ drive->hwif->dma_off_quietly(drive);
/*
* TODO: respect ->using_dma setting
*/
@@ -229,11 +236,6 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
}
pm->pm_step = ide_pm_state_completed;
return ide_stopped;
-
-out_do_tf:
- args->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
- args->data_phase = TASKFILE_NO_DATA;
- return do_rw_taskfile(drive, args);
}
/**
@@ -296,48 +298,6 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
spin_unlock_irqrestore(&ide_lock, flags);
}
-void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct ide_taskfile *tf = &task->tf;
-
- if (task->tf_flags & IDE_TFLAG_IN_DATA) {
- u16 data = hwif->INW(IDE_DATA_REG);
-
- tf->data = data & 0xff;
- tf->hob_data = (data >> 8) & 0xff;
- }
-
- /* be sure we're looking at the low order bits */
- hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
-
- if (task->tf_flags & IDE_TFLAG_IN_NSECT)
- tf->nsect = hwif->INB(IDE_NSECTOR_REG);
- if (task->tf_flags & IDE_TFLAG_IN_LBAL)
- tf->lbal = hwif->INB(IDE_SECTOR_REG);
- if (task->tf_flags & IDE_TFLAG_IN_LBAM)
- tf->lbam = hwif->INB(IDE_LCYL_REG);
- if (task->tf_flags & IDE_TFLAG_IN_LBAH)
- tf->lbah = hwif->INB(IDE_HCYL_REG);
- if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
- tf->device = hwif->INB(IDE_SELECT_REG);
-
- if (task->tf_flags & IDE_TFLAG_LBA48) {
- hwif->OUTB(drive->ctl | 0x80, IDE_CONTROL_REG);
-
- if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
- tf->hob_feature = hwif->INB(IDE_FEATURE_REG);
- if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
- tf->hob_nsect = hwif->INB(IDE_NSECTOR_REG);
- if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
- tf->hob_lbal = hwif->INB(IDE_SECTOR_REG);
- if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
- tf->hob_lbam = hwif->INB(IDE_LCYL_REG);
- if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
- tf->hob_lbah = hwif->INB(IDE_HCYL_REG);
- }
-}
-
/**
* ide_end_drive_cmd - end an explicit drive command
* @drive: command
@@ -372,22 +332,51 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
args[1] = err;
args[2] = hwif->INB(IDE_NSECTOR_REG);
}
+ } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
+ u8 *args = (u8 *) rq->buffer;
+ if (rq->errors == 0)
+ rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
+
+ if (args) {
+ args[0] = stat;
+ args[1] = err;
+ /* be sure we're looking at the low order bits */
+ hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
+ args[2] = hwif->INB(IDE_NSECTOR_REG);
+ args[3] = hwif->INB(IDE_SECTOR_REG);
+ args[4] = hwif->INB(IDE_LCYL_REG);
+ args[5] = hwif->INB(IDE_HCYL_REG);
+ args[6] = hwif->INB(IDE_SELECT_REG);
+ }
} else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
ide_task_t *args = (ide_task_t *) rq->special;
if (rq->errors == 0)
rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
if (args) {
- struct ide_taskfile *tf = &args->tf;
-
- tf->error = err;
- tf->status = stat;
-
- args->tf_flags |= (IDE_TFLAG_IN_TF|IDE_TFLAG_IN_DEVICE);
- if (args->tf_flags & IDE_TFLAG_LBA48)
- args->tf_flags |= IDE_TFLAG_IN_HOB;
-
- ide_tf_read(drive, args);
+ if (args->tf_in_flags.b.data) {
+ u16 data = hwif->INW(IDE_DATA_REG);
+ args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF;
+ args->hobRegister[IDE_DATA_OFFSET] = (data >> 8) & 0xFF;
+ }
+ args->tfRegister[IDE_ERROR_OFFSET] = err;
+ /* be sure we're looking at the low order bits */
+ hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
+ args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
+ args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG);
+ args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG);
+ args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG);
+ args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG);
+ args->tfRegister[IDE_STATUS_OFFSET] = stat;
+
+ if (drive->addressing == 1) {
+ hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
+ args->hobRegister[IDE_FEATURE_OFFSET] = hwif->INB(IDE_FEATURE_REG);
+ args->hobRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
+ args->hobRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG);
+ args->hobRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG);
+ args->hobRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG);
+ }
}
} else if (blk_pm_request(rq)) {
struct request_pm_state *pm = rq->data;
@@ -626,6 +615,28 @@ ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
return __ide_abort(drive, rq);
}
+/**
+ * ide_cmd - issue a simple drive command
+ * @drive: drive the command is for
+ * @cmd: command byte
+ * @nsect: sector byte
+ * @handler: handler for the command completion
+ *
+ * Issue a simple drive command with interrupts.
+ * The drive must be selected beforehand.
+ */
+
+static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect,
+ ide_handler_t *handler)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ if (IDE_CONTROL_REG)
+ hwif->OUTB(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */
+ SELECT_MASK(drive,0);
+ hwif->OUTB(nsect,IDE_NSECTOR_REG);
+ ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL);
+}
+
/**
* drive_cmd_intr - drive command completion interrupt
* @drive: drive the completion interrupt occurred on
@@ -662,26 +673,32 @@ static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
return ide_stopped;
}
-static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
+static void ide_init_specify_cmd(ide_drive_t *drive, ide_task_t *task)
{
- tf->nsect = drive->sect;
- tf->lbal = drive->sect;
- tf->lbam = drive->cyl;
- tf->lbah = drive->cyl >> 8;
- tf->device = ((drive->head - 1) | drive->select.all) & ~ATA_LBA;
- tf->command = WIN_SPECIFY;
+ task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
+ task->tfRegister[IDE_SECTOR_OFFSET] = drive->sect;
+ task->tfRegister[IDE_LCYL_OFFSET] = drive->cyl;
+ task->tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8;
+ task->tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF;
+ task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY;
+
+ task->handler = &set_geometry_intr;
}
-static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
+static void ide_init_restore_cmd(ide_drive_t *drive, ide_task_t *task)
{
- tf->nsect = drive->sect;
- tf->command = WIN_RESTORE;
+ task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
+ task->tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE;
+
+ task->handler = &recal_intr;
}
-static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
+static void ide_init_setmult_cmd(ide_drive_t *drive, ide_task_t *task)
{
- tf->nsect = drive->mult_req;
- tf->command = WIN_SETMULT;
+ task->tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req;
+ task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT;
+
+ task->handler = &set_multmode_intr;
}
static ide_startstop_t ide_disk_special(ide_drive_t *drive)
@@ -690,19 +707,19 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
ide_task_t args;
memset(&args, 0, sizeof(ide_task_t));
- args.data_phase = TASKFILE_NO_DATA;
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
if (s->b.set_geometry) {
s->b.set_geometry = 0;
- ide_tf_set_specify_cmd(drive, &args.tf);
+ ide_init_specify_cmd(drive, &args);
} else if (s->b.recalibrate) {
s->b.recalibrate = 0;
- ide_tf_set_restore_cmd(drive, &args.tf);
+ ide_init_restore_cmd(drive, &args);
} else if (s->b.set_multmode) {
s->b.set_multmode = 0;
if (drive->mult_req > drive->id->max_multsect)
drive->mult_req = drive->id->max_multsect;
- ide_tf_set_setmult_cmd(drive, &args.tf);
+ ide_init_setmult_cmd(drive, &args);
} else if (s->all) {
int special = s->all;
s->all = 0;
@@ -710,9 +727,6 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
return ide_stopped;
}
- args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
- IDE_TFLAG_CUSTOM_HANDLER;
-
do_rw_taskfile(drive, &args);
return ide_started;
@@ -847,17 +861,13 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
struct request *rq)
{
ide_hwif_t *hwif = HWIF(drive);
- u8 *args = rq->buffer;
- ide_task_t ltask;
- struct ide_taskfile *tf = <ask.tf;
-
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
- ide_task_t *task = rq->special;
+ ide_task_t *args = rq->special;
- if (task == NULL)
+ if (!args)
goto done;
- hwif->data_phase = task->data_phase;
+ hwif->data_phase = args->data_phase;
switch (hwif->data_phase) {
case TASKFILE_MULTI_OUT:
@@ -870,34 +880,55 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
break;
}
- return do_rw_taskfile(drive, task);
- }
-
- if (args == NULL)
- goto done;
-
- memset(<ask, 0, sizeof(ltask));
- if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
+ if (args->tf_out_flags.all != 0)
+ return flagged_taskfile(drive, args);
+ return do_rw_taskfile(drive, args);
+ } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
+ u8 *args = rq->buffer;
+
+ if (!args)
+ goto done;
#ifdef DEBUG
- printk("%s: DRIVE_CMD\n", drive->name);
+ printk("%s: DRIVE_TASK_CMD ", drive->name);
+ printk("cmd=0x%02x ", args[0]);
+ printk("fr=0x%02x ", args[1]);
+ printk("ns=0x%02x ", args[2]);
+ printk("sc=0x%02x ", args[3]);
+ printk("lcyl=0x%02x ", args[4]);
+ printk("hcyl=0x%02x ", args[5]);
+ printk("sel=0x%02x\n", args[6]);
#endif
- tf->feature = args[2];
- if (args[0] == WIN_SMART) {
- tf->nsect = args[3];
- tf->lbal = args[1];
- tf->lbam = 0x4f;
- tf->lbah = 0xc2;
- ltask.tf_flags = IDE_TFLAG_OUT_TF;
- } else {
- tf->nsect = args[1];
- ltask.tf_flags = IDE_TFLAG_OUT_FEATURE |
- IDE_TFLAG_OUT_NSECT;
- }
+ hwif->OUTB(args[1], IDE_FEATURE_REG);
+ hwif->OUTB(args[3], IDE_SECTOR_REG);
+ hwif->OUTB(args[4], IDE_LCYL_REG);
+ hwif->OUTB(args[5], IDE_HCYL_REG);
+ hwif->OUTB((args[6] & 0xEF)|drive->select.all, IDE_SELECT_REG);
+ ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
+ return ide_started;
+ } else if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
+ u8 *args = rq->buffer;
+
+ if (!args)
+ goto done;
+#ifdef DEBUG
+ printk("%s: DRIVE_CMD ", drive->name);
+ printk("cmd=0x%02x ", args[0]);
+ printk("sc=0x%02x ", args[1]);
+ printk("fr=0x%02x ", args[2]);
+ printk("xx=0x%02x\n", args[3]);
+#endif
+ if (args[0] == WIN_SMART) {
+ hwif->OUTB(0x4f, IDE_LCYL_REG);
+ hwif->OUTB(0xc2, IDE_HCYL_REG);
+ hwif->OUTB(args[2],IDE_FEATURE_REG);
+ hwif->OUTB(args[1],IDE_SECTOR_REG);
+ ide_cmd(drive, args[0], args[3], &drive_cmd_intr);
+ return ide_started;
+ }
+ hwif->OUTB(args[2],IDE_FEATURE_REG);
+ ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
+ return ide_started;
}
- tf->command = args[0];
- ide_tf_load(drive, <ask);
- ide_execute_command(drive, args[0], &drive_cmd_intr, WAIT_WORSTCASE, NULL);
- return ide_started;
done:
/*
@@ -972,7 +1003,6 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
/* bail early if we've exceeded max_failures */
if (drive->max_failures && (drive->failures > drive->max_failures)) {
- rq->cmd_flags |= REQ_FAILED;
goto kill_rq;
}
@@ -1005,6 +1035,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
ide_config_drive_speed(drive, drive->desired_speed);
if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
+ rq->cmd_type == REQ_TYPE_ATA_TASK ||
rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
return execute_drive_cmd(drive, rq);
else if (blk_pm_request(rq)) {
@@ -1216,12 +1247,8 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
if (hwgroup->hwif->sharing_irq &&
hwif != hwgroup->hwif &&
hwif->io_ports[IDE_CONTROL_OFFSET]) {
- /*
- * set nIEN for previous hwif, drives in the
- * quirk_list may not like intr setups/cleanups
- */
- if (drive->quirk_list != 1)
- hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG);
+ /* set nIEN for previous hwif */
+ SELECT_INTERRUPT(drive);
}
hwgroup->hwif = hwif;
hwgroup->drive = drive;
@@ -1427,8 +1454,12 @@ void ide_timer_expiry (unsigned long data)
*/
spin_unlock(&ide_lock);
hwif = HWIF(drive);
+#if DISABLE_IRQ_NOSYNC
+ disable_irq_nosync(hwif->irq);
+#else
/* disable_irq_nosync ?? */
disable_irq(hwif->irq);
+#endif /* DISABLE_IRQ_NOSYNC */
/* local CPU only,
* as if we were handling an interrupt */
local_irq_disable();
@@ -1754,19 +1785,3 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
}
EXPORT_SYMBOL(ide_do_drive_cmd);
-
-void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
-{
- ide_task_t task;
-
- memset(&task, 0, sizeof(task));
- task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
- IDE_TFLAG_OUT_FEATURE | tf_flags;
- task.tf.feature = dma; /* Use PIO/DMA */
- task.tf.lbam = bcount & 0xff;
- task.tf.lbah = (bcount >> 8) & 0xff;
-
- ide_tf_load(drive, &task);
-}
-
-EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
diff --git a/trunk/drivers/ide/ide-iops.c b/trunk/drivers/ide/ide-iops.c
index c97c0719ddf1..bb9693dabe41 100644
--- a/trunk/drivers/ide/ide-iops.c
+++ b/trunk/drivers/ide/ide-iops.c
@@ -158,6 +158,14 @@ void default_hwif_mmiops (ide_hwif_t *hwif)
EXPORT_SYMBOL(default_hwif_mmiops);
+u32 ide_read_24 (ide_drive_t *drive)
+{
+ u8 hcyl = HWIF(drive)->INB(IDE_HCYL_REG);
+ u8 lcyl = HWIF(drive)->INB(IDE_LCYL_REG);
+ u8 sect = HWIF(drive)->INB(IDE_SECTOR_REG);
+ return (hcyl<<16)|(lcyl<<8)|sect;
+}
+
void SELECT_DRIVE (ide_drive_t *drive)
{
if (HWIF(drive)->selectproc)
@@ -167,12 +175,26 @@ void SELECT_DRIVE (ide_drive_t *drive)
EXPORT_SYMBOL(SELECT_DRIVE);
+void SELECT_INTERRUPT (ide_drive_t *drive)
+{
+ if (HWIF(drive)->intrproc)
+ HWIF(drive)->intrproc(drive);
+ else
+ HWIF(drive)->OUTB(drive->ctl|2, IDE_CONTROL_REG);
+}
+
void SELECT_MASK (ide_drive_t *drive, int mask)
{
if (HWIF(drive)->maskproc)
HWIF(drive)->maskproc(drive, mask);
}
+void QUIRK_LIST (ide_drive_t *drive)
+{
+ if (HWIF(drive)->quirkproc)
+ drive->quirk_list = HWIF(drive)->quirkproc(drive);
+}
+
/*
* Some localbus EIDE interfaces require a special access sequence
* when using 32-bit I/O instructions to transfer data. We call this
@@ -427,6 +449,7 @@ int drive_is_ready (ide_drive_t *drive)
udelay(1);
#endif
+#ifdef CONFIG_IDEPCI_SHARE_IRQ
/*
* We do a passive status test under shared PCI interrupts on
* cards that truly share the ATA side interrupt, but may also share
@@ -436,6 +459,7 @@ int drive_is_ready (ide_drive_t *drive)
if (IDE_CONTROL_REG)
stat = hwif->INB(IDE_ALTSTATUS_REG);
else
+#endif /* CONFIG_IDEPCI_SHARE_IRQ */
/* Note: this may clear a pending IRQ!! */
stat = hwif->INB(IDE_STATUS_REG);
@@ -618,9 +642,9 @@ u8 eighty_ninty_three (ide_drive_t *drive)
int ide_ata66_check (ide_drive_t *drive, ide_task_t *args)
{
- if (args->tf.command == WIN_SETFEATURES &&
- args->tf.lbal > XFER_UDMA_2 &&
- args->tf.feature == SETFEATURES_XFER) {
+ if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
+ (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) &&
+ (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) {
if (eighty_ninty_three(drive) == 0) {
printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
"be set\n", drive->name);
@@ -638,9 +662,9 @@ int ide_ata66_check (ide_drive_t *drive, ide_task_t *args)
*/
int set_transfer (ide_drive_t *drive, ide_task_t *args)
{
- if (args->tf.command == WIN_SETFEATURES &&
- args->tf.lbal >= XFER_SW_DMA_0 &&
- args->tf.feature == SETFEATURES_XFER &&
+ if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
+ (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) &&
+ (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) &&
(drive->id->dma_ultra ||
drive->id->dma_mword ||
drive->id->dma_1word))
@@ -878,9 +902,8 @@ EXPORT_SYMBOL(ide_set_handler);
* handler and IRQ setup do not race. All IDE command kick off
* should go via this function or do equivalent locking.
*/
-
-void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
- unsigned timeout, ide_expiry_t *expiry)
+
+void ide_execute_command(ide_drive_t *drive, task_ioreg_t cmd, ide_handler_t *handler, unsigned timeout, ide_expiry_t *expiry)
{
unsigned long flags;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
@@ -1028,7 +1051,8 @@ static void ide_disk_pre_reset(ide_drive_t *drive)
drive->special.all = 0;
drive->special.b.set_geometry = legacy;
drive->special.b.recalibrate = legacy;
- drive->mult_count = 0;
+ if (OK_TO_RESET_CONTROLLER)
+ drive->mult_count = 0;
if (!drive->keep_settings && !drive->using_dma)
drive->mult_req = 0;
if (drive->mult_req != drive->mult_count)
@@ -1113,6 +1137,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
for (unit = 0; unit < MAX_DRIVES; ++unit)
pre_reset(&hwif->drives[unit]);
+#if OK_TO_RESET_CONTROLLER
if (!IDE_CONTROL_REG) {
spin_unlock_irqrestore(&ide_lock, flags);
return ide_stopped;
@@ -1149,8 +1174,11 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
* state when the disks are reset this way. At least, the Winbond
* 553 documentation says that
*/
- if (hwif->resetproc)
+ if (hwif->resetproc != NULL) {
hwif->resetproc(drive);
+ }
+
+#endif /* OK_TO_RESET_CONTROLLER */
spin_unlock_irqrestore(&ide_lock, flags);
return ide_started;
diff --git a/trunk/drivers/ide/ide-lib.c b/trunk/drivers/ide/ide-lib.c
index a3bd8e8ed6b0..062d3bcb2471 100644
--- a/trunk/drivers/ide/ide-lib.c
+++ b/trunk/drivers/ide/ide-lib.c
@@ -441,12 +441,6 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
* case could happen iff the transfer mode has already been set on
* the device by ide-proc.c::set_xfer_rate()).
*/
- if (rate < XFER_PIO_0) {
- if (hwif->host_flags & IDE_HFLAG_ABUSE_SET_DMA_MODE)
- return ide_set_dma_mode(drive, rate);
- else
- return ide_config_drive_speed(drive, rate);
- }
return ide_set_dma_mode(drive, rate);
}
@@ -464,7 +458,8 @@ static void ide_dump_opcode(ide_drive_t *drive)
spin_unlock(&ide_lock);
if (!rq)
return;
- if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
+ if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
+ rq->cmd_type == REQ_TYPE_ATA_TASK) {
char *args = rq->buffer;
if (args) {
opcode = args[0];
@@ -473,7 +468,8 @@ static void ide_dump_opcode(ide_drive_t *drive)
} else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
ide_task_t *args = rq->special;
if (args) {
- opcode = args->tf.command;
+ task_struct_t *tf = (task_struct_t *) args->tfRegister;
+ opcode = tf->command;
found = 1;
}
}
@@ -485,118 +481,141 @@ static void ide_dump_opcode(ide_drive_t *drive)
printk("0x%02x\n", opcode);
}
-u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48)
+static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat)
{
- u32 high, low;
-
- if (lba48)
- high = (tf->hob_lbah << 16) | (tf->hob_lbam << 8) |
- tf->hob_lbal;
- else
- high = tf->device & 0xf;
- low = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal;
-
- return ((u64)high << 24) | low;
-}
-EXPORT_SYMBOL_GPL(ide_get_lba_addr);
-
-static void ide_dump_sector(ide_drive_t *drive)
-{
- ide_task_t task;
- struct ide_taskfile *tf = &task.tf;
- int lba48 = (drive->addressing == 1) ? 1 : 0;
-
- memset(&task, 0, sizeof(task));
- if (lba48)
- task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA |
- IDE_TFLAG_LBA48;
- else
- task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
-
- ide_tf_read(drive, &task);
-
- if (lba48 || (tf->device & ATA_LBA))
- printk(", LBAsect=%llu",
- (unsigned long long)ide_get_lba_addr(tf, lba48));
- else
- printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam,
- tf->device & 0xf, tf->lbal);
-}
+ ide_hwif_t *hwif = HWIF(drive);
+ unsigned long flags;
+ u8 err = 0;
-static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
-{
- printk("{ ");
- if (err & ABRT_ERR) printk("DriveStatusError ");
- if (err & ICRC_ERR)
- printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
- if (err & ECC_ERR) printk("UncorrectableError ");
- if (err & ID_ERR) printk("SectorIdNotFound ");
- if (err & TRK0_ERR) printk("TrackZeroNotFound ");
- if (err & MARK_ERR) printk("AddrMarkNotFound ");
- printk("}");
- if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
- (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
- ide_dump_sector(drive);
- if (HWGROUP(drive) && HWGROUP(drive)->rq)
- printk(", sector=%llu",
- (unsigned long long)HWGROUP(drive)->rq->sector);
+ local_irq_save(flags);
+ printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
+ if (stat & BUSY_STAT)
+ printk("Busy ");
+ else {
+ if (stat & READY_STAT) printk("DriveReady ");
+ if (stat & WRERR_STAT) printk("DeviceFault ");
+ if (stat & SEEK_STAT) printk("SeekComplete ");
+ if (stat & DRQ_STAT) printk("DataRequest ");
+ if (stat & ECC_STAT) printk("CorrectedError ");
+ if (stat & INDEX_STAT) printk("Index ");
+ if (stat & ERR_STAT) printk("Error ");
}
- printk("\n");
-}
-
-static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
-{
- printk("{ ");
- if (err & ILI_ERR) printk("IllegalLengthIndication ");
- if (err & EOM_ERR) printk("EndOfMedia ");
- if (err & ABRT_ERR) printk("AbortedCommand ");
- if (err & MCR_ERR) printk("MediaChangeRequested ");
- if (err & LFS_ERR) printk("LastFailedSense=0x%02x ",
- (err & LFS_ERR) >> 4);
printk("}\n");
+ if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
+ err = hwif->INB(IDE_ERROR_REG);
+ printk("%s: %s: error=0x%02x { ", drive->name, msg, err);
+ if (err & ABRT_ERR) printk("DriveStatusError ");
+ if (err & ICRC_ERR)
+ printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
+ if (err & ECC_ERR) printk("UncorrectableError ");
+ if (err & ID_ERR) printk("SectorIdNotFound ");
+ if (err & TRK0_ERR) printk("TrackZeroNotFound ");
+ if (err & MARK_ERR) printk("AddrMarkNotFound ");
+ printk("}");
+ if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
+ (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
+ if (drive->addressing == 1) {
+ __u64 sectors = 0;
+ u32 low = 0, high = 0;
+ hwif->OUTB(drive->ctl&~0x80, IDE_CONTROL_REG);
+ low = ide_read_24(drive);
+ hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
+ high = ide_read_24(drive);
+ sectors = ((__u64)high << 24) | low;
+ printk(", LBAsect=%llu, high=%d, low=%d",
+ (unsigned long long) sectors,
+ high, low);
+ } else {
+ u8 cur = hwif->INB(IDE_SELECT_REG);
+ if (cur & 0x40) { /* using LBA? */
+ printk(", LBAsect=%ld", (unsigned long)
+ ((cur&0xf)<<24)
+ |(hwif->INB(IDE_HCYL_REG)<<16)
+ |(hwif->INB(IDE_LCYL_REG)<<8)
+ | hwif->INB(IDE_SECTOR_REG));
+ } else {
+ printk(", CHS=%d/%d/%d",
+ (hwif->INB(IDE_HCYL_REG)<<8) +
+ hwif->INB(IDE_LCYL_REG),
+ cur & 0xf,
+ hwif->INB(IDE_SECTOR_REG));
+ }
+ }
+ if (HWGROUP(drive) && HWGROUP(drive)->rq)
+ printk(", sector=%llu",
+ (unsigned long long)HWGROUP(drive)->rq->sector);
+ }
+ printk("\n");
+ }
+ ide_dump_opcode(drive);
+ local_irq_restore(flags);
+ return err;
}
/**
- * ide_dump_status - translate ATA/ATAPI error
+ * ide_dump_atapi_status - print human readable atapi status
* @drive: drive that status applies to
* @msg: text message to print
* @stat: status byte to decode
*
* Error reporting, in human readable form (luxurious, but a memory hog).
- * Combines the drive name, message and status byte to provide a
- * user understandable explanation of the device error.
*/
-u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
+static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat)
{
unsigned long flags;
- u8 err = 0;
+ atapi_status_t status;
+ atapi_error_t error;
+
+ status.all = stat;
+ error.all = 0;
local_irq_save(flags);
printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
- if (stat & BUSY_STAT)
+ if (status.b.bsy)
printk("Busy ");
else {
- if (stat & READY_STAT) printk("DriveReady ");
- if (stat & WRERR_STAT) printk("DeviceFault ");
- if (stat & SEEK_STAT) printk("SeekComplete ");
- if (stat & DRQ_STAT) printk("DataRequest ");
- if (stat & ECC_STAT) printk("CorrectedError ");
- if (stat & INDEX_STAT) printk("Index ");
- if (stat & ERR_STAT) printk("Error ");
+ if (status.b.drdy) printk("DriveReady ");
+ if (status.b.df) printk("DeviceFault ");
+ if (status.b.dsc) printk("SeekComplete ");
+ if (status.b.drq) printk("DataRequest ");
+ if (status.b.corr) printk("CorrectedError ");
+ if (status.b.idx) printk("Index ");
+ if (status.b.check) printk("Error ");
}
printk("}\n");
- if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
- err = drive->hwif->INB(IDE_ERROR_REG);
- printk("%s: %s: error=0x%02x ", drive->name, msg, err);
- if (drive->media == ide_disk)
- ide_dump_ata_error(drive, err);
- else
- ide_dump_atapi_error(drive, err);
+ if (status.b.check && !status.b.bsy) {
+ error.all = HWIF(drive)->INB(IDE_ERROR_REG);
+ printk("%s: %s: error=0x%02x { ", drive->name, msg, error.all);
+ if (error.b.ili) printk("IllegalLengthIndication ");
+ if (error.b.eom) printk("EndOfMedia ");
+ if (error.b.abrt) printk("AbortedCommand ");
+ if (error.b.mcr) printk("MediaChangeRequested ");
+ if (error.b.sense_key) printk("LastFailedSense=0x%02x ",
+ error.b.sense_key);
+ printk("}\n");
}
ide_dump_opcode(drive);
local_irq_restore(flags);
- return err;
+ return error.all;
+}
+
+/**
+ * ide_dump_status - translate ATA/ATAPI error
+ * @drive: drive the error occured on
+ * @msg: information string
+ * @stat: status byte
+ *
+ * Error reporting, in human readable form (luxurious, but a memory hog).
+ * Combines the drive name, message and status byte to provide a
+ * user understandable explanation of the device error.
+ */
+
+u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
+{
+ if (drive->media == ide_disk)
+ return ide_dump_ata_status(drive, msg, stat);
+ return ide_dump_atapi_status(drive, msg, stat);
}
EXPORT_SYMBOL(ide_dump_status);
diff --git a/trunk/drivers/ide/ide-probe.c b/trunk/drivers/ide/ide-probe.c
index 0379d1f697cf..0cb3d2bb3ab9 100644
--- a/trunk/drivers/ide/ide-probe.c
+++ b/trunk/drivers/ide/ide-probe.c
@@ -95,10 +95,10 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
#ifdef CONFIG_IDEDISK_MULTI_MODE
id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
id->multsect_valid = id->multsect ? 1 : 0;
- drive->mult_req = id->multsect_valid ? id->max_multsect : 0;
+ drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
#else /* original, pre IDE-NFG, per request of AC */
- drive->mult_req = 0;
+ drive->mult_req = INITIAL_MULT_COUNT;
if (drive->mult_req > id->max_multsect)
drive->mult_req = id->max_multsect;
if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
@@ -234,10 +234,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
drive->media = ide_disk;
printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" );
-
- if (hwif->quirkproc)
- drive->quirk_list = hwif->quirkproc(drive);
-
+ QUIRK_LIST(drive);
return;
err_misc:
@@ -833,8 +830,16 @@ static void probe_hwif(ide_hwif_t *hwif)
drive->nice1 = 1;
- if (hwif->ide_dma_on)
+ if (hwif->ide_dma_on) {
+ /*
+ * Force DMAing for the beginning of the check.
+ * Some chipsets appear to do interesting
+ * things, if not checked and cleared.
+ * PARANOIA!!!
+ */
+ hwif->dma_off_quietly(drive);
ide_set_dma(drive);
+ }
}
}
@@ -963,6 +968,11 @@ static int ide_init_queue(ide_drive_t *drive)
* Much of the code is for correctly detecting/handling irq sharing
* and irq serialization situations. This is somewhat complex because
* it handles static as well as dynamic (PCMCIA) IDE interfaces.
+ *
+ * The IRQF_DISABLED in sa_flags means ide_intr() is always entered with
+ * interrupts completely disabled. This can be bad for interrupt latency,
+ * but anything else has led to problems on some machines. We re-enable
+ * interrupts as much as we can safely do in most places.
*/
static int init_irq (ide_hwif_t *hwif)
{
@@ -1045,13 +1055,17 @@ static int init_irq (ide_hwif_t *hwif)
* Allocate the irq, if not already obtained for another hwif
*/
if (!match || match->irq != hwif->irq) {
- int sa = 0;
+ int sa = IRQF_DISABLED;
#if defined(__mc68000__) || defined(CONFIG_APUS)
sa = IRQF_SHARED;
#endif /* __mc68000__ || CONFIG_APUS */
- if (IDE_CHIPSET_IS_PCI(hwif->chipset))
+ if (IDE_CHIPSET_IS_PCI(hwif->chipset)) {
sa = IRQF_SHARED;
+#ifndef CONFIG_IDEPCI_SHARE_IRQ
+ sa |= IRQF_DISABLED;
+#endif /* CONFIG_IDEPCI_SHARE_IRQ */
+ }
if (hwif->io_ports[IDE_CONTROL_OFFSET])
/* clear nIEN */
diff --git a/trunk/drivers/ide/ide-tape.c b/trunk/drivers/ide/ide-tape.c
index 3cbca3f4628a..1495792d7917 100644
--- a/trunk/drivers/ide/ide-tape.c
+++ b/trunk/drivers/ide/ide-tape.c
@@ -614,6 +614,16 @@ typedef struct os_dat_s {
/*************************** End of tunable parameters ***********************/
+/*
+ * Debugging/Performance analysis
+ *
+ * I/O trace support
+ */
+#define USE_IOTRACE 0
+#if USE_IOTRACE
+#define IO_IDETAPE_FIFO 500
+#endif
+
/*
* Read/Write error simulation
*/
@@ -1808,8 +1818,9 @@ static ide_startstop_t idetape_retry_pc (ide_drive_t *drive)
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc;
struct request *rq;
+ atapi_error_t error;
- (void)drive->hwif->INB(IDE_ERROR_REG);
+ error.all = HWIF(drive)->INB(IDE_ERROR_REG);
pc = idetape_next_pc_storage(drive);
rq = idetape_next_rq_storage(drive);
idetape_create_request_sense_cmd(pc);
@@ -1847,13 +1858,15 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
+ atapi_status_t status;
+ atapi_bcount_t bcount;
+ atapi_ireason_t ireason;
idetape_pc_t *pc = tape->pc;
+
unsigned int temp;
#if SIMULATE_ERRORS
static int error_sim_count = 0;
#endif
- u16 bcount;
- u8 stat, ireason;
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 4)
@@ -1862,10 +1875,10 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
#endif /* IDETAPE_DEBUG_LOG */
/* Clear the interrupt */
- stat = hwif->INB(IDE_STATUS_REG);
+ status.all = HWIF(drive)->INB(IDE_STATUS_REG);
if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
- if (hwif->ide_dma_end(drive) || (stat & ERR_STAT)) {
+ if (HWIF(drive)->ide_dma_end(drive) || status.b.check) {
/*
* A DMA error is sometimes expected. For example,
* if the tape is crossing a filemark during a
@@ -1899,7 +1912,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
}
/* No more interrupts */
- if ((stat & DRQ_STAT) == 0) {
+ if (!status.b.drq) {
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 2)
printk(KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred);
@@ -1914,13 +1927,12 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
(++error_sim_count % 100) == 0) {
printk(KERN_INFO "ide-tape: %s: simulating error\n",
tape->name);
- stat |= ERR_STAT;
+ status.b.check = 1;
}
#endif
- if ((stat & ERR_STAT) && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD)
- stat &= ~ERR_STAT;
- if ((stat & ERR_STAT) || test_bit(PC_DMA_ERROR, &pc->flags)) {
- /* Error detected */
+ if (status.b.check && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD)
+ status.b.check = 0;
+ if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) { /* Error detected */
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 1)
printk(KERN_INFO "ide-tape: %s: I/O error\n",
@@ -1939,7 +1951,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
}
pc->error = 0;
if (test_bit(PC_WAIT_FOR_DSC, &pc->flags) &&
- (stat & SEEK_STAT) == 0) {
+ !status.b.dsc) {
/* Media access command */
tape->dsc_polling_start = jiffies;
tape->dsc_polling_frequency = IDETAPE_DSC_MA_FAST;
@@ -1961,30 +1973,30 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
return ide_do_reset(drive);
}
/* Get the number of bytes to transfer on this interrupt. */
- bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
- hwif->INB(IDE_BCOUNTL_REG);
+ bcount.b.high = hwif->INB(IDE_BCOUNTH_REG);
+ bcount.b.low = hwif->INB(IDE_BCOUNTL_REG);
- ireason = hwif->INB(IDE_IREASON_REG);
+ ireason.all = hwif->INB(IDE_IREASON_REG);
- if (ireason & CD) {
+ if (ireason.b.cod) {
printk(KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n");
return ide_do_reset(drive);
}
- if (((ireason & IO) == IO) == test_bit(PC_WRITING, &pc->flags)) {
+ if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) {
/* Hopefully, we will never get here */
printk(KERN_ERR "ide-tape: We wanted to %s, ",
- (ireason & IO) ? "Write" : "Read");
+ ireason.b.io ? "Write":"Read");
printk(KERN_ERR "ide-tape: but the tape wants us to %s !\n",
- (ireason & IO) ? "Read" : "Write");
+ ireason.b.io ? "Read":"Write");
return ide_do_reset(drive);
}
if (!test_bit(PC_WRITING, &pc->flags)) {
/* Reading - Check that we have enough space */
- temp = pc->actually_transferred + bcount;
+ temp = pc->actually_transferred + bcount.all;
if (temp > pc->request_transfer) {
if (temp > pc->buffer_size) {
printk(KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
- idetape_discard_data(drive, bcount);
+ idetape_discard_data(drive, bcount.all);
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
return ide_started;
}
@@ -1996,26 +2008,23 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
}
if (test_bit(PC_WRITING, &pc->flags)) {
if (pc->bh != NULL)
- idetape_output_buffers(drive, pc, bcount);
+ idetape_output_buffers(drive, pc, bcount.all);
else
/* Write the current buffer */
- hwif->atapi_output_bytes(drive, pc->current_position,
- bcount);
+ HWIF(drive)->atapi_output_bytes(drive, pc->current_position, bcount.all);
} else {
if (pc->bh != NULL)
- idetape_input_buffers(drive, pc, bcount);
+ idetape_input_buffers(drive, pc, bcount.all);
else
/* Read the current buffer */
- hwif->atapi_input_bytes(drive, pc->current_position,
- bcount);
+ HWIF(drive)->atapi_input_bytes(drive, pc->current_position, bcount.all);
}
/* Update the current position */
- pc->actually_transferred += bcount;
- pc->current_position += bcount;
+ pc->actually_transferred += bcount.all;
+ pc->current_position += bcount.all;
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 2)
- printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes "
- "on that interrupt\n", pc->c[0], bcount);
+ printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all);
#endif
/* And set the interrupt handler again */
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
@@ -2069,28 +2078,28 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc = tape->pc;
+ atapi_ireason_t ireason;
int retries = 100;
ide_startstop_t startstop;
- u8 ireason;
if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
printk(KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
return startstop;
}
- ireason = hwif->INB(IDE_IREASON_REG);
- while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
+ ireason.all = hwif->INB(IDE_IREASON_REG);
+ while (retries-- && (!ireason.b.cod || ireason.b.io)) {
printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing "
"a packet command, retrying\n");
udelay(100);
- ireason = hwif->INB(IDE_IREASON_REG);
+ ireason.all = hwif->INB(IDE_IREASON_REG);
if (retries == 0) {
printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while "
"issuing a packet command, ignoring\n");
- ireason |= CD;
- ireason &= ~IO;
+ ireason.b.cod = 1;
+ ireason.b.io = 0;
}
}
- if ((ireason & CD) == 0 || (ireason & IO)) {
+ if (!ireason.b.cod || ireason.b.io) {
printk(KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing "
"a packet command\n");
return ide_do_reset(drive);
@@ -2111,8 +2120,8 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
{
ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
+ atapi_bcount_t bcount;
int dma_ok = 0;
- u16 bcount;
#if IDETAPE_DEBUG_BUGS
if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD &&
@@ -2161,7 +2170,7 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
pc->actually_transferred = 0;
pc->current_position = pc->buffer;
/* Request to transfer the entire buffer at once */
- bcount = pc->request_transfer;
+ bcount.all = pc->request_transfer;
if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
printk(KERN_WARNING "ide-tape: DMA disabled, "
@@ -2171,9 +2180,12 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
dma_ok = !hwif->dma_setup(drive);
- ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
- IDE_TFLAG_OUT_DEVICE, bcount, dma_ok);
-
+ if (IDE_CONTROL_REG)
+ hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+ hwif->OUTB(dma_ok ? 1 : 0, IDE_FEATURE_REG); /* Use PIO/DMA */
+ hwif->OUTB(bcount.b.high, IDE_BCOUNTH_REG);
+ hwif->OUTB(bcount.b.low, IDE_BCOUNTL_REG);
+ hwif->OUTB(drive->select.all, IDE_SELECT_REG);
if (dma_ok) /* Will begin DMA later */
set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
@@ -2283,11 +2295,11 @@ static ide_startstop_t idetape_media_access_finished (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc = tape->pc;
- u8 stat;
+ atapi_status_t status;
- stat = drive->hwif->INB(IDE_STATUS_REG);
- if (stat & SEEK_STAT) {
- if (stat & ERR_STAT) {
+ status.all = HWIF(drive)->INB(IDE_STATUS_REG);
+ if (status.b.dsc) {
+ if (status.b.check) {
/* Error detected */
if (pc->c[0] != IDETAPE_TEST_UNIT_READY_CMD)
printk(KERN_ERR "ide-tape: %s: I/O error, ",
@@ -2405,7 +2417,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc = NULL;
struct request *postponed_rq = tape->postponed_rq;
- u8 stat;
+ atapi_status_t status;
#if IDETAPE_DEBUG_LOG
#if 0
@@ -2453,7 +2465,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
* If the tape is still busy, postpone our request and service
* the other device meanwhile.
*/
- stat = drive->hwif->INB(IDE_STATUS_REG);
+ status.all = HWIF(drive)->INB(IDE_STATUS_REG);
if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
@@ -2469,7 +2481,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
calculate_speeds(drive);
if (!test_and_clear_bit(IDETAPE_IGNORE_DSC, &tape->flags) &&
- (stat & SEEK_STAT) == 0) {
+ !status.b.dsc) {
if (postponed_rq == NULL) {
tape->dsc_polling_start = jiffies;
tape->dsc_polling_frequency = tape->best_dsc_rw_frequency;
@@ -2490,6 +2502,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
}
if (rq->cmd[0] & REQ_IDETAPE_READ) {
tape->buffer_head++;
+#if USE_IOTRACE
+ IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
+#endif
tape->postpone_cnt = 0;
pc = idetape_next_pc_storage(drive);
idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
@@ -2497,6 +2512,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
}
if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
tape->buffer_head++;
+#if USE_IOTRACE
+ IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
+#endif
tape->postpone_cnt = 0;
pc = idetape_next_pc_storage(drive);
idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
@@ -3223,6 +3241,9 @@ static int idetape_add_chrdev_write_request (ide_drive_t *drive, int blocks)
idetape_switch_buffers(tape, new_stage);
idetape_add_stage_tail(drive, new_stage);
tape->pipeline_head++;
+#if USE_IOTRACE
+ IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
+#endif
calculate_speeds(drive);
/*
@@ -3472,6 +3493,9 @@ static int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks)
idetape_remove_stage_head(drive);
spin_unlock_irqrestore(&tape->spinlock, flags);
tape->pipeline_head++;
+#if USE_IOTRACE
+ IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
+#endif
calculate_speeds(drive);
}
#if IDETAPE_DEBUG_BUGS
diff --git a/trunk/drivers/ide/ide-taskfile.c b/trunk/drivers/ide/ide-taskfile.c
index 2d63ea9ee61b..2b60f1b0437e 100644
--- a/trunk/drivers/ide/ide-taskfile.c
+++ b/trunk/drivers/ide/ide-taskfile.c
@@ -63,78 +63,65 @@ static void taskfile_output_data(ide_drive_t *drive, void *buffer, u32 wcount)
}
}
-void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct ide_taskfile *tf = &task->tf;
- u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
-
- if (task->tf_flags & IDE_TFLAG_FLAGGED)
- HIHI = 0xFF;
-
-#ifdef DEBUG
- printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x "
- "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n",
- drive->name, tf->feature, tf->nsect, tf->lbal,
- tf->lbam, tf->lbah, tf->device, tf->command);
-#endif
-
- if (IDE_CONTROL_REG)
- hwif->OUTB(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */
-
- if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0)
- SELECT_MASK(drive, 0);
-
- if (task->tf_flags & IDE_TFLAG_OUT_DATA)
- hwif->OUTW((tf->hob_data << 8) | tf->data, IDE_DATA_REG);
-
- if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
- hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG);
- if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
- hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG);
- if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
- hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG);
- if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
- hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG);
- if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
- hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG);
-
- if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
- hwif->OUTB(tf->feature, IDE_FEATURE_REG);
- if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
- hwif->OUTB(tf->nsect, IDE_NSECTOR_REG);
- if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
- hwif->OUTB(tf->lbal, IDE_SECTOR_REG);
- if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
- hwif->OUTB(tf->lbam, IDE_LCYL_REG);
- if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
- hwif->OUTB(tf->lbah, IDE_HCYL_REG);
-
- if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
- hwif->OUTB((tf->device & HIHI) | drive->select.all, IDE_SELECT_REG);
-}
-
int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
{
ide_task_t args;
-
memset(&args, 0, sizeof(ide_task_t));
- args.tf.nsect = 0x01;
+ args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01;
if (drive->media == ide_disk)
- args.tf.command = WIN_IDENTIFY;
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_IDENTIFY;
else
- args.tf.command = WIN_PIDENTIFY;
- args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
- args.data_phase = TASKFILE_IN;
- return ide_raw_taskfile(drive, &args, buf, 1);
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_PIDENTIFY;
+ args.command_type = IDE_DRIVE_TASK_IN;
+ args.data_phase = TASKFILE_IN;
+ args.handler = &task_in_intr;
+ return ide_raw_taskfile(drive, &args, buf);
}
-static int inline task_dma_ok(ide_task_t *task)
+ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
{
- if (blk_fs_request(task->rq) || (task->tf_flags & IDE_TFLAG_FLAGGED))
- return 1;
+ ide_hwif_t *hwif = HWIF(drive);
+ task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
+ hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
+ u8 HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF;
+
+ /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
+ if (IDE_CONTROL_REG) {
+ /* clear nIEN */
+ hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+ }
+ SELECT_MASK(drive, 0);
+
+ if (drive->addressing == 1) {
+ hwif->OUTB(hobfile->feature, IDE_FEATURE_REG);
+ hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
+ hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
+ hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
+ hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
+ }
+
+ hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
+ hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
+ hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
+ hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
+ hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
+
+ hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
+
+ if (task->handler != NULL) {
+ if (task->prehandler != NULL) {
+ hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
+ ndelay(400); /* FIXME */
+ return task->prehandler(drive, task->rq);
+ }
+ ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
+ return ide_started;
+ }
+
+ if (!drive->using_dma)
+ return ide_stopped;
- switch (task->tf.command) {
+ switch (taskfile->command) {
case WIN_WRITEDMA_ONCE:
case WIN_WRITEDMA:
case WIN_WRITEDMA_EXT:
@@ -142,79 +129,24 @@ static int inline task_dma_ok(ide_task_t *task)
case WIN_READDMA:
case WIN_READDMA_EXT:
case WIN_IDENTIFY_DMA:
- return 1;
- }
-
- return 0;
-}
-
-static ide_startstop_t task_no_data_intr(ide_drive_t *);
-static ide_startstop_t set_geometry_intr(ide_drive_t *);
-static ide_startstop_t recal_intr(ide_drive_t *);
-static ide_startstop_t set_multmode_intr(ide_drive_t *);
-static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
-static ide_startstop_t task_in_intr(ide_drive_t *);
-
-ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
-{
- ide_hwif_t *hwif = HWIF(drive);
- struct ide_taskfile *tf = &task->tf;
- ide_handler_t *handler = NULL;
-
- if (task->data_phase == TASKFILE_MULTI_IN ||
- task->data_phase == TASKFILE_MULTI_OUT) {
- if (!drive->mult_count) {
- printk(KERN_ERR "%s: multimode not set!\n",
- drive->name);
- return ide_stopped;
- }
- }
-
- if (task->tf_flags & IDE_TFLAG_FLAGGED)
- task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
-
- if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0)
- ide_tf_load(drive, task);
-
- switch (task->data_phase) {
- case TASKFILE_MULTI_OUT:
- case TASKFILE_OUT:
- hwif->OUTBSYNC(drive, tf->command, IDE_COMMAND_REG);
- ndelay(400); /* FIXME */
- return pre_task_out_intr(drive, task->rq);
- case TASKFILE_MULTI_IN:
- case TASKFILE_IN:
- handler = task_in_intr;
- /* fall-through */
- case TASKFILE_NO_DATA:
- if (handler == NULL)
- handler = task_no_data_intr;
- /* WIN_{SPECIFY,RESTORE,SETMULT} use custom handlers */
- if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) {
- switch (tf->command) {
- case WIN_SPECIFY: handler = set_geometry_intr; break;
- case WIN_RESTORE: handler = recal_intr; break;
- case WIN_SETMULT: handler = set_multmode_intr; break;
+ if (!hwif->dma_setup(drive)) {
+ hwif->dma_exec_cmd(drive, taskfile->command);
+ hwif->dma_start(drive);
+ return ide_started;
}
- }
- ide_execute_command(drive, tf->command, handler,
- WAIT_WORSTCASE, NULL);
- return ide_started;
- default:
- if (task_dma_ok(task) == 0 || drive->using_dma == 0 ||
- hwif->dma_setup(drive))
- return ide_stopped;
- hwif->dma_exec_cmd(drive, tf->command);
- hwif->dma_start(drive);
- return ide_started;
+ break;
+ default:
+ if (task->handler == NULL)
+ return ide_stopped;
}
+
+ return ide_stopped;
}
-EXPORT_SYMBOL_GPL(do_rw_taskfile);
/*
* set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
*/
-static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
+ide_startstop_t set_multmode_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
u8 stat;
@@ -232,7 +164,7 @@ static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
/*
* set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
*/
-static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
+ide_startstop_t set_geometry_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
int retries = 5;
@@ -255,7 +187,7 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
/*
* recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
*/
-static ide_startstop_t recal_intr(ide_drive_t *drive)
+ide_startstop_t recal_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
u8 stat;
@@ -268,7 +200,7 @@ static ide_startstop_t recal_intr(ide_drive_t *drive)
/*
* Handler for commands without a data phase
*/
-static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
+ide_startstop_t task_no_data_intr (ide_drive_t *drive)
{
ide_task_t *args = HWGROUP(drive)->rq->special;
ide_hwif_t *hwif = HWIF(drive);
@@ -285,6 +217,8 @@ static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
return ide_stopped;
}
+EXPORT_SYMBOL(task_no_data_intr);
+
static u8 wait_drive_not_busy(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -429,7 +363,7 @@ static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
ide_task_t *task = rq->special;
- if (task->tf_flags & IDE_TFLAG_FLAGGED) {
+ if (task->tf_out_flags.all) {
u8 err = drive->hwif->INB(IDE_ERROR_REG);
ide_end_drive_cmd(drive, stat, err);
return;
@@ -448,7 +382,7 @@ static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
/*
* Handler for command with PIO data-in phase (Read/Read Multiple).
*/
-static ide_startstop_t task_in_intr(ide_drive_t *drive)
+ide_startstop_t task_in_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct request *rq = HWGROUP(drive)->rq;
@@ -479,6 +413,7 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive)
return ide_started;
}
+EXPORT_SYMBOL(task_in_intr);
/*
* Handler for command with PIO data-out phase (Write/Write Multiple).
@@ -508,7 +443,7 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive)
return ide_started;
}
-static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
+ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
{
ide_startstop_t startstop;
@@ -529,8 +464,9 @@ static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
return ide_started;
}
+EXPORT_SYMBOL(pre_task_out_intr);
-int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect)
+static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf)
{
struct request rq;
@@ -545,27 +481,36 @@ int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect)
* if we would find a solution to transfer any size.
* To support special commands like READ LONG.
*/
- rq.hard_nr_sectors = rq.nr_sectors = nsect;
- rq.hard_cur_sectors = rq.current_nr_sectors = nsect;
+ if (args->command_type != IDE_DRIVE_TASK_NO_DATA) {
+ if (data_size == 0)
+ rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET];
+ else
+ rq.nr_sectors = data_size / SECTOR_SIZE;
+
+ if (!rq.nr_sectors) {
+ printk(KERN_ERR "%s: in/out command without data\n",
+ drive->name);
+ return -EFAULT;
+ }
- if (task->tf_flags & IDE_TFLAG_WRITE)
- rq.cmd_flags |= REQ_RW;
+ rq.hard_nr_sectors = rq.nr_sectors;
+ rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors;
- rq.special = task;
- task->rq = &rq;
+ if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
+ rq.cmd_flags |= REQ_RW;
+ }
+ rq.special = args;
+ args->rq = &rq;
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
-EXPORT_SYMBOL(ide_raw_taskfile);
-
-int ide_no_data_taskfile(ide_drive_t *drive, ide_task_t *task)
+int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf)
{
- task->data_phase = TASKFILE_NO_DATA;
-
- return ide_raw_taskfile(drive, task, NULL, 0);
+ return ide_diag_taskfile(drive, args, 0, buf);
}
-EXPORT_SYMBOL_GPL(ide_no_data_taskfile);
+
+EXPORT_SYMBOL(ide_raw_taskfile);
#ifdef CONFIG_IDE_TASK_IOCTL
int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
@@ -574,12 +519,12 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
ide_task_t args;
u8 *outbuf = NULL;
u8 *inbuf = NULL;
- u8 *data_buf = NULL;
+ task_ioreg_t *argsptr = args.tfRegister;
+ task_ioreg_t *hobsptr = args.hobRegister;
int err = 0;
int tasksize = sizeof(struct ide_task_request_s);
unsigned int taskin = 0;
unsigned int taskout = 0;
- u16 nsect = 0;
u8 io_32bit = drive->io_32bit;
char __user *buf = (char __user *)arg;
@@ -627,52 +572,24 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
}
memset(&args, 0, sizeof(ide_task_t));
+ memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
+ memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE);
- memcpy(&args.tf_array[0], req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2);
- memcpy(&args.tf_array[6], req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
-
- args.data_phase = req_task->data_phase;
-
- args.tf_flags = IDE_TFLAG_OUT_DEVICE;
- if (drive->addressing == 1)
- args.tf_flags |= IDE_TFLAG_LBA48;
-
- if (req_task->out_flags.all) {
- args.tf_flags |= IDE_TFLAG_FLAGGED;
-
- if (req_task->out_flags.b.data)
- args.tf_flags |= IDE_TFLAG_OUT_DATA;
-
- if (req_task->out_flags.b.nsector_hob)
- args.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT;
- if (req_task->out_flags.b.sector_hob)
- args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL;
- if (req_task->out_flags.b.lcyl_hob)
- args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM;
- if (req_task->out_flags.b.hcyl_hob)
- args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH;
-
- if (req_task->out_flags.b.error_feature)
- args.tf_flags |= IDE_TFLAG_OUT_FEATURE;
- if (req_task->out_flags.b.nsector)
- args.tf_flags |= IDE_TFLAG_OUT_NSECT;
- if (req_task->out_flags.b.sector)
- args.tf_flags |= IDE_TFLAG_OUT_LBAL;
- if (req_task->out_flags.b.lcyl)
- args.tf_flags |= IDE_TFLAG_OUT_LBAM;
- if (req_task->out_flags.b.hcyl)
- args.tf_flags |= IDE_TFLAG_OUT_LBAH;
- } else {
- args.tf_flags |= IDE_TFLAG_OUT_TF;
- if (args.tf_flags & IDE_TFLAG_LBA48)
- args.tf_flags |= IDE_TFLAG_OUT_HOB;
- }
-
- if (req_task->in_flags.b.data)
- args.tf_flags |= IDE_TFLAG_IN_DATA;
+ args.tf_in_flags = req_task->in_flags;
+ args.tf_out_flags = req_task->out_flags;
+ args.data_phase = req_task->data_phase;
+ args.command_type = req_task->req_cmd;
drive->io_32bit = 0;
switch(req_task->data_phase) {
+ case TASKFILE_OUT_DMAQ:
+ case TASKFILE_OUT_DMA:
+ err = ide_diag_taskfile(drive, &args, taskout, outbuf);
+ break;
+ case TASKFILE_IN_DMAQ:
+ case TASKFILE_IN_DMA:
+ err = ide_diag_taskfile(drive, &args, taskin, inbuf);
+ break;
case TASKFILE_MULTI_OUT:
if (!drive->mult_count) {
/* (hs): give up if multcount is not set */
@@ -684,11 +601,9 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
}
/* fall through */
case TASKFILE_OUT:
- /* fall through */
- case TASKFILE_OUT_DMAQ:
- case TASKFILE_OUT_DMA:
- nsect = taskout / SECTOR_SIZE;
- data_buf = outbuf;
+ args.prehandler = &pre_task_out_intr;
+ args.handler = &task_out_intr;
+ err = ide_diag_taskfile(drive, &args, taskout, outbuf);
break;
case TASKFILE_MULTI_IN:
if (!drive->mult_count) {
@@ -701,46 +616,22 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
}
/* fall through */
case TASKFILE_IN:
- /* fall through */
- case TASKFILE_IN_DMAQ:
- case TASKFILE_IN_DMA:
- nsect = taskin / SECTOR_SIZE;
- data_buf = inbuf;
+ args.handler = &task_in_intr;
+ err = ide_diag_taskfile(drive, &args, taskin, inbuf);
break;
case TASKFILE_NO_DATA:
+ args.handler = &task_no_data_intr;
+ err = ide_diag_taskfile(drive, &args, 0, NULL);
break;
default:
err = -EFAULT;
goto abort;
}
- if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA)
- nsect = 0;
- else if (!nsect) {
- nsect = (args.tf.hob_nsect << 8) | args.tf.nsect;
-
- if (!nsect) {
- printk(KERN_ERR "%s: in/out command without data\n",
- drive->name);
- err = -EFAULT;
- goto abort;
- }
- }
-
- if (req_task->req_cmd == IDE_DRIVE_TASK_RAW_WRITE)
- args.tf_flags |= IDE_TFLAG_WRITE;
-
- err = ide_raw_taskfile(drive, &args, data_buf, nsect);
-
- memcpy(req_task->hob_ports, &args.tf_array[0], HDIO_DRIVE_HOB_HDR_SIZE - 2);
- memcpy(req_task->io_ports, &args.tf_array[6], HDIO_DRIVE_TASK_HDR_SIZE);
-
- if ((args.tf_flags & IDE_TFLAG_FLAGGED_SET_IN_FLAGS) &&
- req_task->in_flags.all == 0) {
- req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
- if (drive->addressing == 1)
- req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
- }
+ memcpy(req_task->io_ports, &(args.tfRegister), HDIO_DRIVE_TASK_HDR_SIZE);
+ memcpy(req_task->hob_ports, &(args.hobRegister), HDIO_DRIVE_HOB_HDR_SIZE);
+ req_task->in_flags = args.tf_in_flags;
+ req_task->out_flags = args.tf_out_flags;
if (copy_to_user(buf, req_task, tasksize)) {
err = -EFAULT;
@@ -797,7 +688,6 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
u8 xfer_rate = 0;
int argsize = 4;
ide_task_t tfargs;
- struct ide_taskfile *tf = &tfargs.tf;
if (NULL == (void *) arg) {
struct request rq;
@@ -809,10 +699,13 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
return -EFAULT;
memset(&tfargs, 0, sizeof(ide_task_t));
- tf->feature = args[2];
- tf->nsect = args[3];
- tf->lbal = args[1];
- tf->command = args[0];
+ tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2];
+ tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3];
+ tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1];
+ tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00;
+ tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00;
+ tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00;
+ tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0];
if (args[3]) {
argsize = 4 + (SECTOR_WORDS * 4 * args[3]);
@@ -841,28 +734,135 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
return err;
}
+static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf)
+{
+ struct request rq;
+
+ ide_init_drive_cmd(&rq);
+ rq.cmd_type = REQ_TYPE_ATA_TASK;
+ rq.buffer = buf;
+ return ide_do_drive_cmd(drive, &rq, ide_wait);
+}
+
int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
{
void __user *p = (void __user *)arg;
int err = 0;
- u8 args[7];
- ide_task_t task;
+ u8 args[7], *argbuf = args;
+ int argsize = 7;
if (copy_from_user(args, p, 7))
return -EFAULT;
+ err = ide_wait_cmd_task(drive, argbuf);
+ if (copy_to_user(p, argbuf, argsize))
+ err = -EFAULT;
+ return err;
+}
- memset(&task, 0, sizeof(task));
- memcpy(&task.tf_array[7], &args[1], 6);
- task.tf.command = args[0];
- task.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
+/*
+ * NOTICE: This is additions from IBM to provide a discrete interface,
+ * for selective taskregister access operations. Nice JOB Klaus!!!
+ * Glad to be able to work and co-develop this with you and IBM.
+ */
+ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
+ hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
- err = ide_no_data_taskfile(drive, &task);
+ if (task->data_phase == TASKFILE_MULTI_IN ||
+ task->data_phase == TASKFILE_MULTI_OUT) {
+ if (!drive->mult_count) {
+ printk(KERN_ERR "%s: multimode not set!\n", drive->name);
+ return ide_stopped;
+ }
+ }
- args[0] = task.tf.command;
- memcpy(&args[1], &task.tf_array[7], 6);
+ /*
+ * (ks) Check taskfile in flags.
+ * If set, then execute as it is defined.
+ * If not set, then define default settings.
+ * The default values are:
+ * read all taskfile registers (except data)
+ * read the hob registers (sector, nsector, lcyl, hcyl)
+ */
+ if (task->tf_in_flags.all == 0) {
+ task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
+ if (drive->addressing == 1)
+ task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
+ }
- if (copy_to_user(p, args, 7))
- err = -EFAULT;
+ /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
+ if (IDE_CONTROL_REG)
+ /* clear nIEN */
+ hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+ SELECT_MASK(drive, 0);
+
+ if (task->tf_out_flags.b.data) {
+ u16 data = taskfile->data + (hobfile->data << 8);
+ hwif->OUTW(data, IDE_DATA_REG);
+ }
+
+ /* (ks) send hob registers first */
+ if (task->tf_out_flags.b.nsector_hob)
+ hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
+ if (task->tf_out_flags.b.sector_hob)
+ hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
+ if (task->tf_out_flags.b.lcyl_hob)
+ hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
+ if (task->tf_out_flags.b.hcyl_hob)
+ hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
+
+ /* (ks) Send now the standard registers */
+ if (task->tf_out_flags.b.error_feature)
+ hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
+ /* refers to number of sectors to transfer */
+ if (task->tf_out_flags.b.nsector)
+ hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
+ /* refers to sector offset or start sector */
+ if (task->tf_out_flags.b.sector)
+ hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
+ if (task->tf_out_flags.b.lcyl)
+ hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
+ if (task->tf_out_flags.b.hcyl)
+ hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
+
+ /*
+ * (ks) In the flagged taskfile approch, we will use all specified
+ * registers and the register value will not be changed, except the
+ * select bit (master/slave) in the drive_head register. We must make
+ * sure that the desired drive is selected.
+ */
+ hwif->OUTB(taskfile->device_head | drive->select.all, IDE_SELECT_REG);
+ switch(task->data_phase) {
- return err;
+ case TASKFILE_OUT_DMAQ:
+ case TASKFILE_OUT_DMA:
+ case TASKFILE_IN_DMAQ:
+ case TASKFILE_IN_DMA:
+ if (!drive->using_dma)
+ break;
+
+ if (!hwif->dma_setup(drive)) {
+ hwif->dma_exec_cmd(drive, taskfile->command);
+ hwif->dma_start(drive);
+ return ide_started;
+ }
+ break;
+
+ default:
+ if (task->handler == NULL)
+ return ide_stopped;
+
+ /* Issue the command */
+ if (task->prehandler) {
+ hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
+ ndelay(400); /* FIXME */
+ return task->prehandler(drive, task->rq);
+ }
+ ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
+ return ide_started;
+ }
+
+ return ide_stopped;
}
diff --git a/trunk/drivers/ide/ide.c b/trunk/drivers/ide/ide.c
index c6d4f630e18a..54943da6e4e5 100644
--- a/trunk/drivers/ide/ide.c
+++ b/trunk/drivers/ide/ide.c
@@ -424,6 +424,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->reset_poll = tmp_hwif->reset_poll;
hwif->pre_reset = tmp_hwif->pre_reset;
hwif->resetproc = tmp_hwif->resetproc;
+ hwif->intrproc = tmp_hwif->intrproc;
hwif->maskproc = tmp_hwif->maskproc;
hwif->quirkproc = tmp_hwif->quirkproc;
hwif->busproc = tmp_hwif->busproc;
@@ -467,6 +468,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
#endif
hwif->dma_base = tmp_hwif->dma_base;
+ hwif->dma_master = tmp_hwif->dma_master;
hwif->dma_command = tmp_hwif->dma_command;
hwif->dma_vendor1 = tmp_hwif->dma_vendor1;
hwif->dma_status = tmp_hwif->dma_status;
@@ -600,6 +602,7 @@ void ide_unregister(unsigned int index)
(void) ide_release_dma(hwif);
hwif->dma_base = 0;
+ hwif->dma_master = 0;
hwif->dma_command = 0;
hwif->dma_vendor1 = 0;
hwif->dma_status = 0;
@@ -851,7 +854,8 @@ int set_using_dma(ide_drive_t *drive, int arg)
err = 0;
if (arg) {
- if (ide_set_dma(drive))
+ hwif->dma_off_quietly(drive);
+ if (ide_set_dma(drive) || hwif->ide_dma_on(drive))
err = -EIO;
} else
ide_dma_off(drive);
diff --git a/trunk/drivers/ide/mips/au1xxx-ide.c b/trunk/drivers/ide/mips/au1xxx-ide.c
index a4d0d4ca73d0..a4ce3ba15d61 100644
--- a/trunk/drivers/ide/mips/au1xxx-ide.c
+++ b/trunk/drivers/ide/mips/au1xxx-ide.c
@@ -198,6 +198,8 @@ static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
break;
#endif
+ default:
+ return;
}
au_writel(mem_sttime,MEM_STTIME2);
diff --git a/trunk/drivers/ide/pci/aec62xx.c b/trunk/drivers/ide/pci/aec62xx.c
index 7f4d1857d555..44268504ae43 100644
--- a/trunk/drivers/ide/pci/aec62xx.c
+++ b/trunk/drivers/ide/pci/aec62xx.c
@@ -202,7 +202,6 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.host_flags = IDE_HFLAG_SERIALIZE |
IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
@@ -212,7 +211,6 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
@@ -222,8 +220,7 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
@@ -231,9 +228,7 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.name = "AEC6280",
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
- IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -242,9 +237,7 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
- IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
diff --git a/trunk/drivers/ide/pci/alim15x3.c b/trunk/drivers/ide/pci/alim15x3.c
index 49aa82e412b6..ce293936af4b 100644
--- a/trunk/drivers/ide/pci/alim15x3.c
+++ b/trunk/drivers/ide/pci/alim15x3.c
@@ -402,6 +402,9 @@ static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
u8 tmpbyte = 0x00;
int m5229_udma = (hwif->channel) ? 0x57 : 0x56;
+ if (speed < XFER_PIO_0)
+ return;
+
if (speed == XFER_UDMA_6)
speed1 = 0x47;
diff --git a/trunk/drivers/ide/pci/amd74xx.c b/trunk/drivers/ide/pci/amd74xx.c
index cee51fdafcf6..8d4125ec252c 100644
--- a/trunk/drivers/ide/pci/amd74xx.c
+++ b/trunk/drivers/ide/pci/amd74xx.c
@@ -266,7 +266,6 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
#define IDE_HFLAGS_AMD \
(IDE_HFLAG_PIO_NO_BLACKLIST | \
IDE_HFLAG_PIO_NO_DOWNGRADE | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
IDE_HFLAG_POST_SET_MODE | \
IDE_HFLAG_IO_32BIT | \
IDE_HFLAG_UNMASK_IRQS | \
diff --git a/trunk/drivers/ide/pci/atiixp.c b/trunk/drivers/ide/pci/atiixp.c
index 5ae26564fb72..ef8e0164ef7a 100644
--- a/trunk/drivers/ide/pci/atiixp.c
+++ b/trunk/drivers/ide/pci/atiixp.c
@@ -133,6 +133,9 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
u32 tmp32;
u16 tmp16;
+ if (speed < XFER_MW_DMA_0)
+ return;
+
spin_lock_irqsave(&atiixp_lock, flags);
save_mdma_mode[drive->dn] = 0;
diff --git a/trunk/drivers/ide/pci/cmd64x.c b/trunk/drivers/ide/pci/cmd64x.c
index 0b1e9479f019..bc553337b1be 100644
--- a/trunk/drivers/ide/pci/cmd64x.c
+++ b/trunk/drivers/ide/pci/cmd64x.c
@@ -322,6 +322,8 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
case XFER_MW_DMA_0:
program_cycle_times(drive, 480, 215);
break;
+ default:
+ return;
}
if (speed >= XFER_SW_DMA_0)
@@ -331,15 +333,14 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
static int cmd648_ide_dma_end (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned long base = hwif->dma_base - (hwif->channel * 8);
int err = __ide_dma_end(drive);
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0;
- u8 mrdmode = inb(base + 1);
+ u8 mrdmode = inb(hwif->dma_master + 0x01);
/* clear the interrupt bit */
outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask,
- base + 1);
+ hwif->dma_master + 0x01);
return err;
}
@@ -364,11 +365,10 @@ static int cmd64x_ide_dma_end (ide_drive_t *drive)
static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned long base = hwif->dma_base - (hwif->channel * 8);
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0;
u8 dma_stat = inb(hwif->dma_status);
- u8 mrdmode = inb(base + 1);
+ u8 mrdmode = inb(hwif->dma_master + 0x01);
#ifdef DEBUG
printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n",
diff --git a/trunk/drivers/ide/pci/cs5520.c b/trunk/drivers/ide/pci/cs5520.c
index d1a91bcb5b29..0466462fd21b 100644
--- a/trunk/drivers/ide/pci/cs5520.c
+++ b/trunk/drivers/ide/pci/cs5520.c
@@ -137,7 +137,6 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
IDE_HFLAG_CS5520 | \
IDE_HFLAG_VDMA | \
IDE_HFLAG_NO_ATAPI_DMA | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE |\
IDE_HFLAG_BOOTABLE, \
.pio_mask = ATA_PIO4, \
}
diff --git a/trunk/drivers/ide/pci/cs5530.c b/trunk/drivers/ide/pci/cs5530.c
index df5966b33460..547690395eee 100644
--- a/trunk/drivers/ide/pci/cs5530.c
+++ b/trunk/drivers/ide/pci/cs5530.c
@@ -116,6 +116,8 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
case XFER_MW_DMA_0: timings = 0x00077771; break;
case XFER_MW_DMA_1: timings = 0x00012121; break;
case XFER_MW_DMA_2: timings = 0x00002020; break;
+ default:
+ return;
}
basereg = CS5530_BASEREG(drive->hwif);
reg = inl(basereg + 4); /* get drive0 config register */
diff --git a/trunk/drivers/ide/pci/cs5535.c b/trunk/drivers/ide/pci/cs5535.c
index 50b3d7791f55..ddcbeba671e1 100644
--- a/trunk/drivers/ide/pci/cs5535.c
+++ b/trunk/drivers/ide/pci/cs5535.c
@@ -190,7 +190,7 @@ static const struct ide_port_info cs5535_chipset __devinitdata = {
.name = "CS5535",
.init_hwif = init_hwif_cs5535,
.host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
- IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_BOOTABLE,
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
diff --git a/trunk/drivers/ide/pci/hpt34x.c b/trunk/drivers/ide/pci/hpt34x.c
index dfba0d13fcd3..ae6307fae4f9 100644
--- a/trunk/drivers/ide/pci/hpt34x.c
+++ b/trunk/drivers/ide/pci/hpt34x.c
@@ -129,18 +129,14 @@ static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif)
hwif->set_dma_mode = &hpt34x_set_mode;
}
-#define IDE_HFLAGS_HPT34X \
- (IDE_HFLAG_NO_ATAPI_DMA | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
- IDE_HFLAG_NO_AUTODMA)
-
static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
{ /* 0 */
.name = "HPT343",
.init_chipset = init_chipset_hpt34x,
.init_hwif = init_hwif_hpt34x,
.extra = 16,
- .host_flags = IDE_HFLAGS_HPT34X,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_NO_AUTODMA,
.pio_mask = ATA_PIO5,
},
{ /* 1 */
@@ -148,7 +144,9 @@ static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
.init_chipset = init_chipset_hpt34x,
.init_hwif = init_hwif_hpt34x,
.extra = 16,
- .host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_OFF_BOARD,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_NO_AUTODMA |
+ IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO5,
#ifdef CONFIG_HPT34X_AUTODMA
.swdma_mask = ATA_SWDMA2,
diff --git a/trunk/drivers/ide/pci/hpt366.c b/trunk/drivers/ide/pci/hpt366.c
index 3777fb8c8043..9fce25bdec8a 100644
--- a/trunk/drivers/ide/pci/hpt366.c
+++ b/trunk/drivers/ide/pci/hpt366.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/hpt366.c Version 1.30 Dec 12, 2007
+ * linux/drivers/ide/pci/hpt366.c Version 1.22 Dec 4, 2007
*
* Copyright (C) 1999-2003 Andre Hedrick
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
@@ -88,7 +88,7 @@
* - rename all the register related variables consistently
* - move all the interrupt twiddling code from the speedproc handlers into
* init_hwif_hpt366(), also grouping all the DMA related code together there
- * - merge HPT36x/HPT37x speedproc handlers, fix PIO timing register mask and
+ * - merge two HPT37x speedproc handlers, fix the PIO timing register mask and
* separate the UltraDMA and MWDMA masks there to avoid changing PIO timings
* when setting an UltraDMA mode
* - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select
@@ -458,13 +458,6 @@ enum ata_clock {
NUM_ATA_CLOCKS
};
-struct hpt_timings {
- u32 pio_mask;
- u32 dma_mask;
- u32 ultra_mask;
- u32 *clock_table[NUM_ATA_CLOCKS];
-};
-
/*
* Hold all the HighPoint chip information in one place.
*/
@@ -475,8 +468,7 @@ struct hpt_info {
u8 udma_mask; /* Allowed UltraDMA modes mask. */
u8 dpll_clk; /* DPLL clock in MHz */
u8 pci_clk; /* PCI clock in MHz */
- struct hpt_timings *timings; /* Chipset timing data */
- u8 clock; /* ATA clock selected */
+ u32 **settings; /* Chipset settings table */
};
/* Supported HighPoint chips */
@@ -494,30 +486,20 @@ enum {
HPT371N
};
-static struct hpt_timings hpt36x_timings = {
- .pio_mask = 0xc1f8ffff,
- .dma_mask = 0x303800ff,
- .ultra_mask = 0x30070000,
- .clock_table = {
- [ATA_CLOCK_25MHZ] = twenty_five_base_hpt36x,
- [ATA_CLOCK_33MHZ] = thirty_three_base_hpt36x,
- [ATA_CLOCK_40MHZ] = forty_base_hpt36x,
- [ATA_CLOCK_50MHZ] = NULL,
- [ATA_CLOCK_66MHZ] = NULL
- }
+static u32 *hpt36x_settings[NUM_ATA_CLOCKS] = {
+ twenty_five_base_hpt36x,
+ thirty_three_base_hpt36x,
+ forty_base_hpt36x,
+ NULL,
+ NULL
};
-static struct hpt_timings hpt37x_timings = {
- .pio_mask = 0xcfc3ffff,
- .dma_mask = 0x31c001ff,
- .ultra_mask = 0x303c0000,
- .clock_table = {
- [ATA_CLOCK_25MHZ] = NULL,
- [ATA_CLOCK_33MHZ] = thirty_three_base_hpt37x,
- [ATA_CLOCK_40MHZ] = NULL,
- [ATA_CLOCK_50MHZ] = fifty_base_hpt37x,
- [ATA_CLOCK_66MHZ] = sixty_six_base_hpt37x
- }
+static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = {
+ NULL,
+ thirty_three_base_hpt37x,
+ NULL,
+ fifty_base_hpt37x,
+ sixty_six_base_hpt37x
};
static const struct hpt_info hpt36x __devinitdata = {
@@ -525,7 +507,7 @@ static const struct hpt_info hpt36x __devinitdata = {
.chip_type = HPT36x,
.udma_mask = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,
.dpll_clk = 0, /* no DPLL */
- .timings = &hpt36x_timings
+ .settings = hpt36x_settings
};
static const struct hpt_info hpt370 __devinitdata = {
@@ -533,7 +515,7 @@ static const struct hpt_info hpt370 __devinitdata = {
.chip_type = HPT370,
.udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
.dpll_clk = 48,
- .timings = &hpt37x_timings
+ .settings = hpt37x_settings
};
static const struct hpt_info hpt370a __devinitdata = {
@@ -541,7 +523,7 @@ static const struct hpt_info hpt370a __devinitdata = {
.chip_type = HPT370A,
.udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
.dpll_clk = 48,
- .timings = &hpt37x_timings
+ .settings = hpt37x_settings
};
static const struct hpt_info hpt374 __devinitdata = {
@@ -549,7 +531,7 @@ static const struct hpt_info hpt374 __devinitdata = {
.chip_type = HPT374,
.udma_mask = ATA_UDMA5,
.dpll_clk = 48,
- .timings = &hpt37x_timings
+ .settings = hpt37x_settings
};
static const struct hpt_info hpt372 __devinitdata = {
@@ -557,7 +539,7 @@ static const struct hpt_info hpt372 __devinitdata = {
.chip_type = HPT372,
.udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 55,
- .timings = &hpt37x_timings
+ .settings = hpt37x_settings
};
static const struct hpt_info hpt372a __devinitdata = {
@@ -565,7 +547,7 @@ static const struct hpt_info hpt372a __devinitdata = {
.chip_type = HPT372A,
.udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 66,
- .timings = &hpt37x_timings
+ .settings = hpt37x_settings
};
static const struct hpt_info hpt302 __devinitdata = {
@@ -573,7 +555,7 @@ static const struct hpt_info hpt302 __devinitdata = {
.chip_type = HPT302,
.udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 66,
- .timings = &hpt37x_timings
+ .settings = hpt37x_settings
};
static const struct hpt_info hpt371 __devinitdata = {
@@ -581,7 +563,7 @@ static const struct hpt_info hpt371 __devinitdata = {
.chip_type = HPT371,
.udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 66,
- .timings = &hpt37x_timings
+ .settings = hpt37x_settings
};
static const struct hpt_info hpt372n __devinitdata = {
@@ -589,7 +571,7 @@ static const struct hpt_info hpt372n __devinitdata = {
.chip_type = HPT372N,
.udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 77,
- .timings = &hpt37x_timings
+ .settings = hpt37x_settings
};
static const struct hpt_info hpt302n __devinitdata = {
@@ -597,7 +579,7 @@ static const struct hpt_info hpt302n __devinitdata = {
.chip_type = HPT302N,
.udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 77,
- .timings = &hpt37x_timings
+ .settings = hpt37x_settings
};
static const struct hpt_info hpt371n __devinitdata = {
@@ -605,7 +587,7 @@ static const struct hpt_info hpt371n __devinitdata = {
.chip_type = HPT371N,
.udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 77,
- .timings = &hpt37x_timings
+ .settings = hpt37x_settings
};
static int check_in_drive_list(ide_drive_t *drive, const char **list)
@@ -693,33 +675,71 @@ static u32 get_speed_setting(u8 speed, struct hpt_info *info)
for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
if (xfer_speeds[i] == speed)
break;
-
- return info->timings->clock_table[info->clock][i];
+ /*
+ * NOTE: info->settings only points to the pointer
+ * to the list of the actual register values
+ */
+ return (*info->settings)[i];
}
-static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
+static void hpt36x_set_mode(ide_drive_t *drive, const u8 speed)
{
- struct pci_dev *dev = HWIF(drive)->pci_dev;
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = hwif->pci_dev;
struct hpt_info *info = pci_get_drvdata(dev);
- struct hpt_timings *t = info->timings;
- u8 itr_addr = 0x40 + (drive->dn * 4);
+ u8 itr_addr = drive->dn ? 0x44 : 0x40;
u32 old_itr = 0;
- u32 new_itr = get_speed_setting(speed, info);
- u32 itr_mask = speed < XFER_MW_DMA_0 ? t->pio_mask :
- (speed < XFER_UDMA_0 ? t->dma_mask :
- t->ultra_mask);
+ u32 itr_mask, new_itr;
+
+ itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 :
+ (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff);
+
+ new_itr = get_speed_setting(speed, info);
- pci_read_config_dword(dev, itr_addr, &old_itr);
- new_itr = (old_itr & ~itr_mask) | (new_itr & itr_mask);
/*
* Disable on-chip PIO FIFO/buffer (and PIO MST mode as well)
* to avoid problems handling I/O errors later
*/
+ pci_read_config_dword(dev, itr_addr, &old_itr);
+ new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask);
new_itr &= ~0xc0000000;
pci_write_config_dword(dev, itr_addr, new_itr);
}
+static void hpt37x_set_mode(ide_drive_t *drive, const u8 speed)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = hwif->pci_dev;
+ struct hpt_info *info = pci_get_drvdata(dev);
+ u8 itr_addr = 0x40 + (drive->dn * 4);
+ u32 old_itr = 0;
+ u32 itr_mask, new_itr;
+
+ itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 :
+ (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff);
+
+ new_itr = get_speed_setting(speed, info);
+
+ pci_read_config_dword(dev, itr_addr, &old_itr);
+ new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask);
+
+ if (speed < XFER_MW_DMA_0)
+ new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
+ pci_write_config_dword(dev, itr_addr, new_itr);
+}
+
+static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ struct hpt_info *info = pci_get_drvdata(hwif->pci_dev);
+
+ if (info->chip_type >= HPT370)
+ hpt37x_set_mode(drive, speed);
+ else /* hpt368: hpt_minimum_revision(dev, 2) */
+ hpt36x_set_mode(drive, speed);
+}
+
static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
hpt3xx_set_mode(drive, XFER_PIO_0 + pio);
@@ -736,6 +756,15 @@ static int hpt3xx_quirkproc(ide_drive_t *drive)
return 0;
}
+static void hpt3xx_intrproc(ide_drive_t *drive)
+{
+ if (drive->quirk_list)
+ return;
+
+ /* drives in the quirk_list may not like intr setups/cleanups */
+ outb(drive->ctl | 2, IDE_CONTROL_REG);
+}
+
static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -885,33 +914,32 @@ static int hpt374_ide_dma_end(ide_drive_t *drive)
static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
{
- unsigned long base = hwif->extra_base;
- u8 scr2 = inb(base + 0x6b);
+ u8 scr2 = inb(hwif->dma_master + 0x7b);
if ((scr2 & 0x7f) == mode)
return;
/* Tristate the bus */
- outb(0x80, base + 0x63);
- outb(0x80, base + 0x67);
+ outb(0x80, hwif->dma_master + 0x73);
+ outb(0x80, hwif->dma_master + 0x77);
/* Switch clock and reset channels */
- outb(mode, base + 0x6b);
- outb(0xc0, base + 0x69);
+ outb(mode, hwif->dma_master + 0x7b);
+ outb(0xc0, hwif->dma_master + 0x79);
/*
* Reset the state machines.
* NOTE: avoid accidentally enabling the disabled channels.
*/
- outb(inb(base + 0x60) | 0x32, base + 0x60);
- outb(inb(base + 0x64) | 0x32, base + 0x64);
+ outb(inb(hwif->dma_master + 0x70) | 0x32, hwif->dma_master + 0x70);
+ outb(inb(hwif->dma_master + 0x74) | 0x32, hwif->dma_master + 0x74);
/* Complete reset */
- outb(0x00, base + 0x69);
+ outb(0x00, hwif->dma_master + 0x79);
/* Reconnect channels to bus */
- outb(0x00, base + 0x63);
- outb(0x00, base + 0x67);
+ outb(0x00, hwif->dma_master + 0x73);
+ outb(0x00, hwif->dma_master + 0x77);
}
/**
@@ -1182,7 +1210,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
* We also don't like using the DPLL because this causes glitches
* on PRST-/SRST- when the state engine gets reset...
*/
- if (chip_type >= HPT374 || info->timings->clock_table[clock] == NULL) {
+ if (chip_type >= HPT374 || info->settings[clock] == NULL) {
u16 f_low, delta = pci_clk < 50 ? 2 : 4;
int adjust;
@@ -1198,7 +1226,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
clock = ATA_CLOCK_50MHZ;
}
- if (info->timings->clock_table[clock] == NULL) {
+ if (info->settings[clock] == NULL) {
printk(KERN_ERR "%s: unknown bus timing!\n", name);
kfree(info);
return -EIO;
@@ -1239,10 +1267,15 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
printk("%s: using %d MHz PCI clock\n", name, pci_clk);
}
+ /*
+ * Advance the table pointer to a slot which points to the list
+ * of the register values settings matching the clock being used.
+ */
+ info->settings += clock;
+
/* Store the clock frequencies. */
info->dpll_clk = dpll_clk;
info->pci_clk = pci_clk;
- info->clock = clock;
/* Point to this chip's own instance of the hpt_info structure. */
pci_set_drvdata(dev, info);
@@ -1287,8 +1320,8 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
hwif->set_pio_mode = &hpt3xx_set_pio_mode;
hwif->set_dma_mode = &hpt3xx_set_mode;
-
hwif->quirkproc = &hpt3xx_quirkproc;
+ hwif->intrproc = &hpt3xx_intrproc;
hwif->maskproc = &hpt3xx_maskproc;
hwif->busproc = &hpt3xx_busproc;
@@ -1461,11 +1494,6 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
return 0;
}
-#define IDE_HFLAGS_HPT3XX \
- (IDE_HFLAG_NO_ATAPI_DMA | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
- IDE_HFLAG_OFF_BOARD)
-
static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
{ /* 0 */
.name = "HPT36x",
@@ -1480,7 +1508,9 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
*/
.enablebits = {{0x50,0x10,0x10}, {0x54,0x04,0x04}},
.extra = 240,
- .host_flags = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
+ .host_flags = IDE_HFLAG_SINGLE |
+ IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
},{ /* 1 */
@@ -1490,7 +1520,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
.init_dma = init_dma_hpt366,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.extra = 240,
- .host_flags = IDE_HFLAGS_HPT3XX,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
},{ /* 2 */
@@ -1500,7 +1530,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
.init_dma = init_dma_hpt366,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.extra = 240,
- .host_flags = IDE_HFLAGS_HPT3XX,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
},{ /* 3 */
@@ -1510,7 +1540,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
.init_dma = init_dma_hpt366,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.extra = 240,
- .host_flags = IDE_HFLAGS_HPT3XX,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
},{ /* 4 */
@@ -1521,7 +1551,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.udma_mask = ATA_UDMA5,
.extra = 240,
- .host_flags = IDE_HFLAGS_HPT3XX,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
},{ /* 5 */
@@ -1531,7 +1561,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
.init_dma = init_dma_hpt366,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.extra = 240,
- .host_flags = IDE_HFLAGS_HPT3XX,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
}
diff --git a/trunk/drivers/ide/pci/it8213.c b/trunk/drivers/ide/pci/it8213.c
index 2a0f45c4f4c4..90b52ed37bfc 100644
--- a/trunk/drivers/ide/pci/it8213.c
+++ b/trunk/drivers/ide/pci/it8213.c
@@ -101,11 +101,24 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_read_config_byte(dev, 0x54, ®54);
pci_read_config_byte(dev, 0x55, ®55);
- if (speed >= XFER_UDMA_0) {
- u8 udma = speed - XFER_UDMA_0;
-
- u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
+ switch(speed) {
+ case XFER_UDMA_6:
+ case XFER_UDMA_4:
+ case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
+ case XFER_UDMA_5:
+ case XFER_UDMA_3:
+ case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
+ case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
+ break;
+ case XFER_MW_DMA_2:
+ case XFER_MW_DMA_1:
+ case XFER_SW_DMA_2:
+ break;
+ default:
+ return;
+ }
+ if (speed >= XFER_UDMA_0) {
if (!(reg48 & u_flag))
pci_write_config_byte(dev, 0x48, reg48 | u_flag);
if (speed >= XFER_UDMA_5) {
diff --git a/trunk/drivers/ide/pci/pdc202xx_new.c b/trunk/drivers/ide/pci/pdc202xx_new.c
index ef4a99b99d1f..2b4f44e45a1a 100644
--- a/trunk/drivers/ide/pci/pdc202xx_new.c
+++ b/trunk/drivers/ide/pci/pdc202xx_new.c
@@ -146,7 +146,7 @@ static struct udma_timing {
{ 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */
};
-static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
@@ -162,18 +162,45 @@ static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed)
if (max_dma_rate(hwif->pci_dev) == 4) {
u8 mode = speed & 0x07;
- if (speed >= XFER_UDMA_0) {
- set_indexed_reg(hwif, 0x10 + adj,
- udma_timings[mode].reg10);
- set_indexed_reg(hwif, 0x11 + adj,
- udma_timings[mode].reg11);
- set_indexed_reg(hwif, 0x12 + adj,
- udma_timings[mode].reg12);
- } else {
- set_indexed_reg(hwif, 0x0e + adj,
- mwdma_timings[mode].reg0e);
- set_indexed_reg(hwif, 0x0f + adj,
- mwdma_timings[mode].reg0f);
+ switch (speed) {
+ case XFER_UDMA_6:
+ case XFER_UDMA_5:
+ case XFER_UDMA_4:
+ case XFER_UDMA_3:
+ case XFER_UDMA_2:
+ case XFER_UDMA_1:
+ case XFER_UDMA_0:
+ set_indexed_reg(hwif, 0x10 + adj,
+ udma_timings[mode].reg10);
+ set_indexed_reg(hwif, 0x11 + adj,
+ udma_timings[mode].reg11);
+ set_indexed_reg(hwif, 0x12 + adj,
+ udma_timings[mode].reg12);
+ break;
+
+ case XFER_MW_DMA_2:
+ case XFER_MW_DMA_1:
+ case XFER_MW_DMA_0:
+ set_indexed_reg(hwif, 0x0e + adj,
+ mwdma_timings[mode].reg0e);
+ set_indexed_reg(hwif, 0x0f + adj,
+ mwdma_timings[mode].reg0f);
+ break;
+ case XFER_PIO_4:
+ case XFER_PIO_3:
+ case XFER_PIO_2:
+ case XFER_PIO_1:
+ case XFER_PIO_0:
+ set_indexed_reg(hwif, 0x0c + adj,
+ pio_timings[mode].reg0c);
+ set_indexed_reg(hwif, 0x0d + adj,
+ pio_timings[mode].reg0d);
+ set_indexed_reg(hwif, 0x13 + adj,
+ pio_timings[mode].reg13);
+ break;
+ default:
+ printk(KERN_ERR "pdc202xx_new: "
+ "Unknown speed %d ignored\n", speed);
}
} else if (speed == XFER_UDMA_2) {
/* Set tHOLD bit to 0 if using UDMA mode 2 */
@@ -185,14 +212,7 @@ static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed)
static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = drive->hwif;
- u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
-
- if (max_dma_rate(hwif->pci_dev) == 4) {
- set_indexed_reg(hwif, 0x0c + adj, pio_timings[pio].reg0c);
- set_indexed_reg(hwif, 0x0d + adj, pio_timings[pio].reg0d);
- set_indexed_reg(hwif, 0x13 + adj, pio_timings[pio].reg13);
- }
+ pdcnew_set_mode(drive, XFER_PIO_0 + pio);
}
static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
@@ -446,7 +466,7 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
{
hwif->set_pio_mode = &pdcnew_set_pio_mode;
- hwif->set_dma_mode = &pdcnew_set_dma_mode;
+ hwif->set_dma_mode = &pdcnew_set_mode;
hwif->quirkproc = &pdcnew_quirkproc;
hwif->resetproc = &pdcnew_reset;
diff --git a/trunk/drivers/ide/pci/pdc202xx_old.c b/trunk/drivers/ide/pci/pdc202xx_old.c
index 67b2781e2213..e09742e2ba59 100644
--- a/trunk/drivers/ide/pci/pdc202xx_old.c
+++ b/trunk/drivers/ide/pci/pdc202xx_old.c
@@ -162,7 +162,7 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
*/
static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
{
- unsigned long clock_reg = hwif->extra_base + 0x01;
+ unsigned long clock_reg = hwif->dma_master + 0x11;
u8 clock = inb(clock_reg);
outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg);
@@ -170,7 +170,7 @@ static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
{
- unsigned long clock_reg = hwif->extra_base + 0x01;
+ unsigned long clock_reg = hwif->dma_master + 0x11;
u8 clock = inb(clock_reg);
outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
@@ -193,7 +193,7 @@ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
if (drive->media != ide_disk || drive->addressing == 1) {
struct request *rq = HWGROUP(drive)->rq;
ide_hwif_t *hwif = HWIF(drive);
- unsigned long high_16 = hwif->extra_base - 16;
+ unsigned long high_16 = hwif->dma_master;
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
u32 word_count = 0;
u8 clock = inb(high_16 + 0x11);
@@ -212,7 +212,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
{
if (drive->media != ide_disk || drive->addressing == 1) {
ide_hwif_t *hwif = HWIF(drive);
- unsigned long high_16 = hwif->extra_base - 16;
+ unsigned long high_16 = hwif->dma_master;
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
u8 clock = 0;
@@ -228,7 +228,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned long high_16 = hwif->extra_base - 16;
+ unsigned long high_16 = hwif->dma_master;
u8 dma_stat = inb(hwif->dma_status);
u8 sc1d = inb(high_16 + 0x001d);
@@ -271,7 +271,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive)
static void pdc202xx_reset_host (ide_hwif_t *hwif)
{
- unsigned long high_16 = hwif->extra_base - 16;
+ unsigned long high_16 = hwif->dma_master;
u8 udma_speed_flag = inb(high_16 | 0x001f);
outb(udma_speed_flag | 0x10, high_16 | 0x001f);
@@ -375,11 +375,6 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
}
}
-#define IDE_HFLAGS_PDC202XX \
- (IDE_HFLAG_ERROR_STOPS_FIFO | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
- IDE_HFLAG_OFF_BOARD)
-
#define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \
{ \
.name = name_str, \
@@ -387,7 +382,9 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
.init_hwif = init_hwif_pdc202xx, \
.init_dma = init_dma_pdc202xx, \
.extra = 48, \
- .host_flags = IDE_HFLAGS_PDC202XX | extra_flags, \
+ .host_flags = IDE_HFLAG_ERROR_STOPS_FIFO | \
+ extra_flags | \
+ IDE_HFLAG_OFF_BOARD, \
.pio_mask = ATA_PIO4, \
.mwdma_mask = ATA_MWDMA2, \
.udma_mask = udma, \
@@ -400,7 +397,8 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
.init_hwif = init_hwif_pdc202xx,
.init_dma = init_dma_pdc202xx,
.extra = 16,
- .host_flags = IDE_HFLAGS_PDC202XX,
+ .host_flags = IDE_HFLAG_ERROR_STOPS_FIFO |
+ IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
diff --git a/trunk/drivers/ide/pci/piix.c b/trunk/drivers/ide/pci/piix.c
index bd6d3f77d30c..27781d294cea 100644
--- a/trunk/drivers/ide/pci/piix.c
+++ b/trunk/drivers/ide/pci/piix.c
@@ -203,11 +203,20 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_read_config_byte(dev, 0x54, ®54);
pci_read_config_byte(dev, 0x55, ®55);
- if (speed >= XFER_UDMA_0) {
- u8 udma = speed - XFER_UDMA_0;
-
- u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
+ switch(speed) {
+ case XFER_UDMA_4:
+ case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
+ case XFER_UDMA_5:
+ case XFER_UDMA_3:
+ case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
+ case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
+ case XFER_MW_DMA_2:
+ case XFER_MW_DMA_1:
+ case XFER_SW_DMA_2: break;
+ default: return;
+ }
+ if (speed >= XFER_UDMA_0) {
if (!(reg48 & u_flag))
pci_write_config_byte(dev, 0x48, reg48 | u_flag);
if (speed == XFER_UDMA_5) {
diff --git a/trunk/drivers/ide/pci/sc1200.c b/trunk/drivers/ide/pci/sc1200.c
index fef20bd4aa78..707d5ff66b03 100644
--- a/trunk/drivers/ide/pci/sc1200.c
+++ b/trunk/drivers/ide/pci/sc1200.c
@@ -135,29 +135,59 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
unsigned short pci_clock;
unsigned int basereg = hwif->channel ? 0x50 : 0x40;
- static const u32 udma_timing[3][3] = {
- { 0x00921250, 0x00911140, 0x00911030 },
- { 0x00932470, 0x00922260, 0x00922140 },
- { 0x009436a1, 0x00933481, 0x00923261 },
- };
-
- static const u32 mwdma_timing[3][3] = {
- { 0x00077771, 0x00012121, 0x00002020 },
- { 0x000bbbb2, 0x00024241, 0x00013131 },
- { 0x000ffff3, 0x00035352, 0x00015151 },
- };
-
pci_clock = sc1200_get_pci_clock();
/*
* Note that each DMA mode has several timings associated with it.
* The correct timing depends on the fast PCI clock freq.
*/
-
- if (mode >= XFER_UDMA_0)
- timings = udma_timing[pci_clock][mode - XFER_UDMA_0];
- else
- timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0];
+ timings = 0;
+ switch (mode) {
+ case XFER_UDMA_0:
+ switch (pci_clock) {
+ case PCI_CLK_33: timings = 0x00921250; break;
+ case PCI_CLK_48: timings = 0x00932470; break;
+ case PCI_CLK_66: timings = 0x009436a1; break;
+ }
+ break;
+ case XFER_UDMA_1:
+ switch (pci_clock) {
+ case PCI_CLK_33: timings = 0x00911140; break;
+ case PCI_CLK_48: timings = 0x00922260; break;
+ case PCI_CLK_66: timings = 0x00933481; break;
+ }
+ break;
+ case XFER_UDMA_2:
+ switch (pci_clock) {
+ case PCI_CLK_33: timings = 0x00911030; break;
+ case PCI_CLK_48: timings = 0x00922140; break;
+ case PCI_CLK_66: timings = 0x00923261; break;
+ }
+ break;
+ case XFER_MW_DMA_0:
+ switch (pci_clock) {
+ case PCI_CLK_33: timings = 0x00077771; break;
+ case PCI_CLK_48: timings = 0x000bbbb2; break;
+ case PCI_CLK_66: timings = 0x000ffff3; break;
+ }
+ break;
+ case XFER_MW_DMA_1:
+ switch (pci_clock) {
+ case PCI_CLK_33: timings = 0x00012121; break;
+ case PCI_CLK_48: timings = 0x00024241; break;
+ case PCI_CLK_66: timings = 0x00035352; break;
+ }
+ break;
+ case XFER_MW_DMA_2:
+ switch (pci_clock) {
+ case PCI_CLK_33: timings = 0x00002020; break;
+ case PCI_CLK_48: timings = 0x00013131; break;
+ case PCI_CLK_66: timings = 0x00015151; break;
+ }
+ break;
+ default:
+ return;
+ }
if (unit == 0) { /* are we configuring drive0? */
pci_read_config_dword(hwif->pci_dev, basereg+4, ®);
@@ -230,40 +260,67 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
}
#ifdef CONFIG_PM
-struct sc1200_saved_state {
- u32 regs[8];
-};
+static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev)
+{
+ int h;
+
+ for (h = 0; h < MAX_HWIFS; h++) {
+ ide_hwif_t *hwif = &ide_hwifs[h];
+ if (prev) {
+ if (hwif == prev)
+ prev = NULL; // found previous, now look for next match
+ } else {
+ if (hwif && hwif->pci_dev == dev)
+ return hwif; // found next match
+ }
+ }
+ return NULL; // not found
+}
+
+typedef struct sc1200_saved_state_s {
+ __u32 regs[4];
+} sc1200_saved_state_t;
+
static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
{
+ ide_hwif_t *hwif = NULL;
+
printk("SC1200: suspend(%u)\n", state.event);
- /*
- * we only save state when going from full power to less
- */
if (state.event == PM_EVENT_ON) {
- struct sc1200_saved_state *ss;
- unsigned int r;
-
- /*
- * allocate a permanent save area, if not already allocated
- */
- ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
- if (ss == NULL) {
- ss = kmalloc(sizeof(*ss), GFP_KERNEL);
- if (ss == NULL)
- return -ENOMEM;
- pci_set_drvdata(dev, ss);
+ // we only save state when going from full power to less
+
+ //
+ // Loop over all interfaces that are part of this PCI device:
+ //
+ while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
+ sc1200_saved_state_t *ss;
+ unsigned int basereg, r;
+ //
+ // allocate a permanent save area, if not already allocated
+ //
+ ss = (sc1200_saved_state_t *)hwif->config_data;
+ if (ss == NULL) {
+ ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL);
+ if (ss == NULL)
+ return -ENOMEM;
+ hwif->config_data = (unsigned long)ss;
+ }
+ ss = (sc1200_saved_state_t *)hwif->config_data;
+ //
+ // Save timing registers: this may be unnecessary if
+ // BIOS also does it
+ //
+ basereg = hwif->channel ? 0x50 : 0x40;
+ for (r = 0; r < 4; ++r) {
+ pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]);
+ }
}
-
- /*
- * save timing registers
- * (this may be unnecessary if BIOS also does it)
- */
- for (r = 0; r < 8; r++)
- pci_read_config_dword(dev, 0x40 + r * 4, &ss->regs[r]);
}
+ /* You don't need to iterate over disks -- sysfs should have done that for you already */
+
pci_disable_device(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
@@ -271,25 +328,30 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
static int sc1200_resume (struct pci_dev *dev)
{
- struct sc1200_saved_state *ss;
- unsigned int r;
- int i;
+ ide_hwif_t *hwif = NULL;
+ int i;
i = pci_enable_device(dev);
if (i)
return i;
- ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
-
- /*
- * restore timing registers
- * (this may be unnecessary if BIOS also does it)
- */
- if (ss) {
- for (r = 0; r < 8; r++)
- pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]);
+ //
+ // loop over all interfaces that are part of this pci device:
+ //
+ while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
+ unsigned int basereg, r;
+ sc1200_saved_state_t *ss = (sc1200_saved_state_t *)hwif->config_data;
+
+ //
+ // Restore timing registers: this may be unnecessary if BIOS also does it
+ //
+ basereg = hwif->channel ? 0x50 : 0x40;
+ if (ss != NULL) {
+ for (r = 0; r < 4; ++r) {
+ pci_write_config_dword(hwif->pci_dev, basereg + (r<<2), ss->regs[r]);
+ }
+ }
}
-
return 0;
}
#endif
diff --git a/trunk/drivers/ide/pci/scc_pata.c b/trunk/drivers/ide/pci/scc_pata.c
index 24a85bbcd2a6..ebb7132b9b84 100644
--- a/trunk/drivers/ide/pci/scc_pata.c
+++ b/trunk/drivers/ide/pci/scc_pata.c
@@ -254,7 +254,19 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
offset = 0; /* 100MHz */
}
- idx = speed - XFER_UDMA_0;
+ switch (speed) {
+ case XFER_UDMA_6:
+ case XFER_UDMA_5:
+ case XFER_UDMA_4:
+ case XFER_UDMA_3:
+ case XFER_UDMA_2:
+ case XFER_UDMA_1:
+ case XFER_UDMA_0:
+ idx = speed - XFER_UDMA_0;
+ break;
+ default:
+ return;
+ }
jcactsel = JCACTSELtbl[offset][idx];
if (is_slave) {
diff --git a/trunk/drivers/ide/pci/serverworks.c b/trunk/drivers/ide/pci/serverworks.c
index e9bd269547bb..a7280311357b 100644
--- a/trunk/drivers/ide/pci/serverworks.c
+++ b/trunk/drivers/ide/pci/serverworks.c
@@ -366,17 +366,12 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
}
}
-#define IDE_HFLAGS_SVWKS \
- (IDE_HFLAG_LEGACY_IRQS | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
- IDE_HFLAG_BOOTABLE)
-
static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
{ /* 0 */
.name = "SvrWks OSB4",
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .host_flags = IDE_HFLAGS_SVWKS,
+ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = 0x00, /* UDMA is problematic on OSB4 */
@@ -384,7 +379,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
.name = "SvrWks CSB5",
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .host_flags = IDE_HFLAGS_SVWKS,
+ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -392,7 +387,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
.name = "SvrWks CSB6",
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .host_flags = IDE_HFLAGS_SVWKS,
+ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -400,7 +395,8 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
.name = "SvrWks CSB6",
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
+ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -408,7 +404,8 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
.name = "SvrWks HT1000",
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
+ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
diff --git a/trunk/drivers/ide/pci/sgiioc4.c b/trunk/drivers/ide/pci/sgiioc4.c
index 7e9dade5648d..de820aa58cd0 100644
--- a/trunk/drivers/ide/pci/sgiioc4.c
+++ b/trunk/drivers/ide/pci/sgiioc4.c
@@ -582,6 +582,7 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
hwif->pre_reset = NULL; /* No HBA specific pre_set needed */
hwif->resetproc = &sgiioc4_resetproc;/* Reset DMA engine,
clear interrupts */
+ hwif->intrproc = NULL; /* Enable or Disable interrupt from drive */
hwif->maskproc = &sgiioc4_maskproc; /* Mask on/off NIEN register */
hwif->quirkproc = NULL;
hwif->busproc = NULL;
diff --git a/trunk/drivers/ide/pci/siimage.c b/trunk/drivers/ide/pci/siimage.c
index 7b45eaf5afd9..5709c252543b 100644
--- a/trunk/drivers/ide/pci/siimage.c
+++ b/trunk/drivers/ide/pci/siimage.c
@@ -278,14 +278,27 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
scsc = is_sata(hwif) ? 1 : scsc;
- if (speed >= XFER_UDMA_0) {
- multi = dma[2];
- ultra |= (scsc ? ultra6[speed - XFER_UDMA_0] :
- ultra5[speed - XFER_UDMA_0]);
- mode |= (unit ? 0x30 : 0x03);
- } else {
- multi = dma[speed - XFER_MW_DMA_0];
- mode |= (unit ? 0x20 : 0x02);
+ switch(speed) {
+ case XFER_MW_DMA_2:
+ case XFER_MW_DMA_1:
+ case XFER_MW_DMA_0:
+ multi = dma[speed - XFER_MW_DMA_0];
+ mode |= ((unit) ? 0x20 : 0x02);
+ break;
+ case XFER_UDMA_6:
+ case XFER_UDMA_5:
+ case XFER_UDMA_4:
+ case XFER_UDMA_3:
+ case XFER_UDMA_2:
+ case XFER_UDMA_1:
+ case XFER_UDMA_0:
+ multi = dma[2];
+ ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) :
+ (ultra5[speed - XFER_UDMA_0]));
+ mode |= ((unit) ? 0x30 : 0x03);
+ break;
+ default:
+ return;
}
if (hwif->mmio) {
diff --git a/trunk/drivers/ide/pci/sis5513.c b/trunk/drivers/ide/pci/sis5513.c
index 85d36996e6af..d90b42917775 100644
--- a/trunk/drivers/ide/pci/sis5513.c
+++ b/trunk/drivers/ide/pci/sis5513.c
@@ -305,56 +305,59 @@ static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
sis_program_timings(drive, XFER_PIO_0 + pio);
}
-static void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode)
-{
- struct pci_dev *dev = drive->hwif->pci_dev;
- u32 regdw = 0;
- u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
-
- pci_read_config_dword(dev, drive_pci, ®dw);
-
- regdw |= 0x04;
- regdw &= 0xfffff00f;
- /* check if ATA133 enable */
- clk = (regdw & 0x08) ? ATA_133 : ATA_100;
- idx = mode - XFER_UDMA_0;
- regdw |= cycle_time_value[clk][idx] << 4;
- regdw |= cvs_time_value[clk][idx] << 8;
-
- pci_write_config_dword(dev, drive_pci, regdw);
-}
-
-static void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode)
-{
- struct pci_dev *dev = drive->hwif->pci_dev;
- u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family;
-
- pci_read_config_byte(dev, drive_pci + 1, ®);
-
- /* force the UDMA bit on if we want to use UDMA */
- reg |= 0x80;
- /* clean reg cycle time bits */
- reg &= ~((0xff >> (8 - cycle_time_range[i])) << cycle_time_offset[i]);
- /* set reg cycle time bits */
- reg |= cycle_time_value[i][mode - XFER_UDMA_0] << cycle_time_offset[i];
-
- pci_write_config_byte(dev, drive_pci + 1, reg);
-}
-
-static void sis_program_udma_timings(ide_drive_t *drive, const u8 mode)
-{
- if (chipset_family >= ATA_133) /* ATA_133 */
- sis_ata133_program_udma_timings(drive, mode);
- else /* ATA_33/66/100a/100/133a */
- sis_ata33_program_udma_timings(drive, mode);
-}
-
static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
- if (speed >= XFER_UDMA_0)
- sis_program_udma_timings(drive, speed);
- else
- sis_program_timings(drive, speed);
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = hwif->pci_dev;
+
+ /* Config chip for mode */
+ switch(speed) {
+ case XFER_UDMA_6:
+ case XFER_UDMA_5:
+ case XFER_UDMA_4:
+ case XFER_UDMA_3:
+ case XFER_UDMA_2:
+ case XFER_UDMA_1:
+ case XFER_UDMA_0:
+ if (chipset_family >= ATA_133) {
+ u32 regdw = 0;
+ u8 drive_pci = sis_ata133_get_base(drive);
+
+ pci_read_config_dword(dev, drive_pci, ®dw);
+ regdw |= 0x04;
+ regdw &= 0xfffff00f;
+ /* check if ATA133 enable */
+ if (regdw & 0x08) {
+ regdw |= (unsigned long)cycle_time_value[ATA_133][speed-XFER_UDMA_0] << 4;
+ regdw |= (unsigned long)cvs_time_value[ATA_133][speed-XFER_UDMA_0] << 8;
+ } else {
+ regdw |= (unsigned long)cycle_time_value[ATA_100][speed-XFER_UDMA_0] << 4;
+ regdw |= (unsigned long)cvs_time_value[ATA_100][speed-XFER_UDMA_0] << 8;
+ }
+ pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);
+ } else {
+ u8 drive_pci = 0x40 + drive->dn * 2, reg = 0;
+
+ pci_read_config_byte(dev, drive_pci+1, ®);
+ /* Force the UDMA bit on if we want to use UDMA */
+ reg |= 0x80;
+ /* clean reg cycle time bits */
+ reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family]))
+ << cycle_time_offset[chipset_family]);
+ /* set reg cycle time bits */
+ reg |= cycle_time_value[chipset_family][speed-XFER_UDMA_0]
+ << cycle_time_offset[chipset_family];
+ pci_write_config_byte(dev, drive_pci+1, reg);
+ }
+ break;
+ case XFER_MW_DMA_2:
+ case XFER_MW_DMA_1:
+ case XFER_MW_DMA_0:
+ sis_program_timings(drive, speed);
+ break;
+ default:
+ break;
+ }
}
static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
diff --git a/trunk/drivers/ide/pci/sl82c105.c b/trunk/drivers/ide/pci/sl82c105.c
index 069f104fdcea..147d783f7529 100644
--- a/trunk/drivers/ide/pci/sl82c105.c
+++ b/trunk/drivers/ide/pci/sl82c105.c
@@ -115,24 +115,32 @@ static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed)
DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n",
drive->name, ide_xfer_verbose(speed)));
- drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
+ switch (speed) {
+ case XFER_MW_DMA_2:
+ case XFER_MW_DMA_1:
+ case XFER_MW_DMA_0:
+ drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
- /*
- * Store the DMA timings so that we can actually program
- * them when DMA will be turned on...
- */
- drive->drive_data &= 0x0000ffff;
- drive->drive_data |= (unsigned long)drv_ctrl << 16;
-
- /*
- * If we are already using DMA, we just reprogram
- * the drive control register.
- */
- if (drive->using_dma) {
- struct pci_dev *dev = HWIF(drive)->pci_dev;
- int reg = 0x44 + drive->dn * 4;
+ /*
+ * Store the DMA timings so that we can actually program
+ * them when DMA will be turned on...
+ */
+ drive->drive_data &= 0x0000ffff;
+ drive->drive_data |= (unsigned long)drv_ctrl << 16;
- pci_write_config_word(dev, reg, drv_ctrl);
+ /*
+ * If we are already using DMA, we just reprogram
+ * the drive control register.
+ */
+ if (drive->using_dma) {
+ struct pci_dev *dev = HWIF(drive)->pci_dev;
+ int reg = 0x44 + drive->dn * 4;
+
+ pci_write_config_word(dev, reg, drv_ctrl);
+ }
+ break;
+ default:
+ return;
}
}
diff --git a/trunk/drivers/ide/pci/slc90e66.c b/trunk/drivers/ide/pci/slc90e66.c
index dbbb46819a2d..eb4445b229ed 100644
--- a/trunk/drivers/ide/pci/slc90e66.c
+++ b/trunk/drivers/ide/pci/slc90e66.c
@@ -91,9 +91,19 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_read_config_word(dev, 0x48, ®48);
pci_read_config_word(dev, 0x4a, ®4a);
- if (speed >= XFER_UDMA_0) {
- u_speed = (speed - XFER_UDMA_0) << (drive->dn * 4);
+ switch(speed) {
+ case XFER_UDMA_4: u_speed = 4 << (drive->dn * 4); break;
+ case XFER_UDMA_3: u_speed = 3 << (drive->dn * 4); break;
+ case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
+ case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
+ case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
+ case XFER_MW_DMA_2:
+ case XFER_MW_DMA_1:
+ case XFER_SW_DMA_2: break;
+ default: return;
+ }
+ if (speed >= XFER_UDMA_0) {
if (!(reg48 & u_flag))
pci_write_config_word(dev, 0x48, reg48|u_flag);
/* FIXME: (reg4a & a_speed) ? */
diff --git a/trunk/drivers/ide/pci/tc86c001.c b/trunk/drivers/ide/pci/tc86c001.c
index e1faf6c2fe16..a66ebd14664e 100644
--- a/trunk/drivers/ide/pci/tc86c001.c
+++ b/trunk/drivers/ide/pci/tc86c001.c
@@ -222,8 +222,7 @@ static const struct ide_port_info tc86c001_chipset __devinitdata = {
.name = "TC86C001",
.init_chipset = init_chipset_tc86c001,
.init_hwif = init_hwif_tc86c001,
- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD |
- IDE_HFLAG_ABUSE_SET_DMA_MODE,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
diff --git a/trunk/drivers/ide/pci/triflex.c b/trunk/drivers/ide/pci/triflex.c
index ae52a96a1cf9..a227c41d23a3 100644
--- a/trunk/drivers/ide/pci/triflex.c
+++ b/trunk/drivers/ide/pci/triflex.c
@@ -81,6 +81,8 @@ static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
case XFER_PIO_0:
timing = 0x0808;
break;
+ default:
+ return;
}
triflex_timings &= ~(0xFFFF << (16 * unit));
diff --git a/trunk/drivers/ide/pci/via82cxxx.c b/trunk/drivers/ide/pci/via82cxxx.c
index 4b32c90f4896..a0d3c16b68ec 100644
--- a/trunk/drivers/ide/pci/via82cxxx.c
+++ b/trunk/drivers/ide/pci/via82cxxx.c
@@ -439,7 +439,6 @@ static const struct ide_port_info via82cxxx_chipset __devinitdata = {
.enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
.host_flags = IDE_HFLAG_PIO_NO_BLACKLIST |
IDE_HFLAG_PIO_NO_DOWNGRADE |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_POST_SET_MODE |
IDE_HFLAG_IO_32BIT |
IDE_HFLAG_BOOTABLE,
diff --git a/trunk/drivers/ide/ppc/pmac.c b/trunk/drivers/ide/ppc/pmac.c
index 3dce80092fff..7f7a59885777 100644
--- a/trunk/drivers/ide/ppc/pmac.c
+++ b/trunk/drivers/ide/ppc/pmac.c
@@ -438,8 +438,13 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
if (data_port == pmac_ide[ix].regbase)
break;
- if (ix >= MAX_HWIFS)
- return; /* not an IDE PMAC interface */
+ if (ix >= MAX_HWIFS) {
+ /* Probably a PCI interface... */
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i)
+ hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET;
+ hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+ return;
+ }
for (i = 0; i < 8; ++i)
hw->io_ports[i] = data_port + i * 0x10;
@@ -828,20 +833,38 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
tl[0] = *timings;
tl[1] = *timings2;
+ switch(speed) {
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
- if (speed >= XFER_UDMA_0) {
- if (pmif->kind == controller_kl_ata4)
- ret = set_timings_udma_ata4(&tl[0], speed);
- else if (pmif->kind == controller_un_ata6
- || pmif->kind == controller_k2_ata6)
- ret = set_timings_udma_ata6(&tl[0], &tl[1], speed);
- else if (pmif->kind == controller_sh_ata6)
- ret = set_timings_udma_shasta(&tl[0], &tl[1], speed);
- else
- ret = -1;
- } else
- set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed);
+ case XFER_UDMA_6:
+ case XFER_UDMA_5:
+ case XFER_UDMA_4:
+ case XFER_UDMA_3:
+ case XFER_UDMA_2:
+ case XFER_UDMA_1:
+ case XFER_UDMA_0:
+ if (pmif->kind == controller_kl_ata4)
+ ret = set_timings_udma_ata4(&tl[0], speed);
+ else if (pmif->kind == controller_un_ata6
+ || pmif->kind == controller_k2_ata6)
+ ret = set_timings_udma_ata6(&tl[0], &tl[1], speed);
+ else if (pmif->kind == controller_sh_ata6)
+ ret = set_timings_udma_shasta(&tl[0], &tl[1], speed);
+ else
+ ret = 1;
+ break;
+ case XFER_MW_DMA_2:
+ case XFER_MW_DMA_1:
+ case XFER_MW_DMA_0:
+ set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed);
+ break;
+ case XFER_SW_DMA_2:
+ case XFER_SW_DMA_1:
+ case XFER_SW_DMA_0:
+ return;
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+ default:
+ ret = 1;
+ }
if (ret)
return;
diff --git a/trunk/drivers/infiniband/core/cm.c b/trunk/drivers/infiniband/core/cm.c
index c0150147d347..2e39236d189f 100644
--- a/trunk/drivers/infiniband/core/cm.c
+++ b/trunk/drivers/infiniband/core/cm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2007 Intel Corporation. All rights reserved.
+ * Copyright (c) 2004-2006 Intel Corporation. All rights reserved.
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
* Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
@@ -37,14 +37,12 @@
#include
#include
-#include
#include
#include
#include
#include
#include
#include
-#include
#include
#include
@@ -80,94 +78,17 @@ static struct ib_cm {
struct workqueue_struct *wq;
} cm;
-/* Counter indexes ordered by attribute ID */
-enum {
- CM_REQ_COUNTER,
- CM_MRA_COUNTER,
- CM_REJ_COUNTER,
- CM_REP_COUNTER,
- CM_RTU_COUNTER,
- CM_DREQ_COUNTER,
- CM_DREP_COUNTER,
- CM_SIDR_REQ_COUNTER,
- CM_SIDR_REP_COUNTER,
- CM_LAP_COUNTER,
- CM_APR_COUNTER,
- CM_ATTR_COUNT,
- CM_ATTR_ID_OFFSET = 0x0010,
-};
-
-enum {
- CM_XMIT,
- CM_XMIT_RETRIES,
- CM_RECV,
- CM_RECV_DUPLICATES,
- CM_COUNTER_GROUPS
-};
-
-static char const counter_group_names[CM_COUNTER_GROUPS]
- [sizeof("cm_rx_duplicates")] = {
- "cm_tx_msgs", "cm_tx_retries",
- "cm_rx_msgs", "cm_rx_duplicates"
-};
-
-struct cm_counter_group {
- struct kobject obj;
- atomic_long_t counter[CM_ATTR_COUNT];
-};
-
-struct cm_counter_attribute {
- struct attribute attr;
- int index;
-};
-
-#define CM_COUNTER_ATTR(_name, _index) \
-struct cm_counter_attribute cm_##_name##_counter_attr = { \
- .attr = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE }, \
- .index = _index \
-}
-
-static CM_COUNTER_ATTR(req, CM_REQ_COUNTER);
-static CM_COUNTER_ATTR(mra, CM_MRA_COUNTER);
-static CM_COUNTER_ATTR(rej, CM_REJ_COUNTER);
-static CM_COUNTER_ATTR(rep, CM_REP_COUNTER);
-static CM_COUNTER_ATTR(rtu, CM_RTU_COUNTER);
-static CM_COUNTER_ATTR(dreq, CM_DREQ_COUNTER);
-static CM_COUNTER_ATTR(drep, CM_DREP_COUNTER);
-static CM_COUNTER_ATTR(sidr_req, CM_SIDR_REQ_COUNTER);
-static CM_COUNTER_ATTR(sidr_rep, CM_SIDR_REP_COUNTER);
-static CM_COUNTER_ATTR(lap, CM_LAP_COUNTER);
-static CM_COUNTER_ATTR(apr, CM_APR_COUNTER);
-
-static struct attribute *cm_counter_default_attrs[] = {
- &cm_req_counter_attr.attr,
- &cm_mra_counter_attr.attr,
- &cm_rej_counter_attr.attr,
- &cm_rep_counter_attr.attr,
- &cm_rtu_counter_attr.attr,
- &cm_dreq_counter_attr.attr,
- &cm_drep_counter_attr.attr,
- &cm_sidr_req_counter_attr.attr,
- &cm_sidr_rep_counter_attr.attr,
- &cm_lap_counter_attr.attr,
- &cm_apr_counter_attr.attr,
- NULL
-};
-
struct cm_port {
struct cm_device *cm_dev;
struct ib_mad_agent *mad_agent;
- struct kobject port_obj;
u8 port_num;
- struct cm_counter_group counter_group[CM_COUNTER_GROUPS];
};
struct cm_device {
struct list_head list;
struct ib_device *device;
- struct kobject dev_obj;
u8 ack_delay;
- struct cm_port *port[0];
+ struct cm_port port[0];
};
struct cm_av {
@@ -357,7 +278,7 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
list_for_each_entry(cm_dev, &cm.device_list, list) {
if (!ib_find_cached_gid(cm_dev->device, &path->sgid,
&p, NULL)) {
- port = cm_dev->port[p-1];
+ port = &cm_dev->port[p-1];
break;
}
}
@@ -1349,9 +1270,6 @@ static void cm_dup_req_handler(struct cm_work *work,
struct ib_mad_send_buf *msg = NULL;
int ret;
- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
- counter[CM_REQ_COUNTER]);
-
/* Quick state check to discard duplicate REQs. */
if (cm_id_priv->id.state == IB_CM_REQ_RCVD)
return;
@@ -1698,8 +1616,6 @@ static void cm_dup_rep_handler(struct cm_work *work)
if (!cm_id_priv)
return;
- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
- counter[CM_REP_COUNTER]);
ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg);
if (ret)
goto deref;
@@ -1865,8 +1781,6 @@ static int cm_rtu_handler(struct cm_work *work)
if (cm_id_priv->id.state != IB_CM_REP_SENT &&
cm_id_priv->id.state != IB_CM_MRA_REP_RCVD) {
spin_unlock_irq(&cm_id_priv->lock);
- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
- counter[CM_RTU_COUNTER]);
goto out;
}
cm_id_priv->id.state = IB_CM_ESTABLISHED;
@@ -2044,8 +1958,6 @@ static int cm_dreq_handler(struct cm_work *work)
cm_id_priv = cm_acquire_id(dreq_msg->remote_comm_id,
dreq_msg->local_comm_id);
if (!cm_id_priv) {
- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
- counter[CM_DREQ_COUNTER]);
cm_issue_drep(work->port, work->mad_recv_wc);
return -EINVAL;
}
@@ -2065,8 +1977,6 @@ static int cm_dreq_handler(struct cm_work *work)
case IB_CM_MRA_REP_RCVD:
break;
case IB_CM_TIMEWAIT:
- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
- counter[CM_DREQ_COUNTER]);
if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg))
goto unlock;
@@ -2078,10 +1988,6 @@ static int cm_dreq_handler(struct cm_work *work)
if (ib_post_send_mad(msg, NULL))
cm_free_msg(msg);
goto deref;
- case IB_CM_DREQ_RCVD:
- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
- counter[CM_DREQ_COUNTER]);
- goto unlock;
default:
goto unlock;
}
@@ -2433,20 +2339,10 @@ static int cm_mra_handler(struct cm_work *work)
if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_OTHER ||
cm_id_priv->id.lap_state != IB_CM_LAP_SENT ||
ib_modify_mad(cm_id_priv->av.port->mad_agent,
- cm_id_priv->msg, timeout)) {
- if (cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD)
- atomic_long_inc(&work->port->
- counter_group[CM_RECV_DUPLICATES].
- counter[CM_MRA_COUNTER]);
+ cm_id_priv->msg, timeout))
goto out;
- }
cm_id_priv->id.lap_state = IB_CM_MRA_LAP_RCVD;
break;
- case IB_CM_MRA_REQ_RCVD:
- case IB_CM_MRA_REP_RCVD:
- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
- counter[CM_MRA_COUNTER]);
- /* fall through */
default:
goto out;
}
@@ -2606,8 +2502,6 @@ static int cm_lap_handler(struct cm_work *work)
case IB_CM_LAP_IDLE:
break;
case IB_CM_MRA_LAP_SENT:
- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
- counter[CM_LAP_COUNTER]);
if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg))
goto unlock;
@@ -2621,10 +2515,6 @@ static int cm_lap_handler(struct cm_work *work)
if (ib_post_send_mad(msg, NULL))
cm_free_msg(msg);
goto deref;
- case IB_CM_LAP_RCVD:
- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
- counter[CM_LAP_COUNTER]);
- goto unlock;
default:
goto unlock;
}
@@ -2906,8 +2796,6 @@ static int cm_sidr_req_handler(struct cm_work *work)
cur_cm_id_priv = cm_insert_remote_sidr(cm_id_priv);
if (cur_cm_id_priv) {
spin_unlock_irq(&cm.lock);
- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
- counter[CM_SIDR_REQ_COUNTER]);
goto out; /* Duplicate message. */
}
cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
@@ -3102,27 +2990,6 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent,
struct ib_mad_send_wc *mad_send_wc)
{
struct ib_mad_send_buf *msg = mad_send_wc->send_buf;
- struct cm_port *port;
- u16 attr_index;
-
- port = mad_agent->context;
- attr_index = be16_to_cpu(((struct ib_mad_hdr *)
- msg->mad)->attr_id) - CM_ATTR_ID_OFFSET;
-
- /*
- * If the send was in response to a received message (context[0] is not
- * set to a cm_id), and is not a REJ, then it is a send that was
- * manually retried.
- */
- if (!msg->context[0] && (attr_index != CM_REJ_COUNTER))
- msg->retries = 1;
-
- atomic_long_add(1 + msg->retries,
- &port->counter_group[CM_XMIT].counter[attr_index]);
- if (msg->retries)
- atomic_long_add(msg->retries,
- &port->counter_group[CM_XMIT_RETRIES].
- counter[attr_index]);
switch (mad_send_wc->status) {
case IB_WC_SUCCESS:
@@ -3281,10 +3148,8 @@ EXPORT_SYMBOL(ib_cm_notify);
static void cm_recv_handler(struct ib_mad_agent *mad_agent,
struct ib_mad_recv_wc *mad_recv_wc)
{
- struct cm_port *port = mad_agent->context;
struct cm_work *work;
enum ib_cm_event_type event;
- u16 attr_id;
int paths = 0;
switch (mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) {
@@ -3329,10 +3194,6 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent,
return;
}
- attr_id = be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id);
- atomic_long_inc(&port->counter_group[CM_RECV].
- counter[attr_id - CM_ATTR_ID_OFFSET]);
-
work = kmalloc(sizeof *work + sizeof(struct ib_sa_path_rec) * paths,
GFP_KERNEL);
if (!work) {
@@ -3343,7 +3204,7 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent,
INIT_DELAYED_WORK(&work->work, cm_work_handler);
work->cm_event.event = event;
work->mad_recv_wc = mad_recv_wc;
- work->port = port;
+ work->port = (struct cm_port *)mad_agent->context;
queue_delayed_work(cm.wq, &work->work, 0);
}
@@ -3518,108 +3379,6 @@ static void cm_get_ack_delay(struct cm_device *cm_dev)
cm_dev->ack_delay = attr.local_ca_ack_delay;
}
-static ssize_t cm_show_counter(struct kobject *obj, struct attribute *attr,
- char *buf)
-{
- struct cm_counter_group *group;
- struct cm_counter_attribute *cm_attr;
-
- group = container_of(obj, struct cm_counter_group, obj);
- cm_attr = container_of(attr, struct cm_counter_attribute, attr);
-
- return sprintf(buf, "%ld\n",
- atomic_long_read(&group->counter[cm_attr->index]));
-}
-
-static struct sysfs_ops cm_counter_ops = {
- .show = cm_show_counter
-};
-
-static struct kobj_type cm_counter_obj_type = {
- .sysfs_ops = &cm_counter_ops,
- .default_attrs = cm_counter_default_attrs
-};
-
-static void cm_release_port_obj(struct kobject *obj)
-{
- struct cm_port *cm_port;
-
- printk(KERN_ERR "free cm port\n");
-
- cm_port = container_of(obj, struct cm_port, port_obj);
- kfree(cm_port);
-}
-
-static struct kobj_type cm_port_obj_type = {
- .release = cm_release_port_obj
-};
-
-static void cm_release_dev_obj(struct kobject *obj)
-{
- struct cm_device *cm_dev;
-
- printk(KERN_ERR "free cm dev\n");
-
- cm_dev = container_of(obj, struct cm_device, dev_obj);
- kfree(cm_dev);
-}
-
-static struct kobj_type cm_dev_obj_type = {
- .release = cm_release_dev_obj
-};
-
-struct class cm_class = {
- .name = "infiniband_cm",
-};
-EXPORT_SYMBOL(cm_class);
-
-static void cm_remove_fs_obj(struct kobject *obj)
-{
- kobject_put(obj->parent);
- kobject_put(obj);
-}
-
-static int cm_create_port_fs(struct cm_port *port)
-{
- int i, ret;
-
- ret = kobject_init_and_add(&port->port_obj, &cm_port_obj_type,
- kobject_get(&port->cm_dev->dev_obj),
- "%d", port->port_num);
- if (ret) {
- kfree(port);
- return ret;
- }
-
- for (i = 0; i < CM_COUNTER_GROUPS; i++) {
- ret = kobject_init_and_add(&port->counter_group[i].obj,
- &cm_counter_obj_type,
- kobject_get(&port->port_obj),
- "%s", counter_group_names[i]);
- if (ret)
- goto error;
- }
-
- return 0;
-
-error:
- while (i--)
- cm_remove_fs_obj(&port->counter_group[i].obj);
- cm_remove_fs_obj(&port->port_obj);
- return ret;
-
-}
-
-static void cm_remove_port_fs(struct cm_port *port)
-{
- int i;
-
- for (i = 0; i < CM_COUNTER_GROUPS; i++)
- cm_remove_fs_obj(&port->counter_group[i].obj);
-
- cm_remove_fs_obj(&port->port_obj);
-}
-
static void cm_add_one(struct ib_device *device)
{
struct cm_device *cm_dev;
@@ -3638,7 +3397,7 @@ static void cm_add_one(struct ib_device *device)
if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
return;
- cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) *
+ cm_dev = kmalloc(sizeof(*cm_dev) + sizeof(*port) *
device->phys_port_cnt, GFP_KERNEL);
if (!cm_dev)
return;
@@ -3646,27 +3405,11 @@ static void cm_add_one(struct ib_device *device)
cm_dev->device = device;
cm_get_ack_delay(cm_dev);
- ret = kobject_init_and_add(&cm_dev->dev_obj, &cm_dev_obj_type,
- &cm_class.subsys.kobj, "%s", device->name);
- if (ret) {
- kfree(cm_dev);
- return;
- }
-
set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
for (i = 1; i <= device->phys_port_cnt; i++) {
- port = kzalloc(sizeof *port, GFP_KERNEL);
- if (!port)
- goto error1;
-
- cm_dev->port[i-1] = port;
+ port = &cm_dev->port[i-1];
port->cm_dev = cm_dev;
port->port_num = i;
-
- ret = cm_create_port_fs(port);
- if (ret)
- goto error1;
-
port->mad_agent = ib_register_mad_agent(device, i,
IB_QPT_GSI,
®_req,
@@ -3675,11 +3418,11 @@ static void cm_add_one(struct ib_device *device)
cm_recv_handler,
port);
if (IS_ERR(port->mad_agent))
- goto error2;
+ goto error1;
ret = ib_modify_port(device, i, 0, &port_modify);
if (ret)
- goto error3;
+ goto error2;
}
ib_set_client_data(device, &cm_client, cm_dev);
@@ -3688,20 +3431,17 @@ static void cm_add_one(struct ib_device *device)
write_unlock_irqrestore(&cm.device_lock, flags);
return;
-error3:
- ib_unregister_mad_agent(port->mad_agent);
error2:
- cm_remove_port_fs(port);
+ ib_unregister_mad_agent(port->mad_agent);
error1:
port_modify.set_port_cap_mask = 0;
port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
while (--i) {
- port = cm_dev->port[i-1];
+ port = &cm_dev->port[i-1];
ib_modify_port(device, port->port_num, 0, &port_modify);
ib_unregister_mad_agent(port->mad_agent);
- cm_remove_port_fs(port);
}
- cm_remove_fs_obj(&cm_dev->dev_obj);
+ kfree(cm_dev);
}
static void cm_remove_one(struct ib_device *device)
@@ -3723,12 +3463,11 @@ static void cm_remove_one(struct ib_device *device)
write_unlock_irqrestore(&cm.device_lock, flags);
for (i = 1; i <= device->phys_port_cnt; i++) {
- port = cm_dev->port[i-1];
+ port = &cm_dev->port[i-1];
ib_modify_port(device, port->port_num, 0, &port_modify);
ib_unregister_mad_agent(port->mad_agent);
- cm_remove_port_fs(port);
}
- cm_remove_fs_obj(&cm_dev->dev_obj);
+ kfree(cm_dev);
}
static int __init ib_cm_init(void)
@@ -3749,25 +3488,17 @@ static int __init ib_cm_init(void)
idr_pre_get(&cm.local_id_table, GFP_KERNEL);
INIT_LIST_HEAD(&cm.timewait_list);
- ret = class_register(&cm_class);
- if (ret)
- return -ENOMEM;
-
cm.wq = create_workqueue("ib_cm");
- if (!cm.wq) {
- ret = -ENOMEM;
- goto error1;
- }
+ if (!cm.wq)
+ return -ENOMEM;
ret = ib_register_client(&cm_client);
if (ret)
- goto error2;
+ goto error;
return 0;
-error2:
+error:
destroy_workqueue(cm.wq);
-error1:
- class_unregister(&cm_class);
return ret;
}
@@ -3788,7 +3519,6 @@ static void __exit ib_cm_cleanup(void)
}
ib_unregister_client(&cm_client);
- class_unregister(&cm_class);
idr_destroy(&cm.local_id_table);
}
diff --git a/trunk/drivers/infiniband/core/cma.c b/trunk/drivers/infiniband/core/cma.c
index 637efead97a0..0751697ef984 100644
--- a/trunk/drivers/infiniband/core/cma.c
+++ b/trunk/drivers/infiniband/core/cma.c
@@ -488,8 +488,7 @@ void rdma_destroy_qp(struct rdma_cm_id *id)
}
EXPORT_SYMBOL(rdma_destroy_qp);
-static int cma_modify_qp_rtr(struct rdma_id_private *id_priv,
- struct rdma_conn_param *conn_param)
+static int cma_modify_qp_rtr(struct rdma_id_private *id_priv)
{
struct ib_qp_attr qp_attr;
int qp_attr_mask, ret;
@@ -515,16 +514,13 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv,
if (ret)
goto out;
- if (conn_param)
- qp_attr.max_dest_rd_atomic = conn_param->responder_resources;
ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
out:
mutex_unlock(&id_priv->qp_mutex);
return ret;
}
-static int cma_modify_qp_rts(struct rdma_id_private *id_priv,
- struct rdma_conn_param *conn_param)
+static int cma_modify_qp_rts(struct rdma_id_private *id_priv)
{
struct ib_qp_attr qp_attr;
int qp_attr_mask, ret;
@@ -540,8 +536,6 @@ static int cma_modify_qp_rts(struct rdma_id_private *id_priv,
if (ret)
goto out;
- if (conn_param)
- qp_attr.max_rd_atomic = conn_param->initiator_depth;
ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
out:
mutex_unlock(&id_priv->qp_mutex);
@@ -872,11 +866,11 @@ static int cma_rep_recv(struct rdma_id_private *id_priv)
{
int ret;
- ret = cma_modify_qp_rtr(id_priv, NULL);
+ ret = cma_modify_qp_rtr(id_priv);
if (ret)
goto reject;
- ret = cma_modify_qp_rts(id_priv, NULL);
+ ret = cma_modify_qp_rts(id_priv);
if (ret)
goto reject;
@@ -1128,10 +1122,8 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
cm_id->cm_handler = cma_ib_handler;
ret = conn_id->id.event_handler(&conn_id->id, &event);
- if (!ret) {
- cma_enable_remove(conn_id);
+ if (!ret)
goto out;
- }
/* Destroy the CM ID by returning a non-zero value. */
conn_id->cm_id.ib = NULL;
@@ -1270,7 +1262,6 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
struct net_device *dev = NULL;
struct rdma_cm_event event;
int ret;
- struct ib_device_attr attr;
listen_id = cm_id->context;
if (cma_disable_remove(listen_id, CMA_LISTEN))
@@ -1320,19 +1311,10 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
sin = (struct sockaddr_in *) &new_cm_id->route.addr.dst_addr;
*sin = iw_event->remote_addr;
- ret = ib_query_device(conn_id->id.device, &attr);
- if (ret) {
- cma_enable_remove(conn_id);
- rdma_destroy_id(new_cm_id);
- goto out;
- }
-
memset(&event, 0, sizeof event);
event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
event.param.conn.private_data = iw_event->private_data;
event.param.conn.private_data_len = iw_event->private_data_len;
- event.param.conn.initiator_depth = attr.max_qp_init_rd_atom;
- event.param.conn.responder_resources = attr.max_qp_rd_atom;
ret = conn_id->id.event_handler(&conn_id->id, &event);
if (ret) {
/* User wants to destroy the CM ID */
@@ -2290,7 +2272,7 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
sin = (struct sockaddr_in*) &id_priv->id.route.addr.dst_addr;
cm_id->remote_addr = *sin;
- ret = cma_modify_qp_rtr(id_priv, conn_param);
+ ret = cma_modify_qp_rtr(id_priv);
if (ret)
goto out;
@@ -2353,15 +2335,25 @@ static int cma_accept_ib(struct rdma_id_private *id_priv,
struct rdma_conn_param *conn_param)
{
struct ib_cm_rep_param rep;
- int ret;
+ struct ib_qp_attr qp_attr;
+ int qp_attr_mask, ret;
- ret = cma_modify_qp_rtr(id_priv, conn_param);
- if (ret)
- goto out;
+ if (id_priv->id.qp) {
+ ret = cma_modify_qp_rtr(id_priv);
+ if (ret)
+ goto out;
- ret = cma_modify_qp_rts(id_priv, conn_param);
- if (ret)
- goto out;
+ qp_attr.qp_state = IB_QPS_RTS;
+ ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, &qp_attr,
+ &qp_attr_mask);
+ if (ret)
+ goto out;
+
+ qp_attr.max_rd_atomic = conn_param->initiator_depth;
+ ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
+ if (ret)
+ goto out;
+ }
memset(&rep, 0, sizeof rep);
rep.qp_num = id_priv->qp_num;
@@ -2386,7 +2378,7 @@ static int cma_accept_iw(struct rdma_id_private *id_priv,
struct iw_cm_conn_param iw_param;
int ret;
- ret = cma_modify_qp_rtr(id_priv, conn_param);
+ ret = cma_modify_qp_rtr(id_priv);
if (ret)
return ret;
@@ -2606,9 +2598,11 @@ static void cma_set_mgid(struct rdma_id_private *id_priv,
/* IPv6 address is an SA assigned MGID. */
memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
} else {
- ip_ib_mc_map(sin->sin_addr.s_addr, dev_addr->broadcast, mc_map);
+ ip_ib_mc_map(sin->sin_addr.s_addr, mc_map);
if (id_priv->id.ps == RDMA_PS_UDP)
mc_map[7] = 0x01; /* Use RDMA CM signature */
+ mc_map[8] = ib_addr_get_pkey(dev_addr) >> 8;
+ mc_map[9] = (unsigned char) ib_addr_get_pkey(dev_addr);
*mgid = *(union ib_gid *) (mc_map + 4);
}
}
diff --git a/trunk/drivers/infiniband/core/fmr_pool.c b/trunk/drivers/infiniband/core/fmr_pool.c
index 6c7aa59794d4..e8d5f6b64998 100644
--- a/trunk/drivers/infiniband/core/fmr_pool.c
+++ b/trunk/drivers/infiniband/core/fmr_pool.c
@@ -139,7 +139,7 @@ static inline struct ib_pool_fmr *ib_fmr_cache_lookup(struct ib_fmr_pool *pool,
static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
{
int ret;
- struct ib_pool_fmr *fmr, *next;
+ struct ib_pool_fmr *fmr;
LIST_HEAD(unmap_list);
LIST_HEAD(fmr_list);
@@ -158,20 +158,6 @@ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
#endif
}
- /*
- * The free_list may hold FMRs that have been put there
- * because they haven't reached the max_remap count.
- * Invalidate their mapping as well.
- */
- list_for_each_entry_safe(fmr, next, &pool->free_list, list) {
- if (fmr->remap_count == 0)
- continue;
- hlist_del_init(&fmr->cache_node);
- fmr->remap_count = 0;
- list_add_tail(&fmr->fmr->list, &fmr_list);
- list_move(&fmr->list, &unmap_list);
- }
-
list_splice(&pool->dirty_list, &unmap_list);
INIT_LIST_HEAD(&pool->dirty_list);
pool->dirty_len = 0;
@@ -196,7 +182,8 @@ static int ib_fmr_cleanup_thread(void *pool_ptr)
struct ib_fmr_pool *pool = pool_ptr;
do {
- if (atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) < 0) {
+ if (pool->dirty_len >= pool->dirty_watermark ||
+ atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) < 0) {
ib_fmr_batch_release(pool);
atomic_inc(&pool->flush_ser);
@@ -207,7 +194,8 @@ static int ib_fmr_cleanup_thread(void *pool_ptr)
}
set_current_state(TASK_INTERRUPTIBLE);
- if (atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) >= 0 &&
+ if (pool->dirty_len < pool->dirty_watermark &&
+ atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) >= 0 &&
!kthread_should_stop())
schedule();
__set_current_state(TASK_RUNNING);
@@ -381,6 +369,11 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
i = 0;
list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) {
+ if (fmr->remap_count) {
+ INIT_LIST_HEAD(&fmr_list);
+ list_add_tail(&fmr->fmr->list, &fmr_list);
+ ib_unmap_fmr(&fmr_list);
+ }
ib_dealloc_fmr(fmr->fmr);
list_del(&fmr->list);
kfree(fmr);
@@ -518,10 +511,8 @@ int ib_fmr_pool_unmap(struct ib_pool_fmr *fmr)
list_add_tail(&fmr->list, &pool->free_list);
} else {
list_add_tail(&fmr->list, &pool->dirty_list);
- if (++pool->dirty_len >= pool->dirty_watermark) {
- atomic_inc(&pool->req_ser);
- wake_up_process(pool->thread);
- }
+ ++pool->dirty_len;
+ wake_up_process(pool->thread);
}
}
diff --git a/trunk/drivers/infiniband/core/mad.c b/trunk/drivers/infiniband/core/mad.c
index fbe16d5250a4..6f4287716ab1 100644
--- a/trunk/drivers/infiniband/core/mad.c
+++ b/trunk/drivers/infiniband/core/mad.c
@@ -701,8 +701,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
}
/* Check to post send on QP or process locally */
- if (smi_check_local_smp(smp, device) == IB_SMI_DISCARD &&
- smi_check_local_returning_smp(smp, device) == IB_SMI_DISCARD)
+ if (smi_check_local_smp(smp, device) == IB_SMI_DISCARD)
goto out;
local = kmalloc(sizeof *local, GFP_ATOMIC);
@@ -753,7 +752,8 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
port_priv = ib_get_mad_port(mad_agent_priv->agent.device,
mad_agent_priv->agent.port_num);
if (port_priv) {
- memcpy(&mad_priv->mad.mad, smp, sizeof(struct ib_mad));
+ mad_priv->mad.mad.mad_hdr.tid =
+ ((struct ib_mad *)smp)->mad_hdr.tid;
recv_mad_agent = find_mad_agent(port_priv,
&mad_priv->mad.mad);
}
@@ -1100,9 +1100,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
mad_send_wr->tid = ((struct ib_mad_hdr *) send_buf->mad)->tid;
/* Timeout will be updated after send completes */
mad_send_wr->timeout = msecs_to_jiffies(send_buf->timeout_ms);
- mad_send_wr->max_retries = send_buf->retries;
- mad_send_wr->retries_left = send_buf->retries;
- send_buf->retries = 0;
+ mad_send_wr->retries = send_buf->retries;
/* Reference for work request to QP + response */
mad_send_wr->refcount = 1 + (mad_send_wr->timeout > 0);
mad_send_wr->status = IB_WC_SUCCESS;
@@ -1933,6 +1931,15 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv,
if (port_priv->device->process_mad) {
int ret;
+ if (!response) {
+ printk(KERN_ERR PFX "No memory for response MAD\n");
+ /*
+ * Is it better to assume that
+ * it wouldn't be processed ?
+ */
+ goto out;
+ }
+
ret = port_priv->device->process_mad(port_priv->device, 0,
port_priv->port_num,
wc, &recv->grh,
@@ -2275,6 +2282,8 @@ static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv)
/* Empty wait list to prevent receives from finding a request */
list_splice_init(&mad_agent_priv->wait_list, &cancel_list);
+ /* Empty local completion list as well */
+ list_splice_init(&mad_agent_priv->local_list, &cancel_list);
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
/* Report all cancelled requests */
@@ -2436,12 +2445,9 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr)
{
int ret;
- if (!mad_send_wr->retries_left)
+ if (!mad_send_wr->retries--)
return -ETIMEDOUT;
- mad_send_wr->retries_left--;
- mad_send_wr->send_buf.retries++;
-
mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
if (mad_send_wr->mad_agent_priv->agent.rmpp_version) {
diff --git a/trunk/drivers/infiniband/core/mad_priv.h b/trunk/drivers/infiniband/core/mad_priv.h
index 8b75010016ec..9be5cc00a3a9 100644
--- a/trunk/drivers/infiniband/core/mad_priv.h
+++ b/trunk/drivers/infiniband/core/mad_priv.h
@@ -131,8 +131,7 @@ struct ib_mad_send_wr_private {
struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
__be64 tid;
unsigned long timeout;
- int max_retries;
- int retries_left;
+ int retries;
int retry;
int refcount;
enum ib_wc_status status;
diff --git a/trunk/drivers/infiniband/core/mad_rmpp.c b/trunk/drivers/infiniband/core/mad_rmpp.c
index a5e2a310f312..d43bc62005b3 100644
--- a/trunk/drivers/infiniband/core/mad_rmpp.c
+++ b/trunk/drivers/infiniband/core/mad_rmpp.c
@@ -684,7 +684,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
if (seg_num > mad_send_wr->last_ack) {
adjust_last_ack(mad_send_wr, seg_num);
- mad_send_wr->retries_left = mad_send_wr->max_retries;
+ mad_send_wr->retries = mad_send_wr->send_buf.retries;
}
mad_send_wr->newwin = newwin;
if (mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) {
diff --git a/trunk/drivers/infiniband/core/multicast.c b/trunk/drivers/infiniband/core/multicast.c
index 107f170c57cd..1bc1fe605282 100644
--- a/trunk/drivers/infiniband/core/multicast.c
+++ b/trunk/drivers/infiniband/core/multicast.c
@@ -73,20 +73,11 @@ struct mcast_device {
};
enum mcast_state {
+ MCAST_IDLE,
MCAST_JOINING,
MCAST_MEMBER,
- MCAST_ERROR,
-};
-
-enum mcast_group_state {
- MCAST_IDLE,
MCAST_BUSY,
- MCAST_GROUP_ERROR,
- MCAST_PKEY_EVENT
-};
-
-enum {
- MCAST_INVALID_PKEY_INDEX = 0xFFFF
+ MCAST_ERROR
};
struct mcast_member;
@@ -102,10 +93,9 @@ struct mcast_group {
struct mcast_member *last_join;
int members[3];
atomic_t refcount;
- enum mcast_group_state state;
+ enum mcast_state state;
struct ib_sa_query *query;
int query_id;
- u16 pkey_index;
};
struct mcast_member {
@@ -388,19 +378,9 @@ static int fail_join(struct mcast_group *group, struct mcast_member *member,
static void process_group_error(struct mcast_group *group)
{
struct mcast_member *member;
- int ret = 0;
- u16 pkey_index;
-
- if (group->state == MCAST_PKEY_EVENT)
- ret = ib_find_pkey(group->port->dev->device,
- group->port->port_num,
- be16_to_cpu(group->rec.pkey), &pkey_index);
+ int ret;
spin_lock_irq(&group->lock);
- if (group->state == MCAST_PKEY_EVENT && !ret &&
- group->pkey_index == pkey_index)
- goto out;
-
while (!list_empty(&group->active_list)) {
member = list_entry(group->active_list.next,
struct mcast_member, list);
@@ -419,7 +399,6 @@ static void process_group_error(struct mcast_group *group)
}
group->rec.join_state = 0;
-out:
group->state = MCAST_BUSY;
spin_unlock_irq(&group->lock);
}
@@ -436,9 +415,9 @@ static void mcast_work_handler(struct work_struct *work)
retest:
spin_lock_irq(&group->lock);
while (!list_empty(&group->pending_list) ||
- (group->state != MCAST_BUSY)) {
+ (group->state == MCAST_ERROR)) {
- if (group->state != MCAST_BUSY) {
+ if (group->state == MCAST_ERROR) {
spin_unlock_irq(&group->lock);
process_group_error(group);
goto retest;
@@ -515,19 +494,12 @@ static void join_handler(int status, struct ib_sa_mcmember_rec *rec,
void *context)
{
struct mcast_group *group = context;
- u16 pkey_index = MCAST_INVALID_PKEY_INDEX;
if (status)
process_join_error(group, status);
else {
- ib_find_pkey(group->port->dev->device, group->port->port_num,
- be16_to_cpu(rec->pkey), &pkey_index);
-
spin_lock_irq(&group->port->lock);
group->rec = *rec;
- if (group->state == MCAST_BUSY &&
- group->pkey_index == MCAST_INVALID_PKEY_INDEX)
- group->pkey_index = pkey_index;
if (!memcmp(&mgid0, &group->rec.mgid, sizeof mgid0)) {
rb_erase(&group->node, &group->port->table);
mcast_insert(group->port, group, 1);
@@ -567,7 +539,6 @@ static struct mcast_group *acquire_group(struct mcast_port *port,
group->port = port;
group->rec.mgid = *mgid;
- group->pkey_index = MCAST_INVALID_PKEY_INDEX;
INIT_LIST_HEAD(&group->pending_list);
INIT_LIST_HEAD(&group->active_list);
INIT_WORK(&group->work, mcast_work_handler);
@@ -736,8 +707,7 @@ int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
}
EXPORT_SYMBOL(ib_init_ah_from_mcmember);
-static void mcast_groups_event(struct mcast_port *port,
- enum mcast_group_state state)
+static void mcast_groups_lost(struct mcast_port *port)
{
struct mcast_group *group;
struct rb_node *node;
@@ -751,8 +721,7 @@ static void mcast_groups_event(struct mcast_port *port,
atomic_inc(&group->refcount);
queue_work(mcast_wq, &group->work);
}
- if (group->state != MCAST_GROUP_ERROR)
- group->state = state;
+ group->state = MCAST_ERROR;
spin_unlock(&group->lock);
}
spin_unlock_irqrestore(&port->lock, flags);
@@ -762,20 +731,16 @@ static void mcast_event_handler(struct ib_event_handler *handler,
struct ib_event *event)
{
struct mcast_device *dev;
- int index;
dev = container_of(handler, struct mcast_device, event_handler);
- index = event->element.port_num - dev->start_port;
switch (event->event) {
case IB_EVENT_PORT_ERR:
case IB_EVENT_LID_CHANGE:
case IB_EVENT_SM_CHANGE:
case IB_EVENT_CLIENT_REREGISTER:
- mcast_groups_event(&dev->port[index], MCAST_GROUP_ERROR);
- break;
- case IB_EVENT_PKEY_CHANGE:
- mcast_groups_event(&dev->port[index], MCAST_PKEY_EVENT);
+ mcast_groups_lost(&dev->port[event->element.port_num -
+ dev->start_port]);
break;
default:
break;
diff --git a/trunk/drivers/infiniband/core/smi.h b/trunk/drivers/infiniband/core/smi.h
index aff96bac49b4..1cfc2984434f 100644
--- a/trunk/drivers/infiniband/core/smi.h
+++ b/trunk/drivers/infiniband/core/smi.h
@@ -59,8 +59,7 @@ extern enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
u8 node_type, int port_num);
/*
- * Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM
- * via process_mad
+ * Return 1 if the SMP should be handled by the local SMA/SM via process_mad
*/
static inline enum smi_action smi_check_local_smp(struct ib_smp *smp,
struct ib_device *device)
@@ -72,19 +71,4 @@ static inline enum smi_action smi_check_local_smp(struct ib_smp *smp,
(smp->hop_ptr == smp->hop_cnt + 1)) ?
IB_SMI_HANDLE : IB_SMI_DISCARD);
}
-
-/*
- * Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM
- * via process_mad
- */
-static inline enum smi_action smi_check_local_returning_smp(struct ib_smp *smp,
- struct ib_device *device)
-{
- /* C14-13:3 -- We're at the end of the DR segment of path */
- /* C14-13:4 -- Hop Pointer == 0 -> give to SM */
- return ((device->process_mad &&
- ib_get_smp_direction(smp) &&
- !smp->hop_ptr) ? IB_SMI_HANDLE : IB_SMI_DISCARD);
-}
-
#endif /* __SMI_H_ */
diff --git a/trunk/drivers/infiniband/core/ucm.c b/trunk/drivers/infiniband/core/ucm.c
index 4291ab42a5b9..424983f5b1ee 100644
--- a/trunk/drivers/infiniband/core/ucm.c
+++ b/trunk/drivers/infiniband/core/ucm.c
@@ -106,9 +106,6 @@ enum {
IB_UCM_MAX_DEVICES = 32
};
-/* ib_cm and ib_user_cm modules share /sys/class/infiniband_cm */
-extern struct class cm_class;
-
#define IB_UCM_BASE_DEV MKDEV(IB_UCM_MAJOR, IB_UCM_BASE_MINOR)
static void ib_ucm_add_one(struct ib_device *device);
@@ -1202,7 +1199,7 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
return 0;
}
-static void ucm_release_class_dev(struct class_device *class_dev)
+static void ib_ucm_release_class_dev(struct class_device *class_dev)
{
struct ib_ucm_device *dev;
@@ -1220,6 +1217,11 @@ static const struct file_operations ucm_fops = {
.poll = ib_ucm_poll,
};
+static struct class ucm_class = {
+ .name = "infiniband_cm",
+ .release = ib_ucm_release_class_dev
+};
+
static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
{
struct ib_ucm_device *dev;
@@ -1255,10 +1257,9 @@ static void ib_ucm_add_one(struct ib_device *device)
if (cdev_add(&ucm_dev->dev, IB_UCM_BASE_DEV + ucm_dev->devnum, 1))
goto err;
- ucm_dev->class_dev.class = &cm_class;
+ ucm_dev->class_dev.class = &ucm_class;
ucm_dev->class_dev.dev = device->dma_device;
ucm_dev->class_dev.devt = ucm_dev->dev.dev;
- ucm_dev->class_dev.release = ucm_release_class_dev;
snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d",
ucm_dev->devnum);
if (class_device_register(&ucm_dev->class_dev))
@@ -1305,34 +1306,40 @@ static int __init ib_ucm_init(void)
"infiniband_cm");
if (ret) {
printk(KERN_ERR "ucm: couldn't register device number\n");
- goto error1;
+ goto err;
}
- ret = class_create_file(&cm_class, &class_attr_abi_version);
+ ret = class_register(&ucm_class);
+ if (ret) {
+ printk(KERN_ERR "ucm: couldn't create class infiniband_cm\n");
+ goto err_chrdev;
+ }
+
+ ret = class_create_file(&ucm_class, &class_attr_abi_version);
if (ret) {
printk(KERN_ERR "ucm: couldn't create abi_version attribute\n");
- goto error2;
+ goto err_class;
}
ret = ib_register_client(&ucm_client);
if (ret) {
printk(KERN_ERR "ucm: couldn't register client\n");
- goto error3;
+ goto err_class;
}
return 0;
-error3:
- class_remove_file(&cm_class, &class_attr_abi_version);
-error2:
+err_class:
+ class_unregister(&ucm_class);
+err_chrdev:
unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
-error1:
+err:
return ret;
}
static void __exit ib_ucm_cleanup(void)
{
ib_unregister_client(&ucm_client);
- class_remove_file(&cm_class, &class_attr_abi_version);
+ class_unregister(&ucm_class);
unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
idr_destroy(&ctx_id_table);
}
diff --git a/trunk/drivers/infiniband/core/ucma.c b/trunk/drivers/infiniband/core/ucma.c
index 15937eb38aae..90d675ad9ec8 100644
--- a/trunk/drivers/infiniband/core/ucma.c
+++ b/trunk/drivers/infiniband/core/ucma.c
@@ -31,7 +31,6 @@
*/
#include
-#include
#include
#include
#include
@@ -992,96 +991,6 @@ static ssize_t ucma_leave_multicast(struct ucma_file *file,
return ret;
}
-static void ucma_lock_files(struct ucma_file *file1, struct ucma_file *file2)
-{
- /* Acquire mutex's based on pointer comparison to prevent deadlock. */
- if (file1 < file2) {
- mutex_lock(&file1->mut);
- mutex_lock(&file2->mut);
- } else {
- mutex_lock(&file2->mut);
- mutex_lock(&file1->mut);
- }
-}
-
-static void ucma_unlock_files(struct ucma_file *file1, struct ucma_file *file2)
-{
- if (file1 < file2) {
- mutex_unlock(&file2->mut);
- mutex_unlock(&file1->mut);
- } else {
- mutex_unlock(&file1->mut);
- mutex_unlock(&file2->mut);
- }
-}
-
-static void ucma_move_events(struct ucma_context *ctx, struct ucma_file *file)
-{
- struct ucma_event *uevent, *tmp;
-
- list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list)
- if (uevent->ctx == ctx)
- list_move_tail(&uevent->list, &file->event_list);
-}
-
-static ssize_t ucma_migrate_id(struct ucma_file *new_file,
- const char __user *inbuf,
- int in_len, int out_len)
-{
- struct rdma_ucm_migrate_id cmd;
- struct rdma_ucm_migrate_resp resp;
- struct ucma_context *ctx;
- struct file *filp;
- struct ucma_file *cur_file;
- int ret = 0;
-
- if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
- return -EFAULT;
-
- /* Get current fd to protect against it being closed */
- filp = fget(cmd.fd);
- if (!filp)
- return -ENOENT;
-
- /* Validate current fd and prevent destruction of id. */
- ctx = ucma_get_ctx(filp->private_data, cmd.id);
- if (IS_ERR(ctx)) {
- ret = PTR_ERR(ctx);
- goto file_put;
- }
-
- cur_file = ctx->file;
- if (cur_file == new_file) {
- resp.events_reported = ctx->events_reported;
- goto response;
- }
-
- /*
- * Migrate events between fd's, maintaining order, and avoiding new
- * events being added before existing events.
- */
- ucma_lock_files(cur_file, new_file);
- mutex_lock(&mut);
-
- list_move_tail(&ctx->list, &new_file->ctx_list);
- ucma_move_events(ctx, new_file);
- ctx->file = new_file;
- resp.events_reported = ctx->events_reported;
-
- mutex_unlock(&mut);
- ucma_unlock_files(cur_file, new_file);
-
-response:
- if (copy_to_user((void __user *)(unsigned long)cmd.response,
- &resp, sizeof(resp)))
- ret = -EFAULT;
-
- ucma_put_ctx(ctx);
-file_put:
- fput(filp);
- return ret;
-}
-
static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
const char __user *inbuf,
int in_len, int out_len) = {
@@ -1103,7 +1012,6 @@ static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
[RDMA_USER_CM_CMD_NOTIFY] = ucma_notify,
[RDMA_USER_CM_CMD_JOIN_MCAST] = ucma_join_multicast,
[RDMA_USER_CM_CMD_LEAVE_MCAST] = ucma_leave_multicast,
- [RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id
};
static ssize_t ucma_write(struct file *filp, const char __user *buf,
diff --git a/trunk/drivers/infiniband/core/user_mad.c b/trunk/drivers/infiniband/core/user_mad.c
index 4e915104ac4c..b53eac4611de 100644
--- a/trunk/drivers/infiniband/core/user_mad.c
+++ b/trunk/drivers/infiniband/core/user_mad.c
@@ -2,7 +2,6 @@
* Copyright (c) 2004 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Voltaire, Inc. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
- * Copyright (c) 2008 Cisco. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -43,7 +42,7 @@
#include
#include
#include
-#include
+#include
#include
#include
@@ -95,7 +94,7 @@ struct ib_umad_port {
struct class_device *sm_class_dev;
struct semaphore sm_sem;
- struct mutex file_mutex;
+ struct rw_semaphore mutex;
struct list_head file_list;
struct ib_device *ib_dev;
@@ -111,11 +110,11 @@ struct ib_umad_device {
};
struct ib_umad_file {
- struct mutex mutex;
struct ib_umad_port *port;
struct list_head recv_list;
struct list_head send_list;
struct list_head port_list;
+ spinlock_t recv_lock;
spinlock_t send_lock;
wait_queue_head_t recv_wait;
struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS];
@@ -157,7 +156,7 @@ static int hdr_size(struct ib_umad_file *file)
sizeof (struct ib_user_mad_hdr_old);
}
-/* caller must hold file->mutex */
+/* caller must hold port->mutex at least for reading */
static struct ib_mad_agent *__get_agent(struct ib_umad_file *file, int id)
{
return file->agents_dead ? NULL : file->agent[id];
@@ -169,30 +168,32 @@ static int queue_packet(struct ib_umad_file *file,
{
int ret = 1;
- mutex_lock(&file->mutex);
+ down_read(&file->port->mutex);
for (packet->mad.hdr.id = 0;
packet->mad.hdr.id < IB_UMAD_MAX_AGENTS;
packet->mad.hdr.id++)
if (agent == __get_agent(file, packet->mad.hdr.id)) {
+ spin_lock_irq(&file->recv_lock);
list_add_tail(&packet->list, &file->recv_list);
+ spin_unlock_irq(&file->recv_lock);
wake_up_interruptible(&file->recv_wait);
ret = 0;
break;
}
- mutex_unlock(&file->mutex);
+ up_read(&file->port->mutex);
return ret;
}
static void dequeue_send(struct ib_umad_file *file,
struct ib_umad_packet *packet)
-{
+ {
spin_lock_irq(&file->send_lock);
list_del(&packet->list);
spin_unlock_irq(&file->send_lock);
-}
+ }
static void send_handler(struct ib_mad_agent *agent,
struct ib_mad_send_wc *send_wc)
@@ -340,10 +341,10 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
if (count < hdr_size(file))
return -EINVAL;
- mutex_lock(&file->mutex);
+ spin_lock_irq(&file->recv_lock);
while (list_empty(&file->recv_list)) {
- mutex_unlock(&file->mutex);
+ spin_unlock_irq(&file->recv_lock);
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
@@ -352,13 +353,13 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
!list_empty(&file->recv_list)))
return -ERESTARTSYS;
- mutex_lock(&file->mutex);
+ spin_lock_irq(&file->recv_lock);
}
packet = list_entry(file->recv_list.next, struct ib_umad_packet, list);
list_del(&packet->list);
- mutex_unlock(&file->mutex);
+ spin_unlock_irq(&file->recv_lock);
if (packet->recv_wc)
ret = copy_recv_mad(file, buf, packet, count);
@@ -367,9 +368,9 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
if (ret < 0) {
/* Requeue packet */
- mutex_lock(&file->mutex);
+ spin_lock_irq(&file->recv_lock);
list_add(&packet->list, &file->recv_list);
- mutex_unlock(&file->mutex);
+ spin_unlock_irq(&file->recv_lock);
} else {
if (packet->recv_wc)
ib_free_recv_mad(packet->recv_wc);
@@ -480,7 +481,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
goto err;
}
- mutex_lock(&file->mutex);
+ down_read(&file->port->mutex);
agent = __get_agent(file, packet->mad.hdr.id);
if (!agent) {
@@ -576,7 +577,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
if (ret)
goto err_send;
- mutex_unlock(&file->mutex);
+ up_read(&file->port->mutex);
return count;
err_send:
@@ -586,7 +587,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
err_ah:
ib_destroy_ah(ah);
err_up:
- mutex_unlock(&file->mutex);
+ up_read(&file->port->mutex);
err:
kfree(packet);
return ret;
@@ -612,12 +613,11 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, void __user *arg,
{
struct ib_user_mad_reg_req ureq;
struct ib_mad_reg_req req;
- struct ib_mad_agent *agent = NULL;
+ struct ib_mad_agent *agent;
int agent_id;
int ret;
- mutex_lock(&file->port->file_mutex);
- mutex_lock(&file->mutex);
+ down_write(&file->port->mutex);
if (!file->port->ib_dev) {
ret = -EPIPE;
@@ -666,13 +666,13 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, void __user *arg,
send_handler, recv_handler, file);
if (IS_ERR(agent)) {
ret = PTR_ERR(agent);
- agent = NULL;
goto out;
}
if (put_user(agent_id,
(u32 __user *) (arg + offsetof(struct ib_user_mad_reg_req, id)))) {
ret = -EFAULT;
+ ib_unregister_mad_agent(agent);
goto out;
}
@@ -690,13 +690,7 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, void __user *arg,
ret = 0;
out:
- mutex_unlock(&file->mutex);
-
- if (ret && agent)
- ib_unregister_mad_agent(agent);
-
- mutex_unlock(&file->port->file_mutex);
-
+ up_write(&file->port->mutex);
return ret;
}
@@ -709,8 +703,7 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
if (get_user(id, arg))
return -EFAULT;
- mutex_lock(&file->port->file_mutex);
- mutex_lock(&file->mutex);
+ down_write(&file->port->mutex);
if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
ret = -EINVAL;
@@ -721,13 +714,11 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
file->agent[id] = NULL;
out:
- mutex_unlock(&file->mutex);
+ up_write(&file->port->mutex);
if (agent)
ib_unregister_mad_agent(agent);
- mutex_unlock(&file->port->file_mutex);
-
return ret;
}
@@ -735,12 +726,12 @@ static long ib_umad_enable_pkey(struct ib_umad_file *file)
{
int ret = 0;
- mutex_lock(&file->mutex);
+ down_write(&file->port->mutex);
if (file->already_used)
ret = -EINVAL;
else
file->use_pkey_index = 1;
- mutex_unlock(&file->mutex);
+ up_write(&file->port->mutex);
return ret;
}
@@ -792,7 +783,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
if (!port)
return -ENXIO;
- mutex_lock(&port->file_mutex);
+ down_write(&port->mutex);
if (!port->ib_dev) {
ret = -ENXIO;
@@ -806,7 +797,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
goto out;
}
- mutex_init(&file->mutex);
+ spin_lock_init(&file->recv_lock);
spin_lock_init(&file->send_lock);
INIT_LIST_HEAD(&file->recv_list);
INIT_LIST_HEAD(&file->send_list);
@@ -818,7 +809,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
list_add_tail(&file->port_list, &port->file_list);
out:
- mutex_unlock(&port->file_mutex);
+ up_write(&port->mutex);
return ret;
}
@@ -830,8 +821,7 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
int already_dead;
int i;
- mutex_lock(&file->port->file_mutex);
- mutex_lock(&file->mutex);
+ down_write(&file->port->mutex);
already_dead = file->agents_dead;
file->agents_dead = 1;
@@ -844,14 +834,14 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
list_del(&file->port_list);
- mutex_unlock(&file->mutex);
+ downgrade_write(&file->port->mutex);
if (!already_dead)
for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i)
if (file->agent[i])
ib_unregister_mad_agent(file->agent[i]);
- mutex_unlock(&file->port->file_mutex);
+ up_read(&file->port->mutex);
kfree(file);
kref_put(&dev->ref, ib_umad_release_dev);
@@ -924,10 +914,10 @@ static int ib_umad_sm_close(struct inode *inode, struct file *filp)
};
int ret = 0;
- mutex_lock(&port->file_mutex);
+ down_write(&port->mutex);
if (port->ib_dev)
ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
- mutex_unlock(&port->file_mutex);
+ up_write(&port->mutex);
up(&port->sm_sem);
@@ -991,7 +981,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
port->ib_dev = device;
port->port_num = port_num;
init_MUTEX(&port->sm_sem);
- mutex_init(&port->file_mutex);
+ init_rwsem(&port->mutex);
INIT_LIST_HEAD(&port->file_list);
port->dev = cdev_alloc();
@@ -1062,7 +1052,6 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
static void ib_umad_kill_port(struct ib_umad_port *port)
{
struct ib_umad_file *file;
- int already_dead;
int id;
class_set_devdata(port->class_dev, NULL);
@@ -1078,22 +1067,42 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
umad_port[port->dev_num] = NULL;
spin_unlock(&port_lock);
- mutex_lock(&port->file_mutex);
+ down_write(&port->mutex);
port->ib_dev = NULL;
- list_for_each_entry(file, &port->file_list, port_list) {
- mutex_lock(&file->mutex);
- already_dead = file->agents_dead;
+ /*
+ * Now go through the list of files attached to this port and
+ * unregister all of their MAD agents. We need to hold
+ * port->mutex while doing this to avoid racing with
+ * ib_umad_close(), but we can't hold the mutex for writing
+ * while calling ib_unregister_mad_agent(), since that might
+ * deadlock by calling back into queue_packet(). So we
+ * downgrade our lock to a read lock, and then drop and
+ * reacquire the write lock for the next iteration.
+ *
+ * We do list_del_init() on the file's list_head so that the
+ * list_del in ib_umad_close() is still OK, even after the
+ * file is removed from the list.
+ */
+ while (!list_empty(&port->file_list)) {
+ file = list_entry(port->file_list.next, struct ib_umad_file,
+ port_list);
+
file->agents_dead = 1;
- mutex_unlock(&file->mutex);
+ list_del_init(&file->port_list);
+
+ downgrade_write(&port->mutex);
for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id)
if (file->agent[id])
ib_unregister_mad_agent(file->agent[id]);
+
+ up_read(&port->mutex);
+ down_write(&port->mutex);
}
- mutex_unlock(&port->file_mutex);
+ up_write(&port->mutex);
clear_bit(port->dev_num, dev_map);
}
diff --git a/trunk/drivers/infiniband/hw/cxgb3/cxio_hal.c b/trunk/drivers/infiniband/hw/cxgb3/cxio_hal.c
index 03c5ff62889a..eec6a30840ca 100644
--- a/trunk/drivers/infiniband/hw/cxgb3/cxio_hal.c
+++ b/trunk/drivers/infiniband/hw/cxgb3/cxio_hal.c
@@ -179,7 +179,7 @@ int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)
setup.size = 1UL << cq->size_log2;
setup.credits = 65535;
setup.credit_thres = 1;
- if (rdev_p->t3cdev_p->type != T3A)
+ if (rdev_p->t3cdev_p->type == T3B)
setup.ovfl_mode = 0;
else
setup.ovfl_mode = 1;
@@ -584,7 +584,7 @@ static int cxio_hal_ctrl_qp_write_mem(struct cxio_rdev *rdev_p, u32 addr,
{
u32 i, nr_wqe, copy_len;
u8 *copy_data;
- u8 wr_len, utx_len; /* length in 8 byte flit */
+ u8 wr_len, utx_len; /* lenght in 8 byte flit */
enum t3_wr_flags flag;
__be64 *wqe;
u64 utx_cmd;
diff --git a/trunk/drivers/infiniband/hw/cxgb3/cxio_wr.h b/trunk/drivers/infiniband/hw/cxgb3/cxio_wr.h
index 969d4d928455..c84d4ac49355 100644
--- a/trunk/drivers/infiniband/hw/cxgb3/cxio_wr.h
+++ b/trunk/drivers/infiniband/hw/cxgb3/cxio_wr.h
@@ -315,7 +315,7 @@ struct t3_rdma_init_wr {
__be32 ird;
__be64 qp_dma_addr; /* 7 */
__be32 qp_dma_size; /* 8 */
- __be32 irs;
+ u32 irs;
};
struct t3_genbit {
@@ -324,8 +324,7 @@ struct t3_genbit {
};
enum rdma_init_wr_flags {
- RECVS_POSTED = (1<<0),
- PRIV_QP = (1<<1),
+ RECVS_POSTED = 1,
};
union t3_wr {
diff --git a/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c b/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c
index f8cb0fe748c3..20ba372dd182 100644
--- a/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -1118,7 +1118,7 @@ static int act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
status2errno(rpl->status));
connect_reply_upcall(ep, status2errno(rpl->status));
state_set(&ep->com, DEAD);
- if (ep->com.tdev->type != T3A && act_open_has_tid(rpl->status))
+ if (ep->com.tdev->type == T3B && act_open_has_tid(rpl->status))
release_tid(ep->com.tdev, GET_TID(rpl), NULL);
cxgb3_free_atid(ep->com.tdev, ep->atid);
dst_release(ep->dst);
@@ -1249,7 +1249,7 @@ static void reject_cr(struct t3cdev *tdev, u32 hwtid, __be32 peer_ip,
skb_trim(skb, sizeof(struct cpl_tid_release));
skb_get(skb);
- if (tdev->type != T3A)
+ if (tdev->type == T3B)
release_tid(tdev, hwtid, skb);
else {
struct cpl_pass_accept_rpl *rpl;
diff --git a/trunk/drivers/infiniband/hw/cxgb3/iwch_mem.c b/trunk/drivers/infiniband/hw/cxgb3/iwch_mem.c
index 73bfd1656f86..a6c2c4ba29e6 100644
--- a/trunk/drivers/infiniband/hw/cxgb3/iwch_mem.c
+++ b/trunk/drivers/infiniband/hw/cxgb3/iwch_mem.c
@@ -122,13 +122,6 @@ int build_phys_page_list(struct ib_phys_buf *buffer_list,
*total_size += buffer_list[i].size;
if (i > 0)
mask |= buffer_list[i].addr;
- else
- mask |= buffer_list[i].addr & PAGE_MASK;
- if (i != num_phys_buf - 1)
- mask |= buffer_list[i].addr + buffer_list[i].size;
- else
- mask |= (buffer_list[i].addr + buffer_list[i].size +
- PAGE_SIZE - 1) & PAGE_MASK;
}
if (*total_size > 0xFFFFFFFFULL)
diff --git a/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.c b/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.c
index df1838f8f94d..b5436ca92e68 100644
--- a/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -39,7 +39,6 @@
#include
#include
#include
-#include
#include
#include
@@ -646,7 +645,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
if (err)
goto err;
- if (udata && !t3a_device(rhp)) {
+ if (udata && t3b_device(rhp)) {
uresp.pbl_addr = (mhp->attr.pbl_addr -
rhp->rdev.rnic_info.pbl_base) >> 3;
PDBG("%s user resp pbl_addr 0x%x\n", __FUNCTION__,
@@ -1054,9 +1053,7 @@ static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
struct net_device *lldev = dev->rdev.t3cdev_p->lldev;
PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
- rtnl_lock();
lldev->ethtool_ops->get_drvinfo(lldev, &info);
- rtnl_unlock();
return sprintf(buf, "%s\n", info.fw_version);
}
@@ -1068,9 +1065,7 @@ static ssize_t show_hca(struct class_device *cdev, char *buf)
struct net_device *lldev = dev->rdev.t3cdev_p->lldev;
PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
- rtnl_lock();
lldev->ethtool_ops->get_drvinfo(lldev, &info);
- rtnl_unlock();
return sprintf(buf, "%s\n", info.driver);
}
diff --git a/trunk/drivers/infiniband/hw/cxgb3/iwch_qp.c b/trunk/drivers/infiniband/hw/cxgb3/iwch_qp.c
index ea2cdd73dd85..dd89b6b91f9c 100644
--- a/trunk/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/trunk/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -208,19 +208,36 @@ static int iwch_sgl2pbl_map(struct iwch_dev *rhp, struct ib_sge *sg_list,
static int iwch_build_rdma_recv(struct iwch_dev *rhp, union t3_wr *wqe,
struct ib_recv_wr *wr)
{
- int i;
+ int i, err = 0;
+ u32 pbl_addr[4];
+ u8 page_size[4];
if (wr->num_sge > T3_MAX_SGE)
return -EINVAL;
+ err = iwch_sgl2pbl_map(rhp, wr->sg_list, wr->num_sge, pbl_addr,
+ page_size);
+ if (err)
+ return err;
+ wqe->recv.pagesz[0] = page_size[0];
+ wqe->recv.pagesz[1] = page_size[1];
+ wqe->recv.pagesz[2] = page_size[2];
+ wqe->recv.pagesz[3] = page_size[3];
wqe->recv.num_sgle = cpu_to_be32(wr->num_sge);
for (i = 0; i < wr->num_sge; i++) {
wqe->recv.sgl[i].stag = cpu_to_be32(wr->sg_list[i].lkey);
wqe->recv.sgl[i].len = cpu_to_be32(wr->sg_list[i].length);
- wqe->recv.sgl[i].to = cpu_to_be64(wr->sg_list[i].addr);
+
+ /* to in the WQE == the offset into the page */
+ wqe->recv.sgl[i].to = cpu_to_be64(((u32) wr->sg_list[i].addr) %
+ (1UL << (12 + page_size[i])));
+
+ /* pbl_addr is the adapters address in the PBL */
+ wqe->recv.pbl_addr[i] = cpu_to_be32(pbl_addr[i]);
}
for (; i < T3_MAX_SGE; i++) {
wqe->recv.sgl[i].stag = 0;
wqe->recv.sgl[i].len = 0;
wqe->recv.sgl[i].to = 0;
+ wqe->recv.pbl_addr[i] = 0;
}
return 0;
}
@@ -642,7 +659,6 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
cxio_flush_rq(&qhp->wq, &rchp->cq, count);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&rchp->lock, *flag);
- (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
/* locking heirarchy: cq lock first, then qp lock. */
spin_lock_irqsave(&schp->lock, *flag);
@@ -652,7 +668,6 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
cxio_flush_sq(&qhp->wq, &schp->cq, count);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&schp->lock, *flag);
- (*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
/* deref */
if (atomic_dec_and_test(&qhp->refcnt))
@@ -663,7 +678,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
static void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
{
- if (qhp->ibqp.uobject)
+ if (t3b_device(qhp->rhp))
cxio_set_wq_in_error(&qhp->wq);
else
__flush_qp(qhp, flag);
@@ -717,7 +732,6 @@ static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
init_attr.qp_dma_addr = qhp->wq.dma_addr;
init_attr.qp_dma_size = (1UL << qhp->wq.size_log2);
init_attr.flags = rqes_posted(qhp) ? RECVS_POSTED : 0;
- init_attr.flags |= capable(CAP_NET_BIND_SERVICE) ? PRIV_QP : 0;
init_attr.irs = qhp->ep->rcv_seq;
PDBG("%s init_attr.rq_addr 0x%x init_attr.rq_size = %d "
"flags 0x%x qpcaps 0x%x\n", __FUNCTION__,
@@ -833,11 +847,10 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
disconnect = 1;
ep = qhp->ep;
}
- flush_qp(qhp, &flag);
break;
case IWCH_QP_STATE_TERMINATE:
qhp->attr.state = IWCH_QP_STATE_TERMINATE;
- if (qhp->ibqp.uobject)
+ if (t3b_device(qhp->rhp))
cxio_set_wq_in_error(&qhp->wq);
if (!internal)
terminate = 1;
diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_av.c b/trunk/drivers/infiniband/hw/ehca/ehca_av.c
index 194c1c30cf63..f7782c882ab4 100644
--- a/trunk/drivers/infiniband/hw/ehca/ehca_av.c
+++ b/trunk/drivers/infiniband/hw/ehca/ehca_av.c
@@ -1,7 +1,7 @@
/*
* IBM eServer eHCA Infiniband device driver for Linux on POWER
*
- * address vector functions
+ * adress vector functions
*
* Authors: Hoang-Nam Nguyen
* Khadija Souissi
diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h
index f281d16040f5..74d2b72a11d8 100644
--- a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -94,11 +94,7 @@ struct ehca_sma_attr {
struct ehca_sport {
struct ib_cq *ibcq_aqp1;
- struct ib_qp *ibqp_sqp[2];
- /* lock to serialze modify_qp() calls for sqp in normal
- * and irq path (when event PORT_ACTIVE is received first time)
- */
- spinlock_t mod_sqp_lock;
+ struct ib_qp *ibqp_aqp1;
enum ib_port_state port_state;
struct ehca_sma_attr saved_attr;
};
@@ -145,14 +141,6 @@ enum ehca_ext_qp_type {
EQPT_SRQ = 3,
};
-/* struct to cache modify_qp()'s parms for GSI/SMI qp */
-struct ehca_mod_qp_parm {
- int mask;
- struct ib_qp_attr attr;
-};
-
-#define EHCA_MOD_QP_PARM_MAX 4
-
struct ehca_qp {
union {
struct ib_qp ib_qp;
@@ -176,18 +164,10 @@ struct ehca_qp {
struct ehca_cq *recv_cq;
unsigned int sqerr_purgeflag;
struct hlist_node list_entries;
- /* array to cache modify_qp()'s parms for GSI/SMI qp */
- struct ehca_mod_qp_parm *mod_qp_parm;
- int mod_qp_parm_idx;
/* mmap counter for resources mapped into user space */
u32 mm_count_squeue;
u32 mm_count_rqueue;
u32 mm_count_galpa;
- /* unsolicited ack circumvention */
- int unsol_ack_circ;
- int mtu_shift;
- u32 message_count;
- u32 packet_count;
};
#define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
@@ -343,7 +323,6 @@ extern int ehca_port_act_time;
extern int ehca_use_hp_mr;
extern int ehca_scaling_code;
extern int ehca_lock_hcalls;
-extern int ehca_nr_ports;
struct ipzu_queue_resp {
u32 qe_size; /* queue entry size */
diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_cq.c b/trunk/drivers/infiniband/hw/ehca/ehca_cq.c
index 0467c158d4a9..79c25f51c21e 100644
--- a/trunk/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/trunk/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -246,7 +246,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
} else {
if (h_ret != H_PAGE_REGISTERED) {
ehca_err(device, "Registration of page failed "
- "ehca_cq=%p cq_num=%x h_ret=%li "
+ "ehca_cq=%p cq_num=%x h_ret=%li"
"counter=%i act_pages=%i",
my_cq, my_cq->cq_number,
h_ret, counter, param.act_pages);
diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_irq.c b/trunk/drivers/infiniband/hw/ehca/ehca_irq.c
index 863b34fa9ff9..3f617b27b954 100644
--- a/trunk/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/trunk/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -62,7 +62,6 @@
#define NEQE_PORT_NUMBER EHCA_BMASK_IBM( 8, 15)
#define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16, 16)
#define NEQE_DISRUPTIVE EHCA_BMASK_IBM(16, 16)
-#define NEQE_SPECIFIC_EVENT EHCA_BMASK_IBM(16, 23)
#define ERROR_DATA_LENGTH EHCA_BMASK_IBM(52, 63)
#define ERROR_DATA_TYPE EHCA_BMASK_IBM( 0, 7)
@@ -355,34 +354,17 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
{
u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
- u8 spec_event;
- struct ehca_sport *sport = &shca->sport[port - 1];
- unsigned long flags;
switch (ec) {
case 0x30: /* port availability change */
if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
- int suppress_event;
- /* replay modify_qp for sqps */
- spin_lock_irqsave(&sport->mod_sqp_lock, flags);
- suppress_event = !sport->ibqp_sqp[IB_QPT_GSI];
- if (sport->ibqp_sqp[IB_QPT_SMI])
- ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]);
- if (!suppress_event)
- ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]);
- spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
-
- /* AQP1 was destroyed, ignore this event */
- if (suppress_event)
- break;
-
- sport->port_state = IB_PORT_ACTIVE;
+ shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
"is active");
ehca_query_sma_attr(shca, port,
- &sport->saved_attr);
+ &shca->sport[port - 1].saved_attr);
} else {
- sport->port_state = IB_PORT_DOWN;
+ shca->sport[port - 1].port_state = IB_PORT_DOWN;
dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
"is inactive");
}
@@ -396,11 +378,11 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
ehca_warn(&shca->ib_device, "disruptive port "
"%d configuration change", port);
- sport->port_state = IB_PORT_DOWN;
+ shca->sport[port - 1].port_state = IB_PORT_DOWN;
dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
"is inactive");
- sport->port_state = IB_PORT_ACTIVE;
+ shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
"is active");
} else
@@ -412,16 +394,6 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
case 0x33: /* trace stopped */
ehca_err(&shca->ib_device, "Traced stopped.");
break;
- case 0x34: /* util async event */
- spec_event = EHCA_BMASK_GET(NEQE_SPECIFIC_EVENT, eqe);
- if (spec_event == 0x80) /* client reregister required */
- dispatch_port_event(shca, port,
- IB_EVENT_CLIENT_REREGISTER,
- "client reregister req.");
- else
- ehca_warn(&shca->ib_device, "Unknown util async "
- "event %x on port %x", spec_event, port);
- break;
default:
ehca_err(&shca->ib_device, "Unknown event code: %x on %s.",
ec, shca->ib_device.name);
diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h b/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h
index c469bfde2708..5485799cdc8d 100644
--- a/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -200,6 +200,4 @@ void ehca_free_fw_ctrlblock(void *ptr);
#define ehca_free_fw_ctrlblock(ptr) free_page((unsigned long)(ptr))
#endif
-void ehca_recover_sqp(struct ib_qp *sqp);
-
#endif
diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_main.c b/trunk/drivers/infiniband/hw/ehca/ehca_main.c
index 84c9b7b8669b..c9e32b46387f 100644
--- a/trunk/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/trunk/drivers/infiniband/hw/ehca/ehca_main.c
@@ -90,8 +90,7 @@ MODULE_PARM_DESC(hw_level,
"hardware level"
" (0: autosensing (default), 1: v. 0.20, 2: v. 0.21)");
MODULE_PARM_DESC(nr_ports,
- "number of connected ports (-1: autodetect, 1: port one only, "
- "2: two ports (default)");
+ "number of connected ports (default: 2)");
MODULE_PARM_DESC(use_hp_mr,
"high performance MRs (0: no (default), 1: yes)");
MODULE_PARM_DESC(port_act_time,
@@ -512,7 +511,7 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 port)
}
sport->ibcq_aqp1 = ibcq;
- if (sport->ibqp_sqp[IB_QPT_GSI]) {
+ if (sport->ibqp_aqp1) {
ehca_err(&shca->ib_device, "AQP1 QP is already created.");
ret = -EPERM;
goto create_aqp1;
@@ -538,7 +537,7 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 port)
ret = PTR_ERR(ibqp);
goto create_aqp1;
}
- sport->ibqp_sqp[IB_QPT_GSI] = ibqp;
+ sport->ibqp_aqp1 = ibqp;
return 0;
@@ -551,7 +550,7 @@ static int ehca_destroy_aqp1(struct ehca_sport *sport)
{
int ret;
- ret = ib_destroy_qp(sport->ibqp_sqp[IB_QPT_GSI]);
+ ret = ib_destroy_qp(sport->ibqp_aqp1);
if (ret) {
ehca_gen_err("Cannot destroy AQP1 QP. ret=%i", ret);
return ret;
@@ -694,7 +693,7 @@ static int __devinit ehca_probe(struct of_device *dev,
struct ehca_shca *shca;
const u64 *handle;
struct ib_pd *ibpd;
- int ret, i;
+ int ret;
handle = of_get_property(dev->node, "ibm,hca-handle", NULL);
if (!handle) {
@@ -715,8 +714,6 @@ static int __devinit ehca_probe(struct of_device *dev,
return -ENOMEM;
}
mutex_init(&shca->modify_mutex);
- for (i = 0; i < ARRAY_SIZE(shca->sport); i++)
- spin_lock_init(&shca->sport[i].mod_sqp_lock);
shca->ofdev = dev;
shca->ipz_hca_handle.handle = *handle;
@@ -937,7 +934,7 @@ void ehca_poll_eqs(unsigned long data)
ehca_process_eq(shca, 0);
}
}
- mod_timer(&poll_eqs_timer, round_jiffies(jiffies + HZ));
+ mod_timer(&poll_eqs_timer, jiffies + HZ);
spin_unlock(&shca_list_lock);
}
diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_qp.c b/trunk/drivers/infiniband/hw/ehca/ehca_qp.c
index 1012f15a7140..eff5fb55604b 100644
--- a/trunk/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/trunk/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -592,8 +592,10 @@ static struct ehca_qp *internal_create_qp(
goto create_qp_exit1;
}
- /* Always signal by WQE so we can hide circ. WQEs */
- parms.sigtype = HCALL_SIGT_BY_WQE;
+ if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
+ parms.sigtype = HCALL_SIGT_EVERY;
+ else
+ parms.sigtype = HCALL_SIGT_BY_WQE;
/* UD_AV CIRCUMVENTION */
max_send_sge = init_attr->cap.max_send_sge;
@@ -616,10 +618,6 @@ static struct ehca_qp *internal_create_qp(
parms.squeue.max_sge = max_send_sge;
parms.rqueue.max_sge = max_recv_sge;
- /* RC QPs need one more SWQE for unsolicited ack circumvention */
- if (qp_type == IB_QPT_RC)
- parms.squeue.max_wr++;
-
if (EHCA_BMASK_GET(HCA_CAP_MINI_QP, shca->hca_cap)) {
if (HAS_SQ(my_qp))
ehca_determine_small_queue(
@@ -652,8 +650,6 @@ static struct ehca_qp *internal_create_qp(
parms.squeue.act_nr_sges = 1;
parms.rqueue.act_nr_sges = 1;
}
- /* hide the extra WQE */
- parms.squeue.act_nr_wqes--;
break;
case IB_QPT_UD:
case IB_QPT_GSI:
@@ -733,31 +729,12 @@ static struct ehca_qp *internal_create_qp(
init_attr->cap.max_send_wr = parms.squeue.act_nr_wqes;
my_qp->init_attr = *init_attr;
- if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) {
- shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] =
- &my_qp->ib_qp;
- if (ehca_nr_ports < 0) {
- /* alloc array to cache subsequent modify qp parms
- * for autodetect mode
- */
- my_qp->mod_qp_parm =
- kzalloc(EHCA_MOD_QP_PARM_MAX *
- sizeof(*my_qp->mod_qp_parm),
- GFP_KERNEL);
- if (!my_qp->mod_qp_parm) {
- ehca_err(pd->device,
- "Could not alloc mod_qp_parm");
- goto create_qp_exit4;
- }
- }
- }
-
/* NOTE: define_apq0() not supported yet */
if (qp_type == IB_QPT_GSI) {
h_ret = ehca_define_sqp(shca, my_qp, init_attr);
if (h_ret != H_SUCCESS) {
ret = ehca2ib_return_code(h_ret);
- goto create_qp_exit5;
+ goto create_qp_exit4;
}
}
@@ -766,7 +743,7 @@ static struct ehca_qp *internal_create_qp(
if (ret) {
ehca_err(pd->device,
"Couldn't assign qp to send_cq ret=%i", ret);
- goto create_qp_exit5;
+ goto create_qp_exit4;
}
}
@@ -792,18 +769,12 @@ static struct ehca_qp *internal_create_qp(
if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
ehca_err(pd->device, "Copy to udata failed");
ret = -EINVAL;
- goto create_qp_exit6;
+ goto create_qp_exit4;
}
}
return my_qp;
-create_qp_exit6:
- ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num);
-
-create_qp_exit5:
- kfree(my_qp->mod_qp_parm);
-
create_qp_exit4:
if (HAS_RQ(my_qp))
ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
@@ -887,7 +858,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
update_mask,
mqpcb, my_qp->galpas.kernel);
if (hret != H_SUCCESS) {
- ehca_err(pd->device, "Could not modify SRQ to INIT "
+ ehca_err(pd->device, "Could not modify SRQ to INIT"
"ehca_qp=%p qp_num=%x h_ret=%li",
my_qp, my_qp->real_qp_num, hret);
goto create_srq2;
@@ -901,7 +872,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
update_mask,
mqpcb, my_qp->galpas.kernel);
if (hret != H_SUCCESS) {
- ehca_err(pd->device, "Could not enable SRQ "
+ ehca_err(pd->device, "Could not enable SRQ"
"ehca_qp=%p qp_num=%x h_ret=%li",
my_qp, my_qp->real_qp_num, hret);
goto create_srq2;
@@ -915,7 +886,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
update_mask,
mqpcb, my_qp->galpas.kernel);
if (hret != H_SUCCESS) {
- ehca_err(pd->device, "Could not modify SRQ to RTR "
+ ehca_err(pd->device, "Could not modify SRQ to RTR"
"ehca_qp=%p qp_num=%x h_ret=%li",
my_qp, my_qp->real_qp_num, hret);
goto create_srq2;
@@ -1021,7 +992,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
unsigned long flags = 0;
/* do query_qp to obtain current attr values */
- mqpcb = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
+ mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!mqpcb) {
ehca_err(ibqp->device, "Could not get zeroed page for mqpcb "
"ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num);
@@ -1209,8 +1180,6 @@ static int internal_modify_qp(struct ib_qp *ibqp,
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_P_KEY_IDX, 1);
}
if (attr_mask & IB_QP_PORT) {
- struct ehca_sport *sport;
- struct ehca_qp *aqp1;
if (attr->port_num < 1 || attr->port_num > shca->num_ports) {
ret = -EINVAL;
ehca_err(ibqp->device, "Invalid port=%x. "
@@ -1219,29 +1188,6 @@ static int internal_modify_qp(struct ib_qp *ibqp,
shca->num_ports);
goto modify_qp_exit2;
}
- sport = &shca->sport[attr->port_num - 1];
- if (!sport->ibqp_sqp[IB_QPT_GSI]) {
- /* should not occur */
- ret = -EFAULT;
- ehca_err(ibqp->device, "AQP1 was not created for "
- "port=%x", attr->port_num);
- goto modify_qp_exit2;
- }
- aqp1 = container_of(sport->ibqp_sqp[IB_QPT_GSI],
- struct ehca_qp, ib_qp);
- if (ibqp->qp_type != IB_QPT_GSI &&
- ibqp->qp_type != IB_QPT_SMI &&
- aqp1->mod_qp_parm) {
- /*
- * firmware will reject this modify_qp() because
- * port is not activated/initialized fully
- */
- ret = -EFAULT;
- ehca_warn(ibqp->device, "Couldn't modify qp port=%x: "
- "either port is being activated (try again) "
- "or cabling issue", attr->port_num);
- goto modify_qp_exit2;
- }
mqpcb->prim_phys_port = attr->port_num;
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_PHYS_PORT, 1);
}
@@ -1298,8 +1244,6 @@ static int internal_modify_qp(struct ib_qp *ibqp,
}
if (attr_mask & IB_QP_PATH_MTU) {
- /* store ld(MTU) */
- my_qp->mtu_shift = attr->path_mtu + 7;
mqpcb->path_mtu = attr->path_mtu;
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PATH_MTU, 1);
}
@@ -1523,8 +1467,6 @@ static int internal_modify_qp(struct ib_qp *ibqp,
int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
struct ib_udata *udata)
{
- struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
- ib_device);
struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
ib_pd);
@@ -1537,100 +1479,9 @@ int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
return -EINVAL;
}
- /* The if-block below caches qp_attr to be modified for GSI and SMI
- * qps during the initialization by ib_mad. When the respective port
- * is activated, ie we got an event PORT_ACTIVE, we'll replay the
- * cached modify calls sequence, see ehca_recover_sqs() below.
- * Why that is required:
- * 1) If one port is connected, older code requires that port one
- * to be connected and module option nr_ports=1 to be given by
- * user, which is very inconvenient for end user.
- * 2) Firmware accepts modify_qp() only if respective port has become
- * active. Older code had a wait loop of 30sec create_qp()/
- * define_aqp1(), which is not appropriate in practice. This
- * code now removes that wait loop, see define_aqp1(), and always
- * reports all ports to ib_mad resp. users. Only activated ports
- * will then usable for the users.
- */
- if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI) {
- int port = my_qp->init_attr.port_num;
- struct ehca_sport *sport = &shca->sport[port - 1];
- unsigned long flags;
- spin_lock_irqsave(&sport->mod_sqp_lock, flags);
- /* cache qp_attr only during init */
- if (my_qp->mod_qp_parm) {
- struct ehca_mod_qp_parm *p;
- if (my_qp->mod_qp_parm_idx >= EHCA_MOD_QP_PARM_MAX) {
- ehca_err(&shca->ib_device,
- "mod_qp_parm overflow state=%x port=%x"
- " type=%x", attr->qp_state,
- my_qp->init_attr.port_num,
- ibqp->qp_type);
- spin_unlock_irqrestore(&sport->mod_sqp_lock,
- flags);
- return -EINVAL;
- }
- p = &my_qp->mod_qp_parm[my_qp->mod_qp_parm_idx];
- p->mask = attr_mask;
- p->attr = *attr;
- my_qp->mod_qp_parm_idx++;
- ehca_dbg(&shca->ib_device,
- "Saved qp_attr for state=%x port=%x type=%x",
- attr->qp_state, my_qp->init_attr.port_num,
- ibqp->qp_type);
- spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
- return 0;
- }
- spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
- }
-
return internal_modify_qp(ibqp, attr, attr_mask, 0);
}
-void ehca_recover_sqp(struct ib_qp *sqp)
-{
- struct ehca_qp *my_sqp = container_of(sqp, struct ehca_qp, ib_qp);
- int port = my_sqp->init_attr.port_num;
- struct ib_qp_attr attr;
- struct ehca_mod_qp_parm *qp_parm;
- int i, qp_parm_idx, ret;
- unsigned long flags, wr_cnt;
-
- if (!my_sqp->mod_qp_parm)
- return;
- ehca_dbg(sqp->device, "SQP port=%x qp_num=%x", port, sqp->qp_num);
-
- qp_parm = my_sqp->mod_qp_parm;
- qp_parm_idx = my_sqp->mod_qp_parm_idx;
- for (i = 0; i < qp_parm_idx; i++) {
- attr = qp_parm[i].attr;
- ret = internal_modify_qp(sqp, &attr, qp_parm[i].mask, 0);
- if (ret) {
- ehca_err(sqp->device, "Could not modify SQP port=%x "
- "qp_num=%x ret=%x", port, sqp->qp_num, ret);
- goto free_qp_parm;
- }
- ehca_dbg(sqp->device, "SQP port=%x qp_num=%x in state=%x",
- port, sqp->qp_num, attr.qp_state);
- }
-
- /* re-trigger posted recv wrs */
- wr_cnt = my_sqp->ipz_rqueue.current_q_offset /
- my_sqp->ipz_rqueue.qe_size;
- if (wr_cnt) {
- spin_lock_irqsave(&my_sqp->spinlock_r, flags);
- hipz_update_rqa(my_sqp, wr_cnt);
- spin_unlock_irqrestore(&my_sqp->spinlock_r, flags);
- ehca_dbg(sqp->device, "doorbell port=%x qp_num=%x wr_cnt=%lx",
- port, sqp->qp_num, wr_cnt);
- }
-
-free_qp_parm:
- kfree(qp_parm);
- /* this prevents subsequent calls to modify_qp() to cache qp_attr */
- my_sqp->mod_qp_parm = NULL;
-}
-
int ehca_query_qp(struct ib_qp *qp,
struct ib_qp_attr *qp_attr,
int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
@@ -1918,7 +1769,6 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
struct ehca_shca *shca = container_of(dev, struct ehca_shca, ib_device);
struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
ib_pd);
- struct ehca_sport *sport = &shca->sport[my_qp->init_attr.port_num - 1];
u32 cur_pid = current->tgid;
u32 qp_num = my_qp->real_qp_num;
int ret;
@@ -1965,14 +1815,6 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
port_num = my_qp->init_attr.port_num;
qp_type = my_qp->init_attr.qp_type;
- if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) {
- spin_lock_irqsave(&sport->mod_sqp_lock, flags);
- kfree(my_qp->mod_qp_parm);
- my_qp->mod_qp_parm = NULL;
- shca->sport[port_num - 1].ibqp_sqp[qp_type] = NULL;
- spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
- }
-
/* no support for IB_QPT_SMI yet */
if (qp_type == IB_QPT_GSI) {
struct ib_event event;
diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_reqs.c b/trunk/drivers/infiniband/hw/ehca/ehca_reqs.c
index 3aacc8cf1e44..ea91360835d3 100644
--- a/trunk/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/trunk/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -50,9 +50,6 @@
#include "hcp_if.h"
#include "hipz_fns.h"
-/* in RC traffic, insert an empty RDMA READ every this many packets */
-#define ACK_CIRC_THRESHOLD 2000000
-
static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
struct ehca_wqe *wqe_p,
struct ib_recv_wr *recv_wr)
@@ -84,7 +81,7 @@ static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
if (ehca_debug_level) {
ehca_gen_dbg("RECEIVE WQE written into ipz_rqueue=%p",
ipz_rqueue);
- ehca_dmp(wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe");
+ ehca_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe");
}
return 0;
@@ -138,8 +135,7 @@ static void trace_send_wr_ud(const struct ib_send_wr *send_wr)
static inline int ehca_write_swqe(struct ehca_qp *qp,
struct ehca_wqe *wqe_p,
- const struct ib_send_wr *send_wr,
- int hidden)
+ const struct ib_send_wr *send_wr)
{
u32 idx;
u64 dma_length;
@@ -180,9 +176,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
wqe_p->wr_flag = 0;
- if ((send_wr->send_flags & IB_SEND_SIGNALED ||
- qp->init_attr.sq_sig_type == IB_SIGNAL_ALL_WR)
- && !hidden)
+ if (send_wr->send_flags & IB_SEND_SIGNALED)
wqe_p->wr_flag |= WQE_WRFLAG_REQ_SIGNAL_COM;
if (send_wr->opcode == IB_WR_SEND_WITH_IMM ||
@@ -205,7 +199,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
wqe_p->destination_qp_number = send_wr->wr.ud.remote_qpn << 8;
wqe_p->local_ee_context_qkey = remote_qkey;
- if (unlikely(!send_wr->wr.ud.ah)) {
+ if (!send_wr->wr.ud.ah) {
ehca_gen_err("wr.ud.ah is NULL. qp=%p", qp);
return -EINVAL;
}
@@ -261,15 +255,6 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
} /* eof idx */
wqe_p->u.nud.atomic_1st_op_dma_len = dma_length;
- /* unsolicited ack circumvention */
- if (send_wr->opcode == IB_WR_RDMA_READ) {
- /* on RDMA read, switch on and reset counters */
- qp->message_count = qp->packet_count = 0;
- qp->unsol_ack_circ = 1;
- } else
- /* else estimate #packets */
- qp->packet_count += (dma_length >> qp->mtu_shift) + 1;
-
break;
default:
@@ -370,49 +355,13 @@ static inline void map_ib_wc_status(u32 cqe_status,
*wc_status = IB_WC_SUCCESS;
}
-static inline int post_one_send(struct ehca_qp *my_qp,
- struct ib_send_wr *cur_send_wr,
- struct ib_send_wr **bad_send_wr,
- int hidden)
-{
- struct ehca_wqe *wqe_p;
- int ret;
- u64 start_offset = my_qp->ipz_squeue.current_q_offset;
-
- /* get pointer next to free WQE */
- wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue);
- if (unlikely(!wqe_p)) {
- /* too many posted work requests: queue overflow */
- if (bad_send_wr)
- *bad_send_wr = cur_send_wr;
- ehca_err(my_qp->ib_qp.device, "Too many posted WQEs "
- "qp_num=%x", my_qp->ib_qp.qp_num);
- return -ENOMEM;
- }
- /* write a SEND WQE into the QUEUE */
- ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr, hidden);
- /*
- * if something failed,
- * reset the free entry pointer to the start value
- */
- if (unlikely(ret)) {
- my_qp->ipz_squeue.current_q_offset = start_offset;
- if (bad_send_wr)
- *bad_send_wr = cur_send_wr;
- ehca_err(my_qp->ib_qp.device, "Could not write WQE "
- "qp_num=%x", my_qp->ib_qp.qp_num);
- return -EINVAL;
- }
-
- return 0;
-}
-
int ehca_post_send(struct ib_qp *qp,
struct ib_send_wr *send_wr,
struct ib_send_wr **bad_send_wr)
{
struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
struct ib_send_wr *cur_send_wr;
+ struct ehca_wqe *wqe_p;
int wqe_cnt = 0;
int ret = 0;
unsigned long flags;
@@ -420,33 +369,37 @@ int ehca_post_send(struct ib_qp *qp,
/* LOCK the QUEUE */
spin_lock_irqsave(&my_qp->spinlock_s, flags);
- /* Send an empty extra RDMA read if:
- * 1) there has been an RDMA read on this connection before
- * 2) no RDMA read occurred for ACK_CIRC_THRESHOLD link packets
- * 3) we can be sure that any previous extra RDMA read has been
- * processed so we don't overflow the SQ
- */
- if (unlikely(my_qp->unsol_ack_circ &&
- my_qp->packet_count > ACK_CIRC_THRESHOLD &&
- my_qp->message_count > my_qp->init_attr.cap.max_send_wr)) {
- /* insert an empty RDMA READ to fix up the remote QP state */
- struct ib_send_wr circ_wr;
- memset(&circ_wr, 0, sizeof(circ_wr));
- circ_wr.opcode = IB_WR_RDMA_READ;
- post_one_send(my_qp, &circ_wr, NULL, 1); /* ignore retcode */
- wqe_cnt++;
- ehca_dbg(qp->device, "posted circ wr qp_num=%x", qp->qp_num);
- my_qp->message_count = my_qp->packet_count = 0;
- }
-
/* loop processes list of send reqs */
for (cur_send_wr = send_wr; cur_send_wr != NULL;
cur_send_wr = cur_send_wr->next) {
- ret = post_one_send(my_qp, cur_send_wr, bad_send_wr, 0);
+ u64 start_offset = my_qp->ipz_squeue.current_q_offset;
+ /* get pointer next to free WQE */
+ wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue);
+ if (unlikely(!wqe_p)) {
+ /* too many posted work requests: queue overflow */
+ if (bad_send_wr)
+ *bad_send_wr = cur_send_wr;
+ if (wqe_cnt == 0) {
+ ret = -ENOMEM;
+ ehca_err(qp->device, "Too many posted WQEs "
+ "qp_num=%x", qp->qp_num);
+ }
+ goto post_send_exit0;
+ }
+ /* write a SEND WQE into the QUEUE */
+ ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr);
+ /*
+ * if something failed,
+ * reset the free entry pointer to the start value
+ */
if (unlikely(ret)) {
- /* if one or more WQEs were successful, don't fail */
- if (wqe_cnt)
- ret = 0;
+ my_qp->ipz_squeue.current_q_offset = start_offset;
+ *bad_send_wr = cur_send_wr;
+ if (wqe_cnt == 0) {
+ ret = -EINVAL;
+ ehca_err(qp->device, "Could not write WQE "
+ "qp_num=%x", qp->qp_num);
+ }
goto post_send_exit0;
}
wqe_cnt++;
@@ -457,7 +410,6 @@ int ehca_post_send(struct ib_qp *qp,
post_send_exit0:
iosync(); /* serialize GAL register access */
hipz_update_sqa(my_qp, wqe_cnt);
- my_qp->message_count += wqe_cnt;
spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
return ret;
}
diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_sqp.c b/trunk/drivers/infiniband/hw/ehca/ehca_sqp.c
index 79e72b25b252..f0792e5fbd02 100644
--- a/trunk/drivers/infiniband/hw/ehca/ehca_sqp.c
+++ b/trunk/drivers/infiniband/hw/ehca/ehca_sqp.c
@@ -40,8 +40,11 @@
*/
+#include
+#include
#include "ehca_classes.h"
#include "ehca_tools.h"
+#include "ehca_qes.h"
#include "ehca_iverbs.h"
#include "hcp_if.h"
@@ -90,9 +93,6 @@ u64 ehca_define_sqp(struct ehca_shca *shca,
return H_PARAMETER;
}
- if (ehca_nr_ports < 0) /* autodetect mode */
- return H_SUCCESS;
-
for (counter = 0;
shca->sport[port - 1].port_state != IB_PORT_ACTIVE &&
counter < ehca_port_act_time;
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_common.h b/trunk/drivers/infiniband/hw/ipath/ipath_common.h
index 414621095540..851df8a75e79 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_common.h
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_common.h
@@ -81,16 +81,6 @@
#define IPATH_IB_LINK_LOOPBACK 6 /* enable local loopback */
#define IPATH_IB_LINK_EXTERNAL 7 /* normal, disable local loopback */
-/*
- * These 3 values (SDR and DDR may be ORed for auto-speed
- * negotiation) are used for the 3rd argument to path_f_set_ib_cfg
- * with cmd IPATH_IB_CFG_SPD_ENB, by direct calls or via sysfs. They
- * are also the the possible values for ipath_link_speed_enabled and active
- * The values were chosen to match values used within the IB spec.
- */
-#define IPATH_IB_SDR 1
-#define IPATH_IB_DDR 2
-
/*
* stats maintained by the driver. For now, at least, this is global
* to all minor devices.
@@ -443,9 +433,8 @@ struct ipath_user_info {
#define IPATH_CMD_UNUSED_2 26
#define IPATH_CMD_PIOAVAILUPD 27 /* force an update of PIOAvail reg */
#define IPATH_CMD_POLL_TYPE 28 /* set the kind of polling we want */
-#define IPATH_CMD_ARMLAUNCH_CTRL 29 /* armlaunch detection control */
-#define IPATH_CMD_MAX 29
+#define IPATH_CMD_MAX 28
/*
* Poll types
@@ -488,8 +477,6 @@ struct ipath_cmd {
__u64 port_info;
/* enable/disable receipt of packets */
__u32 recv_ctrl;
- /* enable/disable armlaunch errors (non-zero to enable) */
- __u32 armlaunch_ctrl;
/* partition key to set */
__u16 part_key;
/* user address of __u32 bitmask of active slaves */
@@ -592,7 +579,7 @@ struct ipath_flash {
struct infinipath_counters {
__u64 LBIntCnt;
__u64 LBFlowStallCnt;
- __u64 TxSDmaDescCnt; /* was Reserved1 */
+ __u64 Reserved1;
__u64 TxUnsupVLErrCnt;
__u64 TxDataPktCnt;
__u64 TxFlowPktCnt;
@@ -628,26 +615,12 @@ struct infinipath_counters {
__u64 RxP6HdrEgrOvflCnt;
__u64 RxP7HdrEgrOvflCnt;
__u64 RxP8HdrEgrOvflCnt;
- __u64 RxP9HdrEgrOvflCnt; /* was Reserved6 */
- __u64 RxP10HdrEgrOvflCnt; /* was Reserved7 */
- __u64 RxP11HdrEgrOvflCnt; /* new for IBA7220 */
- __u64 RxP12HdrEgrOvflCnt; /* new for IBA7220 */
- __u64 RxP13HdrEgrOvflCnt; /* new for IBA7220 */
- __u64 RxP14HdrEgrOvflCnt; /* new for IBA7220 */
- __u64 RxP15HdrEgrOvflCnt; /* new for IBA7220 */
- __u64 RxP16HdrEgrOvflCnt; /* new for IBA7220 */
+ __u64 Reserved6;
+ __u64 Reserved7;
__u64 IBStatusChangeCnt;
__u64 IBLinkErrRecoveryCnt;
__u64 IBLinkDownedCnt;
__u64 IBSymbolErrCnt;
- /* The following are new for IBA7220 */
- __u64 RxVL15DroppedPktCnt;
- __u64 RxOtherLocalPhyErrCnt;
- __u64 PcieRetryBufDiagQwordCnt;
- __u64 ExcessBufferOvflCnt;
- __u64 LocalLinkIntegrityErrCnt;
- __u64 RxVlErrCnt;
- __u64 RxDlidFltrCnt;
};
/*
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_cq.c b/trunk/drivers/infiniband/hw/ipath/ipath_cq.c
index a03bd28d9b48..d1380c7a1703 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_cq.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_cq.c
@@ -421,7 +421,7 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
else
n = head - tail;
if (unlikely((u32)cqe < n)) {
- ret = -EINVAL;
+ ret = -EOVERFLOW;
goto bail_unlock;
}
for (n = 0; tail != head; n++) {
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_debug.h b/trunk/drivers/infiniband/hw/ipath/ipath_debug.h
index d6f69532d83f..19c56e6491eb 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_debug.h
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_debug.h
@@ -55,7 +55,7 @@
#define __IPATH_PKTDBG 0x80 /* print packet data */
/* print process startup (init)/exit messages */
#define __IPATH_PROCDBG 0x100
-/* print mmap/fault stuff, not using VDBG any more */
+/* print mmap/nopage stuff, not using VDBG any more */
#define __IPATH_MMDBG 0x200
#define __IPATH_ERRPKTDBG 0x400
#define __IPATH_USER_SEND 0x1000 /* use user mode send */
@@ -81,7 +81,7 @@
#define __IPATH_VERBDBG 0x0 /* very verbose debug */
#define __IPATH_PKTDBG 0x0 /* print packet data */
#define __IPATH_PROCDBG 0x0 /* process startup (init)/exit messages */
-/* print mmap/fault stuff, not using VDBG any more */
+/* print mmap/nopage stuff, not using VDBG any more */
#define __IPATH_MMDBG 0x0
#define __IPATH_EPKTDBG 0x0 /* print ethernet packet data */
#define __IPATH_IPATHDBG 0x0 /* Ethernet (IPATH) table dump on */
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_driver.c b/trunk/drivers/infiniband/hw/ipath/ipath_driver.c
index d5ff6ca2db30..fc355981bbab 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -334,8 +334,6 @@ static void ipath_verify_pioperf(struct ipath_devdata *dd)
udelay(1);
}
- ipath_disable_armlaunch(dd);
-
writeq(0, piobuf); /* length 0, no dwords actually sent */
ipath_flush_wc();
@@ -367,7 +365,6 @@ static void ipath_verify_pioperf(struct ipath_devdata *dd)
done:
/* disarm piobuf, so it's available again */
ipath_disarm_piobufs(dd, pbnum, 1);
- ipath_enable_armlaunch(dd);
}
static int __devinit ipath_init_one(struct pci_dev *pdev,
@@ -806,37 +803,31 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
unsigned cnt)
{
unsigned i, last = first + cnt;
- unsigned long flags;
+ u64 sendctrl, sendorig;
ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first);
+ sendorig = dd->ipath_sendctrl;
for (i = first; i < last; i++) {
- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
- /*
- * The disarm-related bits are write-only, so it
- * is ok to OR them in with our copy of sendctrl
- * while we hold the lock.
- */
+ sendctrl = sendorig | INFINIPATH_S_DISARM |
+ (i << INFINIPATH_S_DISARMPIOBUF_SHIFT);
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- dd->ipath_sendctrl | INFINIPATH_S_DISARM |
- (i << INFINIPATH_S_DISARMPIOBUF_SHIFT));
- /* can't disarm bufs back-to-back per iba7220 spec */
- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+ sendctrl);
}
/*
- * Disable PIOAVAILUPD, then re-enable, reading scratch in
+ * Write it again with current value, in case ipath_sendctrl changed
+ * while we were looping; no critical bits that would require
+ * locking.
+ *
+ * disable PIOAVAILUPD, then re-enable, reading scratch in
* between. This seems to avoid a chip timing race that causes
- * pioavail updates to memory to stop. We xor as we don't
- * know the state of the bit when we're called.
+ * pioavail updates to memory to stop.
*/
- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- dd->ipath_sendctrl ^ INFINIPATH_S_PIOBUFAVAILUPD);
- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ sendorig & ~INFINIPATH_S_PIOBUFAVAILUPD);
+ sendorig = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
dd->ipath_sendctrl);
- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
}
/**
@@ -1012,10 +1003,12 @@ static void get_rhf_errstring(u32 err, char *msg, size_t len)
* ipath_get_egrbuf - get an eager buffer
* @dd: the infinipath device
* @bufnum: the eager buffer to get
+ * @err: unused
*
* must only be called if ipath_pd[port] is known to be allocated
*/
-static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum)
+static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum,
+ int err)
{
return dd->ipath_port0_skbinfo ?
(void *) dd->ipath_port0_skbinfo[bufnum].skb->data : NULL;
@@ -1107,14 +1100,13 @@ static void ipath_rcv_hdrerr(struct ipath_devdata *dd,
/*
* ipath_kreceive - receive a packet
- * @pd: the infinipath port
+ * @dd: the infinipath device
*
* called from interrupt handler for errors or receive interrupt
*/
-void ipath_kreceive(struct ipath_portdata *pd)
+void ipath_kreceive(struct ipath_devdata *dd)
{
u64 *rc;
- struct ipath_devdata *dd = pd->port_dd;
void *ebuf;
const u32 rsize = dd->ipath_rcvhdrentsize; /* words */
const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize; /* words */
@@ -1129,8 +1121,8 @@ void ipath_kreceive(struct ipath_portdata *pd)
goto bail;
}
- l = pd->port_head;
- hdrqtail = ipath_get_rcvhdrtail(pd);
+ l = dd->ipath_port0head;
+ hdrqtail = (u32) le64_to_cpu(*dd->ipath_hdrqtailptr);
if (l == hdrqtail)
goto bail;
@@ -1139,7 +1131,7 @@ void ipath_kreceive(struct ipath_portdata *pd)
u32 qp;
u8 *bthbytes;
- rc = (u64 *) (pd->port_rcvhdrq + (l << 2));
+ rc = (u64 *) (dd->ipath_pd[0]->port_rcvhdrq + (l << 2));
hdr = (struct ipath_message_header *)&rc[1];
/*
* could make a network order version of IPATH_KD_QP, and
@@ -1164,7 +1156,7 @@ void ipath_kreceive(struct ipath_portdata *pd)
etail = ipath_hdrget_index((__le32 *) rc);
if (tlen > sizeof(*hdr) ||
etype == RCVHQ_RCV_TYPE_NON_KD)
- ebuf = ipath_get_egrbuf(dd, etail);
+ ebuf = ipath_get_egrbuf(dd, etail, 0);
}
/*
@@ -1199,7 +1191,7 @@ void ipath_kreceive(struct ipath_portdata *pd)
be32_to_cpu(hdr->bth[0]) & 0xff);
else {
/*
- * error packet, type of error unknown.
+ * error packet, type of error unknown.
* Probably type 3, but we don't know, so don't
* even try to print the opcode, etc.
*/
@@ -1249,7 +1241,7 @@ void ipath_kreceive(struct ipath_portdata *pd)
* earlier packets, we "almost" guarantee we have covered
* that case.
*/
- u32 hqtail = ipath_get_rcvhdrtail(pd);
+ u32 hqtail = (u32)le64_to_cpu(*dd->ipath_hdrqtailptr);
if (hqtail != hdrqtail) {
hdrqtail = hqtail;
reloop = 1; /* loop 1 extra time at most */
@@ -1259,7 +1251,7 @@ void ipath_kreceive(struct ipath_portdata *pd)
pkttot += i;
- pd->port_head = l;
+ dd->ipath_port0head = l;
if (pkttot > ipath_stats.sps_maxpkts_call)
ipath_stats.sps_maxpkts_call = pkttot;
@@ -1343,9 +1335,14 @@ static void ipath_update_pio_bufs(struct ipath_devdata *dd)
/*
* Chip Errata: bug 6641; even and odd qwords>3 are swapped
*/
- if (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS))
- piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i ^ 1]);
- else
+ if (i > 3) {
+ if (i & 1)
+ piov = le64_to_cpu(
+ dd->ipath_pioavailregs_dma[i - 1]);
+ else
+ piov = le64_to_cpu(
+ dd->ipath_pioavailregs_dma[i + 1]);
+ } else
piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i]);
pchg = _IPATH_ALL_CHECKBITS &
~(dd->ipath_pioavailshadow[i] ^ piov);
@@ -1604,8 +1601,7 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd,
/* clear for security and sanity on each use */
memset(pd->port_rcvhdrq, 0, pd->port_rcvhdrq_size);
- if (pd->port_rcvhdrtail_kvaddr)
- memset(pd->port_rcvhdrtail_kvaddr, 0, PAGE_SIZE);
+ memset(pd->port_rcvhdrtail_kvaddr, 0, PAGE_SIZE);
/*
* tell chip each time we init it, even if we are re-using previous
@@ -1621,6 +1617,77 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd,
return ret;
}
+int ipath_waitfor_complete(struct ipath_devdata *dd, ipath_kreg reg_id,
+ u64 bits_to_wait_for, u64 * valp)
+{
+ unsigned long timeout;
+ u64 lastval, val;
+ int ret;
+
+ lastval = ipath_read_kreg64(dd, reg_id);
+ /* wait a ridiculously long time */
+ timeout = jiffies + msecs_to_jiffies(5);
+ do {
+ val = ipath_read_kreg64(dd, reg_id);
+ /* set so they have something, even on failures. */
+ *valp = val;
+ if ((val & bits_to_wait_for) == bits_to_wait_for) {
+ ret = 0;
+ break;
+ }
+ if (val != lastval)
+ ipath_cdbg(VERBOSE, "Changed from %llx to %llx, "
+ "waiting for %llx bits\n",
+ (unsigned long long) lastval,
+ (unsigned long long) val,
+ (unsigned long long) bits_to_wait_for);
+ cond_resched();
+ if (time_after(jiffies, timeout)) {
+ ipath_dbg("Didn't get bits %llx in register 0x%x, "
+ "got %llx\n",
+ (unsigned long long) bits_to_wait_for,
+ reg_id, (unsigned long long) *valp);
+ ret = -ENODEV;
+ break;
+ }
+ } while (1);
+
+ return ret;
+}
+
+/**
+ * ipath_waitfor_mdio_cmdready - wait for last command to complete
+ * @dd: the infinipath device
+ *
+ * Like ipath_waitfor_complete(), but we wait for the CMDVALID bit to go
+ * away indicating the last command has completed. It doesn't return data
+ */
+int ipath_waitfor_mdio_cmdready(struct ipath_devdata *dd)
+{
+ unsigned long timeout;
+ u64 val;
+ int ret;
+
+ /* wait a ridiculously long time */
+ timeout = jiffies + msecs_to_jiffies(5);
+ do {
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_mdio);
+ if (!(val & IPATH_MDIO_CMDVALID)) {
+ ret = 0;
+ break;
+ }
+ cond_resched();
+ if (time_after(jiffies, timeout)) {
+ ipath_dbg("CMDVALID stuck in mdio reg? (%llx)\n",
+ (unsigned long long) val);
+ ret = -ENODEV;
+ break;
+ }
+ } while (1);
+
+ return ret;
+}
+
/*
* Flush all sends that might be in the ready to send state, as well as any
@@ -1989,8 +2056,6 @@ void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val)
*/
void ipath_shutdown_device(struct ipath_devdata *dd)
{
- unsigned long flags;
-
ipath_dbg("Shutting down the device\n");
dd->ipath_flags |= IPATH_LINKUNK;
@@ -2011,13 +2076,9 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
* gracefully stop all sends allowing any in progress to trickle out
* first.
*/
- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
- dd->ipath_sendctrl = 0;
- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0ULL);
/* flush it */
ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
-
/*
* enough for anything that's going to trickle out to have actually
* done so.
@@ -2274,34 +2335,5 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv)
}
return 0;
}
-
-/*
- * Disable and enable the armlaunch error. Used for PIO bandwidth testing on
- * the 7220, which is count-based, rather than trigger-based. Safe for the
- * driver check, since it's at init. Not completely safe when used for
- * user-mode checking, since some error checking can be lost, but not
- * particularly risky, and only has problematic side-effects in the face of
- * very buggy user code. There is no reference counting, but that's also
- * fine, given the intended use.
- */
-void ipath_enable_armlaunch(struct ipath_devdata *dd)
-{
- dd->ipath_lasterror &= ~INFINIPATH_E_SPIOARMLAUNCH;
- ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
- INFINIPATH_E_SPIOARMLAUNCH);
- dd->ipath_errormask |= INFINIPATH_E_SPIOARMLAUNCH;
- ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
- dd->ipath_errormask);
-}
-
-void ipath_disable_armlaunch(struct ipath_devdata *dd)
-{
- /* so don't re-enable if already set */
- dd->ipath_maskederrs &= ~INFINIPATH_E_SPIOARMLAUNCH;
- dd->ipath_errormask &= ~INFINIPATH_E_SPIOARMLAUNCH;
- ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
- dd->ipath_errormask);
-}
-
module_init(infinipath_init);
module_exit(infinipath_cleanup);
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_eeprom.c b/trunk/drivers/infiniband/hw/ipath/ipath_eeprom.c
index e28a42f53769..e7c25dbbcdc9 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_eeprom.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_eeprom.c
@@ -510,10 +510,10 @@ int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
{
int ret;
- ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
+ ret = down_interruptible(&dd->ipath_eep_sem);
if (!ret) {
ret = ipath_eeprom_internal_read(dd, eeprom_offset, buff, len);
- mutex_unlock(&dd->ipath_eep_lock);
+ up(&dd->ipath_eep_sem);
}
return ret;
@@ -524,10 +524,10 @@ int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
{
int ret;
- ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
+ ret = down_interruptible(&dd->ipath_eep_sem);
if (!ret) {
ret = ipath_eeprom_internal_write(dd, eeprom_offset, buff, len);
- mutex_unlock(&dd->ipath_eep_lock);
+ up(&dd->ipath_eep_sem);
}
return ret;
@@ -574,7 +574,7 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
struct ipath_devdata *dd0 = ipath_lookup(0);
if (t && dd0->ipath_nguid > 1 && t <= dd0->ipath_nguid) {
- u8 oguid;
+ u8 *bguid, oguid;
dd->ipath_guid = dd0->ipath_guid;
bguid = (u8 *) & dd->ipath_guid;
@@ -616,9 +616,9 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
goto bail;
}
- mutex_lock(&dd->ipath_eep_lock);
+ down(&dd->ipath_eep_sem);
eep_stat = ipath_eeprom_internal_read(dd, 0, buf, len);
- mutex_unlock(&dd->ipath_eep_lock);
+ up(&dd->ipath_eep_sem);
if (eep_stat) {
ipath_dev_err(dd, "Failed reading GUID from eeprom\n");
@@ -674,6 +674,7 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
* elsewhere for backward-compatibility.
*/
char *snp = dd->ipath_serial;
+ int len;
memcpy(snp, ifp->if_sprefix, sizeof ifp->if_sprefix);
snp[sizeof ifp->if_sprefix] = '\0';
len = strlen(snp);
@@ -763,14 +764,14 @@ int ipath_update_eeprom_log(struct ipath_devdata *dd)
/* Grab semaphore and read current EEPROM. If we get an
* error, let go, but if not, keep it until we finish write.
*/
- ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
+ ret = down_interruptible(&dd->ipath_eep_sem);
if (ret) {
ipath_dev_err(dd, "Unable to acquire EEPROM for logging\n");
goto free_bail;
}
ret = ipath_eeprom_internal_read(dd, 0, buf, len);
if (ret) {
- mutex_unlock(&dd->ipath_eep_lock);
+ up(&dd->ipath_eep_sem);
ipath_dev_err(dd, "Unable read EEPROM for logging\n");
goto free_bail;
}
@@ -778,7 +779,7 @@ int ipath_update_eeprom_log(struct ipath_devdata *dd)
csum = flash_csum(ifp, 0);
if (csum != ifp->if_csum) {
- mutex_unlock(&dd->ipath_eep_lock);
+ up(&dd->ipath_eep_sem);
ipath_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n",
csum, ifp->if_csum);
ret = 1;
@@ -848,7 +849,7 @@ int ipath_update_eeprom_log(struct ipath_devdata *dd)
csum = flash_csum(ifp, 1);
ret = ipath_eeprom_internal_write(dd, 0, buf, hi_water + 1);
}
- mutex_unlock(&dd->ipath_eep_lock);
+ up(&dd->ipath_eep_sem);
if (ret)
ipath_dev_err(dd, "Failed updating EEPROM\n");
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c b/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 7e025c8e01b6..5de3243a47c3 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -169,7 +169,7 @@ static int ipath_get_base_info(struct file *fp,
kinfo->spi_piocnt = dd->ipath_pbufsport;
kinfo->spi_piobufbase = (u64) pd->port_piobufs;
kinfo->__spi_uregbase = (u64) dd->ipath_uregbase +
- dd->ipath_ureg_align * pd->port_port;
+ dd->ipath_palign * pd->port_port;
} else if (master) {
kinfo->spi_piocnt = (dd->ipath_pbufsport / subport_cnt) +
(dd->ipath_pbufsport % subport_cnt);
@@ -186,7 +186,7 @@ static int ipath_get_base_info(struct file *fp,
}
if (shared) {
kinfo->spi_port_uregbase = (u64) dd->ipath_uregbase +
- dd->ipath_ureg_align * pd->port_port;
+ dd->ipath_palign * pd->port_port;
kinfo->spi_port_rcvegrbuf = kinfo->spi_rcv_egrbufs;
kinfo->spi_port_rcvhdr_base = kinfo->spi_rcvhdr_base;
kinfo->spi_port_rcvhdr_tailaddr = kinfo->spi_rcvhdr_tailaddr;
@@ -742,12 +742,11 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport,
* updated and correct itself, even in the face of software
* bugs.
*/
- if (pd->port_rcvhdrtail_kvaddr)
- ipath_clear_rcvhdrtail(pd);
- set_bit(dd->ipath_r_portenable_shift + pd->port_port,
+ *(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0;
+ set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
&dd->ipath_rcvctrl);
} else
- clear_bit(dd->ipath_r_portenable_shift + pd->port_port,
+ clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
&dd->ipath_rcvctrl);
ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
dd->ipath_rcvctrl);
@@ -882,7 +881,7 @@ static int ipath_create_user_egr(struct ipath_portdata *pd)
egrcnt = dd->ipath_rcvegrcnt;
/* TID number offset for this port */
- egroff = (pd->port_port - 1) * egrcnt + dd->ipath_p0_rcvegrcnt;
+ egroff = pd->port_port * egrcnt;
egrsize = dd->ipath_rcvegrbufsize;
ipath_cdbg(VERBOSE, "Allocating %d egr buffers, at egrtid "
"offset %x, egrsize %u\n", egrcnt, egroff, egrsize);
@@ -1050,6 +1049,11 @@ static int mmap_piobufs(struct vm_area_struct *vma,
phys = dd->ipath_physaddr + piobufs;
+ /*
+ * Don't mark this as non-cached, or we don't get the
+ * write combining behavior we want on the PIO buffers!
+ */
+
#if defined(__powerpc__)
/* There isn't a generic way to specify writethrough mappings */
pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
@@ -1116,24 +1120,33 @@ static int mmap_rcvegrbufs(struct vm_area_struct *vma,
}
/*
- * ipath_file_vma_fault - handle a VMA page fault.
+ * ipath_file_vma_nopage - handle a VMA page fault.
*/
-static int ipath_file_vma_fault(struct vm_area_struct *vma,
- struct vm_fault *vmf)
+static struct page *ipath_file_vma_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
{
- struct page *page;
+ unsigned long offset = address - vma->vm_start;
+ struct page *page = NOPAGE_SIGBUS;
+ void *pageptr;
- page = vmalloc_to_page((void *)(vmf->pgoff << PAGE_SHIFT));
+ /*
+ * Convert the vmalloc address into a struct page.
+ */
+ pageptr = (void *)(offset + (vma->vm_pgoff << PAGE_SHIFT));
+ page = vmalloc_to_page(pageptr);
if (!page)
- return VM_FAULT_SIGBUS;
- get_page(page);
- vmf->page = page;
+ goto out;
- return 0;
+ /* Increment the reference count. */
+ get_page(page);
+ if (type)
+ *type = VM_FAULT_MINOR;
+out:
+ return page;
}
static struct vm_operations_struct ipath_file_vm_ops = {
- .fault = ipath_file_vma_fault,
+ .nopage = ipath_file_vma_nopage,
};
static int mmap_kvaddr(struct vm_area_struct *vma, u64 pgaddr,
@@ -1271,7 +1284,7 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma)
goto bail;
}
- ureg = dd->ipath_uregbase + dd->ipath_ureg_align * pd->port_port;
+ ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
if (!pd->port_subport_cnt) {
/* port is not shared */
piocnt = dd->ipath_pbufsport;
@@ -1387,10 +1400,7 @@ static unsigned int ipath_poll_next(struct ipath_portdata *pd,
pollflag = ipath_poll_hdrqfull(pd);
head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port);
- if (pd->port_rcvhdrtail_kvaddr)
- tail = ipath_get_rcvhdrtail(pd);
- else
- tail = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
+ tail = *(volatile u64 *)pd->port_rcvhdrtail_kvaddr;
if (head != tail)
pollflag |= POLLIN | POLLRDNORM;
@@ -1400,7 +1410,7 @@ static unsigned int ipath_poll_next(struct ipath_portdata *pd,
/* flush waiting flag so we don't miss an event */
wmb();
- set_bit(pd->port_port + dd->ipath_r_intravail_shift,
+ set_bit(pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT,
&dd->ipath_rcvctrl);
ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
@@ -1780,7 +1790,6 @@ static int find_shared_port(struct file *fp,
}
port_fp(fp) = pd;
subport_fp(fp) = pd->port_cnt++;
- pd->port_subpid[subport_fp(fp)] = current->pid;
tidcursor_fp(fp) = 0;
pd->active_slaves |= 1 << subport_fp(fp);
ipath_cdbg(PROC,
@@ -1911,7 +1920,8 @@ static int ipath_do_user_init(struct file *fp,
*/
head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port);
ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port);
- pd->port_lastrcvhdrqtail = -1;
+ dd->ipath_lastegrheads[pd->port_port] = -1;
+ dd->ipath_lastrcvhdrqtails[pd->port_port] = -1;
ipath_cdbg(VERBOSE, "Wrote port%d egrhead %x from tail regs\n",
pd->port_port, head32);
pd->port_tidcursor = 0; /* start at beginning after open */
@@ -1931,13 +1941,11 @@ static int ipath_do_user_init(struct file *fp,
* We explictly set the in-memory copy to 0 beforehand, so we don't
* have to wait to be sure the DMA update has happened.
*/
- if (pd->port_rcvhdrtail_kvaddr)
- ipath_clear_rcvhdrtail(pd);
- set_bit(dd->ipath_r_portenable_shift + pd->port_port,
+ *(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0ULL;
+ set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
&dd->ipath_rcvctrl);
ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
- dd->ipath_rcvctrl &
- ~(1ULL << dd->ipath_r_tailupd_shift));
+ dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD);
ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
dd->ipath_rcvctrl);
/* Notify any waiting slaves */
@@ -2014,7 +2022,6 @@ static int ipath_close(struct inode *in, struct file *fp)
* the slave(s) don't wait for receive data forever.
*/
pd->active_slaves &= ~(1 << fd->subport);
- pd->port_subpid[fd->subport] = 0;
mutex_unlock(&ipath_mutex);
goto bail;
}
@@ -2047,9 +2054,9 @@ static int ipath_close(struct inode *in, struct file *fp)
if (dd->ipath_kregbase) {
int i;
/* atomically clear receive enable port and intr avail. */
- clear_bit(dd->ipath_r_portenable_shift + port,
+ clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + port,
&dd->ipath_rcvctrl);
- clear_bit(pd->port_port + dd->ipath_r_intravail_shift,
+ clear_bit(pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT,
&dd->ipath_rcvctrl);
ipath_write_kreg( dd, dd->ipath_kregs->kr_rcvctrl,
dd->ipath_rcvctrl);
@@ -2142,15 +2149,11 @@ static int ipath_get_slave_info(struct ipath_portdata *pd,
static int ipath_force_pio_avail_update(struct ipath_devdata *dd)
{
- unsigned long flags;
+ u64 reg = dd->ipath_sendctrl;
- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ clear_bit(IPATH_S_PIOBUFAVAILUPD, ®);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, reg);
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
return 0;
}
@@ -2224,11 +2227,6 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
dest = &cmd.cmd.poll_type;
src = &ucmd->cmd.poll_type;
break;
- case IPATH_CMD_ARMLAUNCH_CTRL:
- copy = sizeof(cmd.cmd.armlaunch_ctrl);
- dest = &cmd.cmd.armlaunch_ctrl;
- src = &ucmd->cmd.armlaunch_ctrl;
- break;
default:
ret = -EINVAL;
goto bail;
@@ -2304,12 +2302,6 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
case IPATH_CMD_POLL_TYPE:
pd->poll_type = cmd.cmd.poll_type;
break;
- case IPATH_CMD_ARMLAUNCH_CTRL:
- if (cmd.cmd.armlaunch_ctrl)
- ipath_enable_armlaunch(pd->port_dd);
- else
- ipath_disable_armlaunch(pd->port_dd);
- break;
}
if (ret >= 0)
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_fs.c b/trunk/drivers/infiniband/hw/ipath/ipath_fs.c
index 23faba9d21eb..262c25db05cd 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -108,16 +108,21 @@ static const struct file_operations atomic_stats_ops = {
.read = atomic_stats_read,
};
+#define NUM_COUNTERS sizeof(struct infinipath_counters) / sizeof(u64)
+
static ssize_t atomic_counters_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct infinipath_counters counters;
+ u64 counters[NUM_COUNTERS];
+ u16 i;
struct ipath_devdata *dd;
dd = file->f_path.dentry->d_inode->i_private;
- dd->ipath_f_read_counters(dd, &counters);
- return simple_read_from_buffer(buf, count, ppos, &counters,
+ for (i = 0; i < NUM_COUNTERS; i++)
+ counters[i] = ipath_snap_cntr(dd, i);
+
+ return simple_read_from_buffer(buf, count, ppos, counters,
sizeof counters);
}
@@ -238,7 +243,8 @@ static int create_device_files(struct super_block *sb,
snprintf(unit, sizeof unit, "%02d", dd->ipath_unit);
ret = create_file(unit, S_IFDIR|S_IRUGO|S_IXUGO, sb->s_root, &dir,
- &simple_dir_operations, dd);
+ (struct file_operations *) &simple_dir_operations,
+ dd);
if (ret) {
printk(KERN_ERR "create_file(%s) failed: %d\n", unit, ret);
goto bail;
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_iba6110.c b/trunk/drivers/infiniband/hw/ipath/ipath_iba6110.c
index 9e2ced3cdc5e..ddbebe4bdb27 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_iba6110.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_iba6110.c
@@ -148,57 +148,10 @@ struct _infinipath_do_not_use_kernel_regs {
unsigned long long ReservedSW2[4];
};
-struct _infinipath_do_not_use_counters {
- __u64 LBIntCnt;
- __u64 LBFlowStallCnt;
- __u64 Reserved1;
- __u64 TxUnsupVLErrCnt;
- __u64 TxDataPktCnt;
- __u64 TxFlowPktCnt;
- __u64 TxDwordCnt;
- __u64 TxLenErrCnt;
- __u64 TxMaxMinLenErrCnt;
- __u64 TxUnderrunCnt;
- __u64 TxFlowStallCnt;
- __u64 TxDroppedPktCnt;
- __u64 RxDroppedPktCnt;
- __u64 RxDataPktCnt;
- __u64 RxFlowPktCnt;
- __u64 RxDwordCnt;
- __u64 RxLenErrCnt;
- __u64 RxMaxMinLenErrCnt;
- __u64 RxICRCErrCnt;
- __u64 RxVCRCErrCnt;
- __u64 RxFlowCtrlErrCnt;
- __u64 RxBadFormatCnt;
- __u64 RxLinkProblemCnt;
- __u64 RxEBPCnt;
- __u64 RxLPCRCErrCnt;
- __u64 RxBufOvflCnt;
- __u64 RxTIDFullErrCnt;
- __u64 RxTIDValidErrCnt;
- __u64 RxPKeyMismatchCnt;
- __u64 RxP0HdrEgrOvflCnt;
- __u64 RxP1HdrEgrOvflCnt;
- __u64 RxP2HdrEgrOvflCnt;
- __u64 RxP3HdrEgrOvflCnt;
- __u64 RxP4HdrEgrOvflCnt;
- __u64 RxP5HdrEgrOvflCnt;
- __u64 RxP6HdrEgrOvflCnt;
- __u64 RxP7HdrEgrOvflCnt;
- __u64 RxP8HdrEgrOvflCnt;
- __u64 Reserved6;
- __u64 Reserved7;
- __u64 IBStatusChangeCnt;
- __u64 IBLinkErrRecoveryCnt;
- __u64 IBLinkDownedCnt;
- __u64 IBSymbolErrCnt;
-};
-
-#define IPATH_KREG_OFFSET(field) (offsetof( \
- struct _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
+#define IPATH_KREG_OFFSET(field) (offsetof(struct \
+ _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
#define IPATH_CREG_OFFSET(field) (offsetof( \
- struct _infinipath_do_not_use_counters, field) / sizeof(u64))
+ struct infinipath_counters, field) / sizeof(u64))
static const struct ipath_kregs ipath_ht_kregs = {
.kr_control = IPATH_KREG_OFFSET(Control),
@@ -329,9 +282,6 @@ static const struct ipath_cregs ipath_ht_cregs = {
#define INFINIPATH_HWE_HTAPLL_RFSLIP 0x1000000000000000ULL
#define INFINIPATH_HWE_SERDESPLLFAILED 0x2000000000000000ULL
-#define IBA6110_IBCS_LINKTRAININGSTATE_MASK 0xf
-#define IBA6110_IBCS_LINKSTATE_SHIFT 4
-
/* kr_extstatus bits */
#define INFINIPATH_EXTS_FREQSEL 0x2
#define INFINIPATH_EXTS_SERDESSEL 0x4
@@ -346,12 +296,6 @@ static const struct ipath_cregs ipath_ht_cregs = {
#define INFINIPATH_RT_BUFSIZE_MASK 0x3FFFULL
#define INFINIPATH_RT_BUFSIZE_SHIFT 48
-#define INFINIPATH_R_INTRAVAIL_SHIFT 16
-#define INFINIPATH_R_TAILUPD_SHIFT 31
-
-/* kr_xgxsconfig bits */
-#define INFINIPATH_XGXS_RESET 0x7ULL
-
/*
* masks and bits that are different in different chips, or present only
* in one
@@ -708,6 +652,7 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
"with ID %u\n", boardrev);
snprintf(name, namelen, "Unknown_InfiniPath_QHT7xxx_%u",
boardrev);
+ ret = 1;
break;
}
if (n)
@@ -741,13 +686,6 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
dd->ipath_htspeed);
ret = 0;
- /*
- * set here, not in ipath_init_*_funcs because we have to do
- * it after we can read chip registers.
- */
- dd->ipath_ureg_align =
- ipath_read_kreg32(dd, dd->ipath_kregs->kr_pagealign);
-
bail:
return ret;
}
@@ -1031,8 +969,7 @@ static int ipath_setup_ht_config(struct ipath_devdata *dd,
do {
u8 cap_type;
- /*
- * The HT capability type byte is 3 bytes after the
+ /* the HT capability type byte is 3 bytes after the
* capability byte.
*/
if (pci_read_config_byte(pdev, pos + 3, &cap_type)) {
@@ -1045,8 +982,6 @@ static int ipath_setup_ht_config(struct ipath_devdata *dd,
} while ((pos = pci_find_next_capability(pdev, pos,
PCI_CAP_ID_HT)));
- dd->ipath_flags |= IPATH_SWAP_PIOBUFS;
-
bail:
return ret;
}
@@ -1139,55 +1074,11 @@ static void ipath_setup_ht_setextled(struct ipath_devdata *dd,
static void ipath_init_ht_variables(struct ipath_devdata *dd)
{
- /*
- * setup the register offsets, since they are different for each
- * chip
- */
- dd->ipath_kregs = &ipath_ht_kregs;
- dd->ipath_cregs = &ipath_ht_cregs;
-
dd->ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
dd->ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
dd->ipath_gpio_sda = IPATH_GPIO_SDA;
dd->ipath_gpio_scl = IPATH_GPIO_SCL;
- /*
- * Fill in data for field-values that change in newer chips.
- * We dynamically specify only the mask for LINKTRAININGSTATE
- * and only the shift for LINKSTATE, as they are the only ones
- * that change. Also precalculate the 3 link states of interest
- * and the combined mask.
- */
- dd->ibcs_ls_shift = IBA6110_IBCS_LINKSTATE_SHIFT;
- dd->ibcs_lts_mask = IBA6110_IBCS_LINKTRAININGSTATE_MASK;
- dd->ibcs_mask = (INFINIPATH_IBCS_LINKSTATE_MASK <<
- dd->ibcs_ls_shift) | dd->ibcs_lts_mask;
- dd->ib_init = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
- INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
- (INFINIPATH_IBCS_L_STATE_INIT << dd->ibcs_ls_shift);
- dd->ib_arm = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
- INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
- (INFINIPATH_IBCS_L_STATE_ARM << dd->ibcs_ls_shift);
- dd->ib_active = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
- INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
- (INFINIPATH_IBCS_L_STATE_ACTIVE << dd->ibcs_ls_shift);
-
- /*
- * Fill in data for ibcc field-values that change in newer chips.
- * We dynamically specify only the mask for LINKINITCMD
- * and only the shift for LINKCMD and MAXPKTLEN, as they are
- * the only ones that change.
- */
- dd->ibcc_lic_mask = INFINIPATH_IBCC_LINKINITCMD_MASK;
- dd->ibcc_lc_shift = INFINIPATH_IBCC_LINKCMD_SHIFT;
- dd->ibcc_mpl_shift = INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
-
- /* Fill in shifts for RcvCtrl. */
- dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT;
- dd->ipath_r_intravail_shift = INFINIPATH_R_INTRAVAIL_SHIFT;
- dd->ipath_r_tailupd_shift = INFINIPATH_R_TAILUPD_SHIFT;
- dd->ipath_r_portcfg_shift = 0; /* Not on IBA6110 */
-
dd->ipath_i_bitsextant =
(INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |
(INFINIPATH_I_RCVAVAIL_MASK <<
@@ -1244,8 +1135,6 @@ static void ipath_init_ht_variables(struct ipath_devdata *dd)
dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
- dd->ipath_i_rcvavail_shift = INFINIPATH_I_RCVAVAIL_SHIFT;
- dd->ipath_i_rcvurg_shift = INFINIPATH_I_RCVURG_SHIFT;
/*
* EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
@@ -1259,17 +1148,9 @@ static void ipath_init_ht_variables(struct ipath_devdata *dd)
INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
- dd->ipath_eep_st_masks[2].errs_to_log = INFINIPATH_E_RESET;
+ dd->ipath_eep_st_masks[2].errs_to_log =
+ INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
- dd->delay_mult = 2; /* SDR, 4X, can't change */
-
- dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
- dd->ipath_link_speed_supported = IPATH_IB_SDR;
- dd->ipath_link_width_enabled = IB_WIDTH_4X;
- dd->ipath_link_speed_enabled = dd->ipath_link_speed_supported;
- /* these can't change for this chip, so set once */
- dd->ipath_link_width_active = dd->ipath_link_width_enabled;
- dd->ipath_link_speed_active = dd->ipath_link_speed_enabled;
}
/**
@@ -1324,16 +1205,14 @@ static void ipath_ht_init_hwerrors(struct ipath_devdata *dd)
val &= ~INFINIPATH_HWE_HTCMISCERR4;
/*
- * PLL ignored because unused MDIO interface has a logic problem
+ * PLL ignored because MDIO interface has a logic problem
+ * for reads, on Comstock and Ponderosa. BRINGUP
*/
if (dd->ipath_boardrev == 4 || dd->ipath_boardrev == 9)
val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
dd->ipath_hwerrmask = val;
}
-
-
-
/**
* ipath_ht_bringup_serdes - bring up the serdes
* @dd: the infinipath device
@@ -1405,6 +1284,16 @@ static int ipath_ht_bringup_serdes(struct ipath_devdata *dd)
}
val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+ if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &
+ INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {
+ val &= ~(INFINIPATH_XGXS_MDIOADDR_MASK <<
+ INFINIPATH_XGXS_MDIOADDR_SHIFT);
+ /*
+ * we use address 3
+ */
+ val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;
+ change = 1;
+ }
if (val & INFINIPATH_XGXS_RESET) {
/* normally true after boot */
val &= ~INFINIPATH_XGXS_RESET;
@@ -1440,6 +1329,21 @@ static int ipath_ht_bringup_serdes(struct ipath_devdata *dd)
(unsigned long long)
ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+ if (!ipath_waitfor_mdio_cmdready(dd)) {
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_mdio,
+ ipath_mdio_req(IPATH_MDIO_CMD_READ, 31,
+ IPATH_MDIO_CTRL_XGXS_REG_8,
+ 0));
+ if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio,
+ IPATH_MDIO_DATAVALID, &val))
+ ipath_dbg("Never got MDIO data for XGXS status "
+ "read\n");
+ else
+ ipath_cdbg(VERBOSE, "MDIO Read reg8, "
+ "'bank' 31 %x\n", (u32) val);
+ } else
+ ipath_dbg("Never got MDIO cmdready for XGXS status read\n");
+
return ret; /* for now, say we always succeeded */
}
@@ -1492,7 +1396,6 @@ static void ipath_ht_put_tid(struct ipath_devdata *dd,
pa |= lenvalid | INFINIPATH_RT_VALID;
}
}
-
writeq(pa, tidptr);
}
@@ -1623,7 +1526,8 @@ static int ipath_ht_early_init(struct ipath_devdata *dd)
}
ipath_get_eeprom_info(dd);
- if (dd->ipath_boardrev == 5) {
+ if (dd->ipath_boardrev == 5 && dd->ipath_serial[0] == '1' &&
+ dd->ipath_serial[1] == '2' && dd->ipath_serial[2] == '8') {
/*
* Later production QHT7040 has same changes as QHT7140, so
* can use GPIO interrupts. They have serial #'s starting
@@ -1698,210 +1602,6 @@ static void ipath_ht_free_irq(struct ipath_devdata *dd)
dd->ipath_intconfig = 0;
}
-static struct ipath_message_header *
-ipath_ht_get_msgheader(struct ipath_devdata *dd, __le32 *rhf_addr)
-{
- return (struct ipath_message_header *)
- &rhf_addr[sizeof(u64) / sizeof(u32)];
-}
-
-static void ipath_ht_config_ports(struct ipath_devdata *dd, ushort cfgports)
-{
- dd->ipath_portcnt =
- ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
- dd->ipath_p0_rcvegrcnt =
- ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt);
-}
-
-static void ipath_ht_read_counters(struct ipath_devdata *dd,
- struct infinipath_counters *cntrs)
-{
- cntrs->LBIntCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBIntCnt));
- cntrs->LBFlowStallCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBFlowStallCnt));
- cntrs->TxSDmaDescCnt = 0;
- cntrs->TxUnsupVLErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnsupVLErrCnt));
- cntrs->TxDataPktCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDataPktCnt));
- cntrs->TxFlowPktCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowPktCnt));
- cntrs->TxDwordCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDwordCnt));
- cntrs->TxLenErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxLenErrCnt));
- cntrs->TxMaxMinLenErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxMaxMinLenErrCnt));
- cntrs->TxUnderrunCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnderrunCnt));
- cntrs->TxFlowStallCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowStallCnt));
- cntrs->TxDroppedPktCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDroppedPktCnt));
- cntrs->RxDroppedPktCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDroppedPktCnt));
- cntrs->RxDataPktCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDataPktCnt));
- cntrs->RxFlowPktCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowPktCnt));
- cntrs->RxDwordCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDwordCnt));
- cntrs->RxLenErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLenErrCnt));
- cntrs->RxMaxMinLenErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxMaxMinLenErrCnt));
- cntrs->RxICRCErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxICRCErrCnt));
- cntrs->RxVCRCErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxVCRCErrCnt));
- cntrs->RxFlowCtrlErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowCtrlErrCnt));
- cntrs->RxBadFormatCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBadFormatCnt));
- cntrs->RxLinkProblemCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLinkProblemCnt));
- cntrs->RxEBPCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxEBPCnt));
- cntrs->RxLPCRCErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLPCRCErrCnt));
- cntrs->RxBufOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBufOvflCnt));
- cntrs->RxTIDFullErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDFullErrCnt));
- cntrs->RxTIDValidErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDValidErrCnt));
- cntrs->RxPKeyMismatchCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxPKeyMismatchCnt));
- cntrs->RxP0HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt));
- cntrs->RxP1HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP1HdrEgrOvflCnt));
- cntrs->RxP2HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP2HdrEgrOvflCnt));
- cntrs->RxP3HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP3HdrEgrOvflCnt));
- cntrs->RxP4HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP4HdrEgrOvflCnt));
- cntrs->RxP5HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP5HdrEgrOvflCnt));
- cntrs->RxP6HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP6HdrEgrOvflCnt));
- cntrs->RxP7HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP7HdrEgrOvflCnt));
- cntrs->RxP8HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP8HdrEgrOvflCnt));
- cntrs->RxP9HdrEgrOvflCnt = 0;
- cntrs->RxP10HdrEgrOvflCnt = 0;
- cntrs->RxP11HdrEgrOvflCnt = 0;
- cntrs->RxP12HdrEgrOvflCnt = 0;
- cntrs->RxP13HdrEgrOvflCnt = 0;
- cntrs->RxP14HdrEgrOvflCnt = 0;
- cntrs->RxP15HdrEgrOvflCnt = 0;
- cntrs->RxP16HdrEgrOvflCnt = 0;
- cntrs->IBStatusChangeCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBStatusChangeCnt));
- cntrs->IBLinkErrRecoveryCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt));
- cntrs->IBLinkDownedCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkDownedCnt));
- cntrs->IBSymbolErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBSymbolErrCnt));
- cntrs->RxVL15DroppedPktCnt = 0;
- cntrs->RxOtherLocalPhyErrCnt = 0;
- cntrs->PcieRetryBufDiagQwordCnt = 0;
- cntrs->ExcessBufferOvflCnt = dd->ipath_overrun_thresh_errs;
- cntrs->LocalLinkIntegrityErrCnt =
- (dd->ipath_flags & IPATH_GPIO_ERRINTRS) ?
- dd->ipath_lli_errs : dd->ipath_lli_errors;
- cntrs->RxVlErrCnt = 0;
- cntrs->RxDlidFltrCnt = 0;
-}
-
-
-/* no interrupt fallback for these chips */
-static int ipath_ht_nointr_fallback(struct ipath_devdata *dd)
-{
- return 0;
-}
-
-
-/*
- * reset the XGXS (between serdes and IBC). Slightly less intrusive
- * than resetting the IBC or external link state, and useful in some
- * cases to cause some retraining. To do this right, we reset IBC
- * as well.
- */
-static void ipath_ht_xgxs_reset(struct ipath_devdata *dd)
-{
- u64 val, prev_val;
-
- prev_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
- val = prev_val | INFINIPATH_XGXS_RESET;
- prev_val &= ~INFINIPATH_XGXS_RESET; /* be sure */
- ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
- dd->ipath_control & ~INFINIPATH_C_LINKENABLE);
- ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
- ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
- ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, prev_val);
- ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
- dd->ipath_control);
-}
-
-
-static int ipath_ht_get_ib_cfg(struct ipath_devdata *dd, int which)
-{
- int ret;
-
- switch (which) {
- case IPATH_IB_CFG_LWID:
- ret = dd->ipath_link_width_active;
- break;
- case IPATH_IB_CFG_SPD:
- ret = dd->ipath_link_speed_active;
- break;
- case IPATH_IB_CFG_LWID_ENB:
- ret = dd->ipath_link_width_enabled;
- break;
- case IPATH_IB_CFG_SPD_ENB:
- ret = dd->ipath_link_speed_enabled;
- break;
- default:
- ret = -ENOTSUPP;
- break;
- }
- return ret;
-}
-
-
-/* we assume range checking is already done, if needed */
-static int ipath_ht_set_ib_cfg(struct ipath_devdata *dd, int which, u32 val)
-{
- int ret = 0;
-
- if (which == IPATH_IB_CFG_LWID_ENB)
- dd->ipath_link_width_enabled = val;
- else if (which == IPATH_IB_CFG_SPD_ENB)
- dd->ipath_link_speed_enabled = val;
- else
- ret = -ENOTSUPP;
- return ret;
-}
-
-
-static void ipath_ht_config_jint(struct ipath_devdata *dd, u16 a, u16 b)
-{
-}
-
-
-static int ipath_ht_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
-{
- ipath_setup_ht_setextled(dd, ipath_ib_linkstate(dd, ibcs),
- ipath_ib_linktrstate(dd, ibcs));
- return 0;
-}
-
-
/**
* ipath_init_iba6110_funcs - set up the chip-specific function pointers
* @dd: the infinipath device
@@ -1926,19 +1626,22 @@ void ipath_init_iba6110_funcs(struct ipath_devdata *dd)
dd->ipath_f_setextled = ipath_setup_ht_setextled;
dd->ipath_f_get_base_info = ipath_ht_get_base_info;
dd->ipath_f_free_irq = ipath_ht_free_irq;
- dd->ipath_f_tidtemplate = ipath_ht_tidtemplate;
- dd->ipath_f_intr_fallback = ipath_ht_nointr_fallback;
- dd->ipath_f_get_msgheader = ipath_ht_get_msgheader;
- dd->ipath_f_config_ports = ipath_ht_config_ports;
- dd->ipath_f_read_counters = ipath_ht_read_counters;
- dd->ipath_f_xgxs_reset = ipath_ht_xgxs_reset;
- dd->ipath_f_get_ib_cfg = ipath_ht_get_ib_cfg;
- dd->ipath_f_set_ib_cfg = ipath_ht_set_ib_cfg;
- dd->ipath_f_config_jint = ipath_ht_config_jint;
- dd->ipath_f_ib_updown = ipath_ht_ib_updown;
/*
* initialize chip-specific variables
*/
+ dd->ipath_f_tidtemplate = ipath_ht_tidtemplate;
+
+ /*
+ * setup the register offsets, since they are different for each
+ * chip
+ */
+ dd->ipath_kregs = &ipath_ht_kregs;
+ dd->ipath_cregs = &ipath_ht_cregs;
+
+ /*
+ * do very early init that is needed before ipath_f_bus is
+ * called
+ */
ipath_init_ht_variables(dd);
}
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c b/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c
index c7a2f50824c0..0103d6f4847b 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c
@@ -145,57 +145,10 @@ struct _infinipath_do_not_use_kernel_regs {
unsigned long long Reserved12;
};
-struct _infinipath_do_not_use_counters {
- __u64 LBIntCnt;
- __u64 LBFlowStallCnt;
- __u64 Reserved1;
- __u64 TxUnsupVLErrCnt;
- __u64 TxDataPktCnt;
- __u64 TxFlowPktCnt;
- __u64 TxDwordCnt;
- __u64 TxLenErrCnt;
- __u64 TxMaxMinLenErrCnt;
- __u64 TxUnderrunCnt;
- __u64 TxFlowStallCnt;
- __u64 TxDroppedPktCnt;
- __u64 RxDroppedPktCnt;
- __u64 RxDataPktCnt;
- __u64 RxFlowPktCnt;
- __u64 RxDwordCnt;
- __u64 RxLenErrCnt;
- __u64 RxMaxMinLenErrCnt;
- __u64 RxICRCErrCnt;
- __u64 RxVCRCErrCnt;
- __u64 RxFlowCtrlErrCnt;
- __u64 RxBadFormatCnt;
- __u64 RxLinkProblemCnt;
- __u64 RxEBPCnt;
- __u64 RxLPCRCErrCnt;
- __u64 RxBufOvflCnt;
- __u64 RxTIDFullErrCnt;
- __u64 RxTIDValidErrCnt;
- __u64 RxPKeyMismatchCnt;
- __u64 RxP0HdrEgrOvflCnt;
- __u64 RxP1HdrEgrOvflCnt;
- __u64 RxP2HdrEgrOvflCnt;
- __u64 RxP3HdrEgrOvflCnt;
- __u64 RxP4HdrEgrOvflCnt;
- __u64 RxP5HdrEgrOvflCnt;
- __u64 RxP6HdrEgrOvflCnt;
- __u64 RxP7HdrEgrOvflCnt;
- __u64 RxP8HdrEgrOvflCnt;
- __u64 Reserved6;
- __u64 Reserved7;
- __u64 IBStatusChangeCnt;
- __u64 IBLinkErrRecoveryCnt;
- __u64 IBLinkDownedCnt;
- __u64 IBSymbolErrCnt;
-};
-
-#define IPATH_KREG_OFFSET(field) (offsetof( \
- struct _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
+#define IPATH_KREG_OFFSET(field) (offsetof(struct \
+ _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
#define IPATH_CREG_OFFSET(field) (offsetof( \
- struct _infinipath_do_not_use_counters, field) / sizeof(u64))
+ struct infinipath_counters, field) / sizeof(u64))
static const struct ipath_kregs ipath_pe_kregs = {
.kr_control = IPATH_KREG_OFFSET(Control),
@@ -329,9 +282,6 @@ static const struct ipath_cregs ipath_pe_cregs = {
#define INFINIPATH_HWE_PCIE0PLLFAILED 0x0800000000000000ULL
#define INFINIPATH_HWE_SERDESPLLFAILED 0x1000000000000000ULL
-#define IBA6120_IBCS_LINKTRAININGSTATE_MASK 0xf
-#define IBA6120_IBCS_LINKSTATE_SHIFT 4
-
/* kr_extstatus bits */
#define INFINIPATH_EXTS_FREQSEL 0x2
#define INFINIPATH_EXTS_SERDESSEL 0x4
@@ -346,9 +296,6 @@ static const struct ipath_cregs ipath_pe_cregs = {
#define IPATH_GPIO_SCL (1ULL << \
(_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
-#define INFINIPATH_R_INTRAVAIL_SHIFT 16
-#define INFINIPATH_R_TAILUPD_SHIFT 31
-
/* 6120 specific hardware errors... */
static const struct ipath_hwerror_msgs ipath_6120_hwerror_msgs[] = {
INFINIPATH_HWE_MSG(PCIEPOISONEDTLP, "PCIe Poisoned TLP"),
@@ -373,28 +320,10 @@ static const struct ipath_hwerror_msgs ipath_6120_hwerror_msgs[] = {
INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC) \
<< INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)
+static int ipath_pe_txe_recover(struct ipath_devdata *);
static void ipath_pe_put_tid_2(struct ipath_devdata *, u64 __iomem *,
u32, unsigned long);
-/*
- * On platforms using this chip, and not having ordered WC stores, we
- * can get TXE parity errors due to speculative reads to the PIO buffers,
- * and this, due to a chip bug can result in (many) false parity error
- * reports. So it's a debug print on those, and an info print on systems
- * where the speculative reads don't occur.
- */
-static void ipath_pe_txe_recover(struct ipath_devdata *dd)
-{
- if (ipath_unordered_wc())
- ipath_dbg("Recovering from TXE PIO parity error\n");
- else {
- ++ipath_stats.sps_txeparity;
- dev_info(&dd->pcidev->dev,
- "Recovering from TXE PIO parity error\n");
- }
-}
-
-
/**
* ipath_pe_handle_hwerrors - display hardware errors.
* @dd: the infinipath device
@@ -474,11 +403,35 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
* occur if a processor speculative read is done to the PIO
* buffer while we are sending a packet, for example.
*/
- if (hwerrs & TXE_PIO_PARITY) {
- ipath_pe_txe_recover(dd);
+ if ((hwerrs & TXE_PIO_PARITY) && ipath_pe_txe_recover(dd))
hwerrs &= ~TXE_PIO_PARITY;
- }
- if (!hwerrs) {
+ if (hwerrs) {
+ /*
+ * if any set that we aren't ignoring only make the
+ * complaint once, in case it's stuck or recurring,
+ * and we get here multiple times
+ * Force link down, so switch knows, and
+ * LEDs are turned off
+ */
+ if (dd->ipath_flags & IPATH_INITTED) {
+ ipath_set_linkstate(dd, IPATH_IB_LINKDOWN);
+ ipath_setup_pe_setextled(dd,
+ INFINIPATH_IBCS_L_STATE_DOWN,
+ INFINIPATH_IBCS_LT_STATE_DISABLED);
+ ipath_dev_err(dd, "Fatal Hardware Error (freeze "
+ "mode), no longer usable, SN %.16s\n",
+ dd->ipath_serial);
+ isfatal = 1;
+ }
+ /*
+ * Mark as having had an error for driver, and also
+ * for /sys and status word mapped to user programs.
+ * This marks unit as not usable, until reset
+ */
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+ *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+ dd->ipath_flags &= ~IPATH_INITTED;
+ } else {
static u32 freeze_cnt;
freeze_cnt++;
@@ -532,7 +485,7 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) {
/*
- * If it occurs, it is left masked since the external
+ * If it occurs, it is left masked since the eternal
* interface is unused
*/
dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED;
@@ -610,14 +563,6 @@ static int ipath_pe_boardname(struct ipath_devdata *dd, char *name,
dd->ipath_f_put_tid = ipath_pe_put_tid_2;
}
-
- /*
- * set here, not in ipath_init_*_funcs because we have to do
- * it after we can read chip registers.
- */
- dd->ipath_ureg_align =
- ipath_read_kreg32(dd, dd->ipath_kregs->kr_pagealign);
-
return ret;
}
@@ -722,8 +667,17 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
prev_val = val;
- if (val & INFINIPATH_XGXS_RESET)
+ if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &
+ INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {
+ val &=
+ ~(INFINIPATH_XGXS_MDIOADDR_MASK <<
+ INFINIPATH_XGXS_MDIOADDR_SHIFT);
+ /* MDIO address 3 */
+ val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;
+ }
+ if (val & INFINIPATH_XGXS_RESET) {
val &= ~INFINIPATH_XGXS_RESET;
+ }
if (((val >> INFINIPATH_XGXS_RX_POL_SHIFT) &
INFINIPATH_XGXS_RX_POL_MASK) != dd->ipath_rx_pol_inv ) {
/* need to compensate for Tx inversion in partner */
@@ -753,6 +707,21 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
(unsigned long long)
ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+ if (!ipath_waitfor_mdio_cmdready(dd)) {
+ ipath_write_kreg(
+ dd, dd->ipath_kregs->kr_mdio,
+ ipath_mdio_req(IPATH_MDIO_CMD_READ, 31,
+ IPATH_MDIO_CTRL_XGXS_REG_8, 0));
+ if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio,
+ IPATH_MDIO_DATAVALID, &val))
+ ipath_dbg("Never got MDIO data for XGXS "
+ "status read\n");
+ else
+ ipath_cdbg(VERBOSE, "MDIO Read reg8, "
+ "'bank' 31 %x\n", (u32) val);
+ } else
+ ipath_dbg("Never got MDIO cmdready for XGXS status read\n");
+
return ret;
}
@@ -933,26 +902,11 @@ static int ipath_setup_pe_config(struct ipath_devdata *dd,
else
ipath_dev_err(dd, "Can't find PCI Express "
"capability!\n");
-
- dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
- dd->ipath_link_speed_supported = IPATH_IB_SDR;
- dd->ipath_link_width_enabled = IB_WIDTH_4X;
- dd->ipath_link_speed_enabled = dd->ipath_link_speed_supported;
- /* these can't change for this chip, so set once */
- dd->ipath_link_width_active = dd->ipath_link_width_enabled;
- dd->ipath_link_speed_active = dd->ipath_link_speed_enabled;
return 0;
}
static void ipath_init_pe_variables(struct ipath_devdata *dd)
{
- /*
- * setup the register offsets, since they are different for each
- * chip
- */
- dd->ipath_kregs = &ipath_pe_kregs;
- dd->ipath_cregs = &ipath_pe_cregs;
-
/*
* bits for selecting i2c direction and values,
* used for I2C serial flash
@@ -962,43 +916,6 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
dd->ipath_gpio_sda = IPATH_GPIO_SDA;
dd->ipath_gpio_scl = IPATH_GPIO_SCL;
- /*
- * Fill in data for field-values that change in newer chips.
- * We dynamically specify only the mask for LINKTRAININGSTATE
- * and only the shift for LINKSTATE, as they are the only ones
- * that change. Also precalculate the 3 link states of interest
- * and the combined mask.
- */
- dd->ibcs_ls_shift = IBA6120_IBCS_LINKSTATE_SHIFT;
- dd->ibcs_lts_mask = IBA6120_IBCS_LINKTRAININGSTATE_MASK;
- dd->ibcs_mask = (INFINIPATH_IBCS_LINKSTATE_MASK <<
- dd->ibcs_ls_shift) | dd->ibcs_lts_mask;
- dd->ib_init = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
- INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
- (INFINIPATH_IBCS_L_STATE_INIT << dd->ibcs_ls_shift);
- dd->ib_arm = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
- INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
- (INFINIPATH_IBCS_L_STATE_ARM << dd->ibcs_ls_shift);
- dd->ib_active = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
- INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
- (INFINIPATH_IBCS_L_STATE_ACTIVE << dd->ibcs_ls_shift);
-
- /*
- * Fill in data for ibcc field-values that change in newer chips.
- * We dynamically specify only the mask for LINKINITCMD
- * and only the shift for LINKCMD and MAXPKTLEN, as they are
- * the only ones that change.
- */
- dd->ibcc_lic_mask = INFINIPATH_IBCC_LINKINITCMD_MASK;
- dd->ibcc_lc_shift = INFINIPATH_IBCC_LINKCMD_SHIFT;
- dd->ibcc_mpl_shift = INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
-
- /* Fill in shifts for RcvCtrl. */
- dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT;
- dd->ipath_r_intravail_shift = INFINIPATH_R_INTRAVAIL_SHIFT;
- dd->ipath_r_tailupd_shift = INFINIPATH_R_TAILUPD_SHIFT;
- dd->ipath_r_portcfg_shift = 0; /* Not on IBA6120 */
-
/* variables for sanity checking interrupt and errors */
dd->ipath_hwe_bitsextant =
(INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
@@ -1046,8 +963,6 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
- dd->ipath_i_rcvavail_shift = INFINIPATH_I_RCVAVAIL_SHIFT;
- dd->ipath_i_rcvurg_shift = INFINIPATH_I_RCVURG_SHIFT;
/*
* EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
@@ -1069,7 +984,6 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
- dd->delay_mult = 2; /* SDR, 4X, can't change */
}
/* setup the MSI stuff again after a reset. I'd like to just call
@@ -1375,9 +1289,6 @@ static int ipath_pe_early_init(struct ipath_devdata *dd)
*/
dd->ipath_rcvhdrentsize = 24;
dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;
- dd->ipath_rhf_offset = 0;
- dd->ipath_egrtidbase = (u64 __iomem *)
- ((char __iomem *) dd->ipath_kregbase + dd->ipath_rcvegrbase);
/*
* To truly support a 4KB MTU (for usermode), we need to
@@ -1448,204 +1359,34 @@ static void ipath_pe_free_irq(struct ipath_devdata *dd)
dd->ipath_irq = 0;
}
-
-static struct ipath_message_header *
-ipath_pe_get_msgheader(struct ipath_devdata *dd, __le32 *rhf_addr)
-{
- return (struct ipath_message_header *)
- &rhf_addr[sizeof(u64) / sizeof(u32)];
-}
-
-static void ipath_pe_config_ports(struct ipath_devdata *dd, ushort cfgports)
-{
- dd->ipath_portcnt =
- ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
- dd->ipath_p0_rcvegrcnt =
- ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt);
-}
-
-static void ipath_pe_read_counters(struct ipath_devdata *dd,
- struct infinipath_counters *cntrs)
-{
- cntrs->LBIntCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBIntCnt));
- cntrs->LBFlowStallCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBFlowStallCnt));
- cntrs->TxSDmaDescCnt = 0;
- cntrs->TxUnsupVLErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnsupVLErrCnt));
- cntrs->TxDataPktCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDataPktCnt));
- cntrs->TxFlowPktCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowPktCnt));
- cntrs->TxDwordCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDwordCnt));
- cntrs->TxLenErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxLenErrCnt));
- cntrs->TxMaxMinLenErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxMaxMinLenErrCnt));
- cntrs->TxUnderrunCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnderrunCnt));
- cntrs->TxFlowStallCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowStallCnt));
- cntrs->TxDroppedPktCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDroppedPktCnt));
- cntrs->RxDroppedPktCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDroppedPktCnt));
- cntrs->RxDataPktCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDataPktCnt));
- cntrs->RxFlowPktCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowPktCnt));
- cntrs->RxDwordCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDwordCnt));
- cntrs->RxLenErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLenErrCnt));
- cntrs->RxMaxMinLenErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxMaxMinLenErrCnt));
- cntrs->RxICRCErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxICRCErrCnt));
- cntrs->RxVCRCErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxVCRCErrCnt));
- cntrs->RxFlowCtrlErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowCtrlErrCnt));
- cntrs->RxBadFormatCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBadFormatCnt));
- cntrs->RxLinkProblemCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLinkProblemCnt));
- cntrs->RxEBPCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxEBPCnt));
- cntrs->RxLPCRCErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLPCRCErrCnt));
- cntrs->RxBufOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBufOvflCnt));
- cntrs->RxTIDFullErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDFullErrCnt));
- cntrs->RxTIDValidErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDValidErrCnt));
- cntrs->RxPKeyMismatchCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxPKeyMismatchCnt));
- cntrs->RxP0HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt));
- cntrs->RxP1HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP1HdrEgrOvflCnt));
- cntrs->RxP2HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP2HdrEgrOvflCnt));
- cntrs->RxP3HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP3HdrEgrOvflCnt));
- cntrs->RxP4HdrEgrOvflCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP4HdrEgrOvflCnt));
- cntrs->RxP5HdrEgrOvflCnt = 0;
- cntrs->RxP6HdrEgrOvflCnt = 0;
- cntrs->RxP7HdrEgrOvflCnt = 0;
- cntrs->RxP8HdrEgrOvflCnt = 0;
- cntrs->RxP9HdrEgrOvflCnt = 0;
- cntrs->RxP10HdrEgrOvflCnt = 0;
- cntrs->RxP11HdrEgrOvflCnt = 0;
- cntrs->RxP12HdrEgrOvflCnt = 0;
- cntrs->RxP13HdrEgrOvflCnt = 0;
- cntrs->RxP14HdrEgrOvflCnt = 0;
- cntrs->RxP15HdrEgrOvflCnt = 0;
- cntrs->RxP16HdrEgrOvflCnt = 0;
- cntrs->IBStatusChangeCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBStatusChangeCnt));
- cntrs->IBLinkErrRecoveryCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt));
- cntrs->IBLinkDownedCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkDownedCnt));
- cntrs->IBSymbolErrCnt =
- ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBSymbolErrCnt));
- cntrs->RxVL15DroppedPktCnt = 0;
- cntrs->RxOtherLocalPhyErrCnt = 0;
- cntrs->PcieRetryBufDiagQwordCnt = 0;
- cntrs->ExcessBufferOvflCnt = dd->ipath_overrun_thresh_errs;
- cntrs->LocalLinkIntegrityErrCnt = dd->ipath_lli_errs;
- cntrs->RxVlErrCnt = 0;
- cntrs->RxDlidFltrCnt = 0;
-}
-
-
-/* no interrupt fallback for these chips */
-static int ipath_pe_nointr_fallback(struct ipath_devdata *dd)
-{
- return 0;
-}
-
-
/*
- * reset the XGXS (between serdes and IBC). Slightly less intrusive
- * than resetting the IBC or external link state, and useful in some
- * cases to cause some retraining. To do this right, we reset IBC
- * as well.
+ * On platforms using this chip, and not having ordered WC stores, we
+ * can get TXE parity errors due to speculative reads to the PIO buffers,
+ * and this, due to a chip bug can result in (many) false parity error
+ * reports. So it's a debug print on those, and an info print on systems
+ * where the speculative reads don't occur.
+ * Because we can get lots of false errors, we have no upper limit
+ * on recovery attempts on those platforms.
*/
-static void ipath_pe_xgxs_reset(struct ipath_devdata *dd)
-{
- u64 val, prev_val;
-
- prev_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
- val = prev_val | INFINIPATH_XGXS_RESET;
- prev_val &= ~INFINIPATH_XGXS_RESET; /* be sure */
- ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
- dd->ipath_control & ~INFINIPATH_C_LINKENABLE);
- ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
- ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
- ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, prev_val);
- ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
- dd->ipath_control);
-}
-
-
-static int ipath_pe_get_ib_cfg(struct ipath_devdata *dd, int which)
+static int ipath_pe_txe_recover(struct ipath_devdata *dd)
{
- int ret;
-
- switch (which) {
- case IPATH_IB_CFG_LWID:
- ret = dd->ipath_link_width_active;
- break;
- case IPATH_IB_CFG_SPD:
- ret = dd->ipath_link_speed_active;
- break;
- case IPATH_IB_CFG_LWID_ENB:
- ret = dd->ipath_link_width_enabled;
- break;
- case IPATH_IB_CFG_SPD_ENB:
- ret = dd->ipath_link_speed_enabled;
- break;
- default:
- ret = -ENOTSUPP;
- break;
+ if (ipath_unordered_wc())
+ ipath_dbg("Recovering from TXE PIO parity error\n");
+ else {
+ int cnt = ++ipath_stats.sps_txeparity;
+ if (cnt >= IPATH_MAX_PARITY_ATTEMPTS) {
+ if (cnt == IPATH_MAX_PARITY_ATTEMPTS)
+ ipath_dev_err(dd,
+ "Too many attempts to recover from "
+ "TXE parity, giving up\n");
+ return 0;
+ }
+ dev_info(&dd->pcidev->dev,
+ "Recovering from TXE PIO parity error\n");
}
- return ret;
-}
-
-
-/* we assume range checking is already done, if needed */
-static int ipath_pe_set_ib_cfg(struct ipath_devdata *dd, int which, u32 val)
-{
- int ret = 0;
-
- if (which == IPATH_IB_CFG_LWID_ENB)
- dd->ipath_link_width_enabled = val;
- else if (which == IPATH_IB_CFG_SPD_ENB)
- dd->ipath_link_speed_enabled = val;
- else
- ret = -ENOTSUPP;
- return ret;
+ return 1;
}
-static void ipath_pe_config_jint(struct ipath_devdata *dd, u16 a, u16 b)
-{
-}
-
-
-static int ipath_pe_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
-{
- ipath_setup_pe_setextled(dd, ipath_ib_linkstate(dd, ibcs),
- ipath_ib_linktrstate(dd, ibcs));
- return 0;
-}
-
-
/**
* ipath_init_iba6120_funcs - set up the chip-specific function pointers
* @dd: the infinipath device
@@ -1666,7 +1407,7 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd)
dd->ipath_f_bringup_serdes = ipath_pe_bringup_serdes;
dd->ipath_f_clear_tids = ipath_pe_clear_tids;
/*
- * _f_put_tid may get changed after we read the chip revision,
+ * this may get changed after we read the chip revision,
* but we start with the safe version for all revs
*/
dd->ipath_f_put_tid = ipath_pe_put_tid;
@@ -1674,19 +1415,17 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd)
dd->ipath_f_setextled = ipath_setup_pe_setextled;
dd->ipath_f_get_base_info = ipath_pe_get_base_info;
dd->ipath_f_free_irq = ipath_pe_free_irq;
+
+ /* initialize chip-specific variables */
dd->ipath_f_tidtemplate = ipath_pe_tidtemplate;
- dd->ipath_f_intr_fallback = ipath_pe_nointr_fallback;
- dd->ipath_f_xgxs_reset = ipath_pe_xgxs_reset;
- dd->ipath_f_get_msgheader = ipath_pe_get_msgheader;
- dd->ipath_f_config_ports = ipath_pe_config_ports;
- dd->ipath_f_read_counters = ipath_pe_read_counters;
- dd->ipath_f_get_ib_cfg = ipath_pe_get_ib_cfg;
- dd->ipath_f_set_ib_cfg = ipath_pe_set_ib_cfg;
- dd->ipath_f_config_jint = ipath_pe_config_jint;
- dd->ipath_f_ib_updown = ipath_pe_ib_updown;
+ /*
+ * setup the register offsets, since they are different for each
+ * chip
+ */
+ dd->ipath_kregs = &ipath_pe_kregs;
+ dd->ipath_cregs = &ipath_pe_cregs;
- /* initialize chip-specific variables */
ipath_init_pe_variables(dd);
}
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_init_chip.c b/trunk/drivers/infiniband/hw/ipath/ipath_init_chip.c
index 4471674975cd..9dd0bacf8461 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_init_chip.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -91,7 +91,7 @@ static int create_port0_egr(struct ipath_devdata *dd)
struct ipath_skbinfo *skbinfo;
int ret;
- egrcnt = dd->ipath_p0_rcvegrcnt;
+ egrcnt = dd->ipath_rcvegrcnt;
skbinfo = vmalloc(sizeof(*dd->ipath_port0_skbinfo) * egrcnt);
if (skbinfo == NULL) {
@@ -244,7 +244,8 @@ static int init_chip_first(struct ipath_devdata *dd,
* cfgports. We do still check and report a difference, if
* not same (should be impossible).
*/
- dd->ipath_f_config_ports(dd, ipath_cfgports);
+ dd->ipath_portcnt =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
if (!ipath_cfgports)
dd->ipath_cfgports = dd->ipath_portcnt;
else if (ipath_cfgports <= dd->ipath_portcnt) {
@@ -271,7 +272,22 @@ static int init_chip_first(struct ipath_devdata *dd,
goto done;
}
+ dd->ipath_lastegrheads = kzalloc(sizeof(*dd->ipath_lastegrheads)
+ * dd->ipath_cfgports,
+ GFP_KERNEL);
+ dd->ipath_lastrcvhdrqtails =
+ kzalloc(sizeof(*dd->ipath_lastrcvhdrqtails)
+ * dd->ipath_cfgports, GFP_KERNEL);
+
+ if (!dd->ipath_lastegrheads || !dd->ipath_lastrcvhdrqtails) {
+ ipath_dev_err(dd, "Unable to allocate head arrays, "
+ "failing\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+
pd = create_portdata0(dd);
+
if (!pd) {
ipath_dev_err(dd, "Unable to allocate portdata for port "
"0, failing\n");
@@ -329,10 +345,10 @@ static int init_chip_first(struct ipath_devdata *dd,
dd->ipath_piobcnt2k, dd->ipath_pio2kbase);
spin_lock_init(&dd->ipath_tid_lock);
- spin_lock_init(&dd->ipath_sendctrl_lock);
+
spin_lock_init(&dd->ipath_gpio_lock);
spin_lock_init(&dd->ipath_eep_st_lock);
- mutex_init(&dd->ipath_eep_lock);
+ sema_init(&dd->ipath_eep_sem, 1);
done:
*pdp = pd;
@@ -356,9 +372,9 @@ static int init_chip_reset(struct ipath_devdata *dd,
*pdp = dd->ipath_pd[0];
/* ensure chip does no sends or receives while we re-initialize */
dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U;
- ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, dd->ipath_rcvctrl);
- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
- ipath_write_kreg(dd, dd->ipath_kregs->kr_control, dd->ipath_control);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, 0);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0);
rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
if (dd->ipath_portcnt != rtmp)
@@ -471,7 +487,6 @@ static void enable_chip(struct ipath_devdata *dd,
struct ipath_portdata *pd, int reinit)
{
u32 val;
- unsigned long flags;
int i;
if (!reinit)
@@ -480,21 +495,19 @@ static void enable_chip(struct ipath_devdata *dd,
ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
dd->ipath_rcvctrl);
- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
/* Enable PIO send, and update of PIOavail regs to memory. */
dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE |
INFINIPATH_S_PIOBUFAVAILUPD;
- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
/*
* enable port 0 receive, and receive interrupt. other ports
* done as user opens and inits them.
*/
- dd->ipath_rcvctrl = (1ULL << dd->ipath_r_tailupd_shift) |
- (1ULL << dd->ipath_r_portenable_shift) |
- (1ULL << dd->ipath_r_intravail_shift);
+ dd->ipath_rcvctrl = INFINIPATH_R_TAILUPD |
+ (1ULL << INFINIPATH_R_PORTENABLE_SHIFT) |
+ (1ULL << INFINIPATH_R_INTRAVAIL_SHIFT);
ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
dd->ipath_rcvctrl);
@@ -510,11 +523,12 @@ static void enable_chip(struct ipath_devdata *dd,
*/
val = ipath_read_ureg32(dd, ur_rcvegrindextail, 0);
(void)ipath_write_ureg(dd, ur_rcvegrindexhead, val, 0);
+ dd->ipath_port0head = ipath_read_ureg32(dd, ur_rcvhdrtail, 0);
/* Initialize so we interrupt on next packet received */
(void)ipath_write_ureg(dd, ur_rcvhdrhead,
dd->ipath_rhdrhead_intr_off |
- dd->ipath_pd[0]->port_head, 0);
+ dd->ipath_port0head, 0);
/*
* by now pioavail updates to memory should have occurred, so
@@ -528,8 +542,12 @@ static void enable_chip(struct ipath_devdata *dd,
/*
* Chip Errata bug 6641; even and odd qwords>3 are swapped.
*/
- if (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS))
- val = dd->ipath_pioavailregs_dma[i ^ 1];
+ if (i > 3) {
+ if (i & 1)
+ val = dd->ipath_pioavailregs_dma[i - 1];
+ else
+ val = dd->ipath_pioavailregs_dma[i + 1];
+ }
else
val = dd->ipath_pioavailregs_dma[i];
dd->ipath_pioavailshadow[i] = le64_to_cpu(val);
@@ -672,13 +690,12 @@ static int init_housekeeping(struct ipath_devdata *dd,
*/
int ipath_init_chip(struct ipath_devdata *dd, int reinit)
{
- int ret = 0;
+ int ret = 0, i;
u32 val32, kpiobufs;
u32 piobufs, uports;
u64 val;
struct ipath_portdata *pd = NULL; /* keep gcc4 happy */
gfp_t gfp_flags = GFP_USER | __GFP_COMP;
- unsigned long flags;
ret = init_housekeeping(dd, &pd, reinit);
if (ret)
@@ -729,7 +746,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
kpiobufs = ipath_kpiobufs;
if (kpiobufs + (uports * IPATH_MIN_USER_PORT_BUFCNT) > piobufs) {
- int i = (int) piobufs -
+ i = (int) piobufs -
(int) (uports * IPATH_MIN_USER_PORT_BUFCNT);
if (i < 0)
i = 0;
@@ -810,12 +827,8 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
~0ULL&~INFINIPATH_HWE_MEMBISTFAILED);
ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0ULL);
-
- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
- dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE;
- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ INFINIPATH_S_PIOENABLE);
/*
* before error clears, since we expect serdes pll errors during
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_intr.c b/trunk/drivers/infiniband/hw/ipath/ipath_intr.c
index 92e58c921522..c61f9da2964a 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -683,7 +683,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
for (i = 0; i < dd->ipath_cfgports; i++) {
struct ipath_portdata *pd = dd->ipath_pd[i];
if (i == 0) {
- hd = pd->port_head;
+ hd = dd->ipath_port0head;
tl = (u32) le64_to_cpu(
*dd->ipath_hdrqtailptr);
} else if (pd && pd->port_cnt &&
@@ -693,7 +693,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
* except kernel
*/
tl = *(u64 *) pd->port_rcvhdrtail_kvaddr;
- if (tl == pd->port_lastrcvhdrqtail)
+ if (tl == dd->ipath_lastrcvhdrqtails[i])
continue;
hd = ipath_read_ureg32(dd, ur_rcvhdrhead,
i);
@@ -703,7 +703,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
(!hd && tl == dd->ipath_hdrqlast)) {
if (i == 0)
chkerrpkts = 1;
- pd->port_lastrcvhdrqtail = tl;
+ dd->ipath_lastrcvhdrqtails[i] = tl;
pd->port_hdrqfull++;
/* flush hdrqfull so that poll() sees it */
wmb();
@@ -712,8 +712,6 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
}
}
if (errs & INFINIPATH_E_RRCVEGRFULL) {
- struct ipath_portdata *pd = dd->ipath_pd[0];
-
/*
* since this is of less importance and not likely to
* happen without also getting hdrfull, only count
@@ -721,7 +719,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
* vs user)
*/
ipath_stats.sps_etidfull++;
- if (pd->port_head !=
+ if (dd->ipath_port0head !=
(u32) le64_to_cpu(*dd->ipath_hdrqtailptr))
chkerrpkts = 1;
}
@@ -797,7 +795,6 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
{
int i, im;
__le64 val;
- unsigned long flags;
/* disable error interrupts, to avoid confusion */
ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL);
@@ -816,14 +813,11 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
dd->ipath_control);
/* ensure pio avail updates continue */
- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- dd->ipath_sendctrl);
- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+ dd->ipath_sendctrl);
/*
* We just enabled pioavailupdate, so dma copy is almost certainly
@@ -831,8 +825,8 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
*/
for (i = 0; i < dd->ipath_pioavregs; i++) {
/* deal with 6110 chip bug */
- im = i > 3 ? i ^ 1 : i;
- val = ipath_read_kreg64(dd, (0x1000 / sizeof(u64)) + im);
+ im = i > 3 ? ((i&1) ? i-1 : i+1) : i;
+ val = ipath_read_kreg64(dd, (0x1000/sizeof(u64))+im);
dd->ipath_pioavailregs_dma[i] = dd->ipath_pioavailshadow[i]
= le64_to_cpu(val);
}
@@ -855,7 +849,7 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
/* this is separate to allow for better optimization of ipath_intr() */
-static noinline void ipath_bad_intr(struct ipath_devdata *dd, u32 *unexpectp)
+static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
{
/*
* sometimes happen during driver init and unload, don't want
@@ -883,7 +877,7 @@ static noinline void ipath_bad_intr(struct ipath_devdata *dd, u32 *unexpectp)
dd->ipath_f_free_irq(dd);
}
}
- if (ipath_read_ireg(dd, dd->ipath_kregs->kr_intmask)) {
+ if (ipath_read_kreg32(dd, dd->ipath_kregs->kr_intmask)) {
ipath_dev_err(dd, "%u unexpected interrupts, "
"disabling interrupts completely\n",
*unexpectp);
@@ -898,7 +892,7 @@ static noinline void ipath_bad_intr(struct ipath_devdata *dd, u32 *unexpectp)
"ignoring\n");
}
-static noinline void ipath_bad_regread(struct ipath_devdata *dd)
+static void ipath_bad_regread(struct ipath_devdata *dd)
{
static int allbits;
@@ -926,9 +920,31 @@ static noinline void ipath_bad_regread(struct ipath_devdata *dd)
}
}
+static void handle_port_pioavail(struct ipath_devdata *dd)
+{
+ u32 i;
+ /*
+ * start from port 1, since for now port 0 is never using
+ * wait_event for PIO
+ */
+ for (i = 1; dd->ipath_portpiowait && i < dd->ipath_cfgports; i++) {
+ struct ipath_portdata *pd = dd->ipath_pd[i];
+
+ if (pd && pd->port_cnt &&
+ dd->ipath_portpiowait & (1U << i)) {
+ clear_bit(i, &dd->ipath_portpiowait);
+ if (test_bit(IPATH_PORT_WAITING_PIO,
+ &pd->port_flag)) {
+ clear_bit(IPATH_PORT_WAITING_PIO,
+ &pd->port_flag);
+ wake_up_interruptible(&pd->port_wait);
+ }
+ }
+ }
+}
+
static void handle_layer_pioavail(struct ipath_devdata *dd)
{
- unsigned long flags;
int ret;
ret = ipath_ib_piobufavail(dd->verbs_dev);
@@ -937,12 +953,9 @@ static void handle_layer_pioavail(struct ipath_devdata *dd)
return;
set:
- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
- dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
+ set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
dd->ipath_sendctrl);
- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
}
/*
@@ -956,15 +969,7 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
int i;
int rcvdint = 0;
- /*
- * test_and_clear_bit(IPATH_PORT_WAITING_RCV) and
- * test_and_clear_bit(IPATH_PORT_WAITING_URG) below
- * would both like timely updates of the bits so that
- * we don't pass them by unnecessarily. the rmb()
- * here ensures that we see them promptly -- the
- * corresponding wmb()'s are in ipath_poll_urgent()
- * and ipath_poll_next()...
- */
+ /* test_bit below needs this... */
rmb();
portr = ((istat >> INFINIPATH_I_RCVAVAIL_SHIFT) &
dd->ipath_i_rcvavail_mask)
@@ -975,7 +980,7 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
if (portr & (1 << i) && pd && pd->port_cnt) {
if (test_and_clear_bit(IPATH_PORT_WAITING_RCV,
&pd->port_flag)) {
- clear_bit(i + dd->ipath_r_intravail_shift,
+ clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT,
&dd->ipath_rcvctrl);
wake_up_interruptible(&pd->port_wait);
rcvdint = 1;
@@ -1034,7 +1039,7 @@ irqreturn_t ipath_intr(int irq, void *data)
goto bail;
}
- istat = ipath_read_ireg(dd, dd->ipath_kregs->kr_intstatus);
+ istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus);
if (unlikely(!istat)) {
ipath_stats.sps_nullintr++;
@@ -1175,7 +1180,7 @@ irqreturn_t ipath_intr(int irq, void *data)
* for receive are at the bottom.
*/
if (chk0rcv) {
- ipath_kreceive(dd->ipath_pd[0]);
+ ipath_kreceive(dd);
istat &= ~port0rbits;
}
@@ -1186,14 +1191,12 @@ irqreturn_t ipath_intr(int irq, void *data)
handle_urcv(dd, istat);
if (istat & INFINIPATH_I_SPIOBUFAVAIL) {
- unsigned long flags;
-
- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
- dd->ipath_sendctrl &= ~INFINIPATH_S_PIOINTBUFAVAIL;
+ clear_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
dd->ipath_sendctrl);
- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+
+ if (dd->ipath_portpiowait)
+ handle_port_pioavail(dd);
handle_layer_pioavail(dd);
}
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_kernel.h b/trunk/drivers/infiniband/hw/ipath/ipath_kernel.h
index 4cc0f95ea877..bb1dc075f1d1 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -41,7 +41,6 @@
#include
#include
#include
-#include
#include
#include
@@ -141,11 +140,6 @@ struct ipath_portdata {
u32 port_pionowait;
/* total number of rcvhdrqfull errors */
u32 port_hdrqfull;
- /*
- * Used to suppress multiple instances of same
- * port staying stuck at same point.
- */
- u32 port_lastrcvhdrqtail;
/* saved total number of rcvhdrqfull errors for poll edge trigger */
u32 port_hdrqfull_poll;
/* total number of polled urgent packets */
@@ -154,7 +148,6 @@ struct ipath_portdata {
u32 port_urgent_poll;
/* pid of process using this port */
pid_t port_pid;
- pid_t port_subpid[INFINIPATH_MAX_SUBPORT];
/* same size as task_struct .comm[] */
char port_comm[16];
/* pkeys set by this use of this port */
@@ -173,8 +166,6 @@ struct ipath_portdata {
u32 active_slaves;
/* Type of packets or conditions we want to poll for */
u16 poll_type;
- /* port rcvhdrq head offset */
- u32 port_head;
};
struct sk_buff;
@@ -191,22 +182,6 @@ struct ipath_skbinfo {
dma_addr_t phys;
};
-/*
- * Possible IB config parameters for ipath_f_get/set_ib_cfg()
- */
-#define IPATH_IB_CFG_LIDLMC 0 /* Get/set LID (LS16b) and Mask (MS16b) */
-#define IPATH_IB_CFG_HRTBT 1 /* Get/set Heartbeat off/enable/auto */
-#define IPATH_IB_HRTBT_ON 3 /* Heartbeat enabled, sent every 100msec */
-#define IPATH_IB_HRTBT_OFF 0 /* Heartbeat off */
-#define IPATH_IB_CFG_LWID_ENB 2 /* Get/set allowed Link-width */
-#define IPATH_IB_CFG_LWID 3 /* Get currently active Link-width */
-#define IPATH_IB_CFG_SPD_ENB 4 /* Get/set allowed Link speeds */
-#define IPATH_IB_CFG_SPD 5 /* Get current Link spd */
-#define IPATH_IB_CFG_RXPOL_ENB 6 /* Get/set Auto-RX-polarity enable */
-#define IPATH_IB_CFG_LREV_ENB 7 /* Get/set Auto-Lane-reversal enable */
-#define IPATH_IB_CFG_LINKLATENCY 8 /* Get Auto-Lane-reversal enable */
-
-
struct ipath_devdata {
struct list_head ipath_list;
@@ -247,8 +222,6 @@ struct ipath_devdata {
struct _ipath_layer ipath_layer;
/* setup intr */
int (*ipath_f_intrsetup)(struct ipath_devdata *);
- /* fallback to alternate interrupt type if possible */
- int (*ipath_f_intr_fallback)(struct ipath_devdata *);
/* setup on-chip bus config */
int (*ipath_f_bus)(struct ipath_devdata *, struct pci_dev *);
/* hard reset chip */
@@ -271,18 +244,6 @@ struct ipath_devdata {
int (*ipath_f_get_base_info)(struct ipath_portdata *, void *);
/* free irq */
void (*ipath_f_free_irq)(struct ipath_devdata *);
- struct ipath_message_header *(*ipath_f_get_msgheader)
- (struct ipath_devdata *, __le32 *);
- void (*ipath_f_config_ports)(struct ipath_devdata *, ushort);
- int (*ipath_f_get_ib_cfg)(struct ipath_devdata *, int);
- int (*ipath_f_set_ib_cfg)(struct ipath_devdata *, int, u32);
- void (*ipath_f_config_jint)(struct ipath_devdata *, u16 , u16);
- void (*ipath_f_read_counters)(struct ipath_devdata *,
- struct infinipath_counters *);
- void (*ipath_f_xgxs_reset)(struct ipath_devdata *);
- /* per chip actions needed for IB Link up/down changes */
- int (*ipath_f_ib_updown)(struct ipath_devdata *, int, u64);
-
struct ipath_ibdev *verbs_dev;
struct timer_list verbs_timer;
/* total dwords sent (summed from counter) */
@@ -352,11 +313,21 @@ struct ipath_devdata {
* supports, less gives more pio bufs/port, etc.
*/
u32 ipath_cfgports;
+ /* port0 rcvhdrq head offset */
+ u32 ipath_port0head;
/* count of port 0 hdrqfull errors */
u32 ipath_p0_hdrqfull;
- /* port 0 number of receive eager buffers */
- u32 ipath_p0_rcvegrcnt;
+ /*
+ * (*cfgports) used to suppress multiple instances of same
+ * port staying stuck at same point
+ */
+ u32 *ipath_lastrcvhdrqtails;
+ /*
+ * (*cfgports) used to suppress multiple instances of same
+ * port staying stuck at same point
+ */
+ u32 *ipath_lastegrheads;
/*
* index of last piobuffer we used. Speeds up searching, by
* starting at this point. Doesn't matter if multiple cpu's use and
@@ -396,15 +367,14 @@ struct ipath_devdata {
unsigned long ipath_wc_len;
/* ref count for each pkey */
atomic_t ipath_pkeyrefs[4];
+ /* shadow copy of all exptids physaddr; used only by funcsim */
+ u64 *ipath_tidsimshadow;
/* shadow copy of struct page *'s for exp tid pages */
struct page **ipath_pageshadow;
/* shadow copy of dma handles for exp tid pages */
dma_addr_t *ipath_physshadow;
- u64 __iomem *ipath_egrtidbase;
- /* lock to workaround chip bug 9437 and others */
- spinlock_t ipath_kernel_tid_lock;
+ /* lock to workaround chip bug 9437 */
spinlock_t ipath_tid_lock;
- spinlock_t ipath_sendctrl_lock;
/*
* IPATH_STATUS_*,
@@ -425,8 +395,6 @@ struct ipath_devdata {
void *ipath_dummy_hdrq; /* used after port close */
dma_addr_t ipath_dummy_hdrq_phys;
- unsigned long ipath_ureg_align; /* user register alignment */
-
/*
* Shadow copies of registers; size indicates read access size.
* Most of them are readonly, but some are write-only register,
@@ -488,6 +456,8 @@ struct ipath_devdata {
unsigned long ipath_rcvctrl;
/* shadow kr_sendctrl */
unsigned long ipath_sendctrl;
+ /* ports waiting for PIOavail intr */
+ unsigned long ipath_portpiowait;
unsigned long ipath_lastcancel; /* to not count armlaunch after cancel */
/* value we put in kr_rcvhdrcnt */
@@ -580,26 +550,12 @@ struct ipath_devdata {
u8 ipath_minrev;
/* board rev, from ipath_revision */
u8 ipath_boardrev;
-
- u8 ipath_r_portenable_shift;
- u8 ipath_r_intravail_shift;
- u8 ipath_r_tailupd_shift;
- u8 ipath_r_portcfg_shift;
-
/* unit # of this chip, if present */
int ipath_unit;
/* saved for restore after reset */
u8 ipath_pci_cacheline;
/* LID mask control */
u8 ipath_lmc;
- /* link width supported */
- u8 ipath_link_width_supported;
- /* link speed supported */
- u8 ipath_link_speed_supported;
- u8 ipath_link_width_enabled;
- u8 ipath_link_speed_enabled;
- u8 ipath_link_width_active;
- u8 ipath_link_speed_active;
/* Rx Polarity inversion (compensate for ~tx on partner) */
u8 ipath_rx_pol_inv;
@@ -634,8 +590,6 @@ struct ipath_devdata {
*/
u32 ipath_i_rcvavail_mask;
u32 ipath_i_rcvurg_mask;
- u16 ipath_i_rcvurg_shift;
- u16 ipath_i_rcvavail_shift;
/*
* Register bits for selecting i2c direction and values, used for
@@ -649,29 +603,6 @@ struct ipath_devdata {
/* lock for doing RMW of shadows/regs for ExtCtrl and GPIO */
spinlock_t ipath_gpio_lock;
- /*
- * IB link and linktraining states and masks that vary per chip in
- * some way. Set at init, to avoid each IB status change interrupt
- */
- u8 ibcs_ls_shift;
- u8 ibcs_lts_mask;
- u32 ibcs_mask;
- u32 ib_init;
- u32 ib_arm;
- u32 ib_active;
-
- u16 ipath_rhf_offset; /* offset of RHF within receive header entry */
-
- /*
- * shift/mask for linkcmd, linkinitcmd, maxpktlen in ibccontol
- * reg. Changes for IBA7220
- */
- u8 ibcc_lic_mask; /* LinkInitCmd */
- u8 ibcc_lc_shift; /* LinkCmd */
- u8 ibcc_mpl_shift; /* Maxpktlen */
-
- u8 delay_mult;
-
/* used to override LED behavior */
u8 ipath_led_override; /* Substituted for normal value, if non-zero */
u16 ipath_led_override_timeoff; /* delta to next timer event */
@@ -685,7 +616,7 @@ struct ipath_devdata {
/* control access to actual counters, timer */
spinlock_t ipath_eep_st_lock;
/* control high-level access to EEPROM */
- struct mutex ipath_eep_lock;
+ struct semaphore ipath_eep_sem;
/* Below inc'd by ipath_snap_cntrs(), locked by ipath_eep_st_lock */
uint64_t ipath_traffic_wds;
/* active time is kept in seconds, but logged in hours */
@@ -699,10 +630,6 @@ struct ipath_devdata {
* each of the counters to increment.
*/
struct ipath_eep_log_mask ipath_eep_st_masks[IPATH_EEP_LOG_CNT];
-
- /* interrupt mitigation reload register info */
- u16 ipath_jint_idle_ticks; /* idle clock ticks */
- u16 ipath_jint_max_packets; /* max packets across all ports */
};
/* Private data for file operations */
@@ -763,7 +690,7 @@ void ipath_free_pddata(struct ipath_devdata *, struct ipath_portdata *);
int ipath_parse_ushort(const char *str, unsigned short *valp);
-void ipath_kreceive(struct ipath_portdata *);
+void ipath_kreceive(struct ipath_devdata *);
int ipath_setrcvhdrsize(struct ipath_devdata *, unsigned);
int ipath_reset_device(int);
void ipath_get_faststats(unsigned long);
@@ -771,8 +698,6 @@ int ipath_set_linkstate(struct ipath_devdata *, u8);
int ipath_set_mtu(struct ipath_devdata *, u16);
int ipath_set_lid(struct ipath_devdata *, u32, u8);
int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
-void ipath_enable_armlaunch(struct ipath_devdata *);
-void ipath_disable_armlaunch(struct ipath_devdata *);
/* for use in system calls, where we want to know device type, etc. */
#define port_fp(fp) ((struct ipath_filedata *)(fp)->private_data)->pd
@@ -819,15 +744,9 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
* are 64bit */
#define IPATH_32BITCOUNTERS 0x20000
/* can miss port0 rx interrupts */
- /* Interrupt register is 64 bits */
-#define IPATH_INTREG_64 0x40000
#define IPATH_DISABLED 0x80000 /* administratively disabled */
/* Use GPIO interrupts for new counters */
#define IPATH_GPIO_ERRINTRS 0x100000
-#define IPATH_SWAP_PIOBUFS 0x200000
- /* Suppress heartbeat, even if turning off loopback */
-#define IPATH_NO_HRTBT 0x1000000
-#define IPATH_HAS_MULT_IB_SPEED 0x8000000
/* Bits in GPIO for the added interrupts */
#define IPATH_GPIO_PORT0_BIT 2
@@ -839,6 +758,8 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
/* portdata flag bit offsets */
/* waiting for a packet to arrive */
#define IPATH_PORT_WAITING_RCV 2
+ /* waiting for a PIO buffer to be available */
+#define IPATH_PORT_WAITING_PIO 3
/* master has not finished initializing */
#define IPATH_PORT_MASTER_UNINIT 4
/* waiting for an urgent packet to arrive */
@@ -846,6 +767,8 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
/* free up any allocated data at closes */
void ipath_free_data(struct ipath_portdata *dd);
+int ipath_waitfor_mdio_cmdready(struct ipath_devdata *);
+int ipath_waitfor_complete(struct ipath_devdata *, ipath_kreg, u64, u64 *);
u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *);
void ipath_init_iba6120_funcs(struct ipath_devdata *);
void ipath_init_iba6110_funcs(struct ipath_devdata *);
@@ -869,6 +792,33 @@ void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val);
*/
#define IPATH_DFLT_RCVHDRSIZE 9
+#define IPATH_MDIO_CMD_WRITE 1
+#define IPATH_MDIO_CMD_READ 2
+#define IPATH_MDIO_CLD_DIV 25 /* to get 2.5 Mhz mdio clock */
+#define IPATH_MDIO_CMDVALID 0x40000000 /* bit 30 */
+#define IPATH_MDIO_DATAVALID 0x80000000 /* bit 31 */
+#define IPATH_MDIO_CTRL_STD 0x0
+
+static inline u64 ipath_mdio_req(int cmd, int dev, int reg, int data)
+{
+ return (((u64) IPATH_MDIO_CLD_DIV) << 32) |
+ (cmd << 26) |
+ (dev << 21) |
+ (reg << 16) |
+ (data & 0xFFFF);
+}
+
+ /* signal and fifo status, in bank 31 */
+#define IPATH_MDIO_CTRL_XGXS_REG_8 0x8
+ /* controls loopback, redundancy */
+#define IPATH_MDIO_CTRL_8355_REG_1 0x10
+ /* premph, encdec, etc. */
+#define IPATH_MDIO_CTRL_8355_REG_2 0x11
+ /* Kchars, etc. */
+#define IPATH_MDIO_CTRL_8355_REG_6 0x15
+#define IPATH_MDIO_CTRL_8355_REG_9 0x18
+#define IPATH_MDIO_CTRL_8355_REG_10 0x1D
+
int ipath_get_user_pages(unsigned long, size_t, struct page **);
void ipath_release_user_pages(struct page **, size_t);
void ipath_release_user_pages_on_close(struct page **, size_t);
@@ -913,7 +863,7 @@ static inline u32 ipath_read_ureg32(const struct ipath_devdata *dd,
return readl(regno + (u64 __iomem *)
(dd->ipath_uregbase +
(char __iomem *)dd->ipath_kregbase +
- dd->ipath_ureg_align * port));
+ dd->ipath_palign * port));
}
/**
@@ -930,7 +880,7 @@ static inline void ipath_write_ureg(const struct ipath_devdata *dd,
{
u64 __iomem *ubase = (u64 __iomem *)
(dd->ipath_uregbase + (char __iomem *) dd->ipath_kregbase +
- dd->ipath_ureg_align * port);
+ dd->ipath_palign * port);
if (dd->ipath_kregbase)
writeq(value, &ubase[regno]);
}
@@ -980,53 +930,6 @@ static inline u32 ipath_read_creg32(const struct ipath_devdata *dd,
(char __iomem *)dd->ipath_kregbase));
}
-static inline void ipath_write_creg(const struct ipath_devdata *dd,
- ipath_creg regno, u64 value)
-{
- if (dd->ipath_kregbase)
- writeq(value, regno + (u64 __iomem *)
- (dd->ipath_cregbase +
- (char __iomem *)dd->ipath_kregbase));
-}
-
-static inline void ipath_clear_rcvhdrtail(const struct ipath_portdata *pd)
-{
- *((u64 *) pd->port_rcvhdrtail_kvaddr) = 0ULL;
-}
-
-static inline u32 ipath_get_rcvhdrtail(const struct ipath_portdata *pd)
-{
- return (u32) le64_to_cpu(*((volatile __le64 *)
- pd->port_rcvhdrtail_kvaddr));
-}
-
-static inline u64 ipath_read_ireg(const struct ipath_devdata *dd, ipath_kreg r)
-{
- return (dd->ipath_flags & IPATH_INTREG_64) ?
- ipath_read_kreg64(dd, r) : ipath_read_kreg32(dd, r);
-}
-
-/*
- * from contents of IBCStatus (or a saved copy), return linkstate
- * Report ACTIVE_DEFER as ACTIVE, because we treat them the same
- * everywhere, anyway (and should be, for almost all purposes).
- */
-static inline u32 ipath_ib_linkstate(struct ipath_devdata *dd, u64 ibcs)
-{
- u32 state = (u32)(ibcs >> dd->ibcs_ls_shift) &
- INFINIPATH_IBCS_LINKSTATE_MASK;
- if (state == INFINIPATH_IBCS_L_STATE_ACT_DEFER)
- state = INFINIPATH_IBCS_L_STATE_ACTIVE;
- return state;
-}
-
-/* from contents of IBCStatus (or a saved copy), return linktrainingstate */
-static inline u32 ipath_ib_linktrstate(struct ipath_devdata *dd, u64 ibcs)
-{
- return (u32)(ibcs >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
- dd->ibcs_lts_mask;
-}
-
/*
* sysfs interface.
*/
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_keys.c b/trunk/drivers/infiniband/hw/ipath/ipath_keys.c
index 8f32b17a5eed..85a4aefc6c03 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_keys.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_keys.c
@@ -128,8 +128,9 @@ int ipath_lkey_ok(struct ipath_qp *qp, struct ipath_sge *isge,
int ret;
/*
- * We use LKEY == zero for kernel virtual addresses
- * (see ipath_get_dma_mr and ipath_dma.c).
+ * We use LKEY == zero to mean a physical kmalloc() address.
+ * This is a bit of a hack since we rely on dma_map_single()
+ * being reversible by calling bus_to_virt().
*/
if (sge->lkey == 0) {
struct ipath_pd *pd = to_ipd(qp->ibqp.pd);
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_mad.c b/trunk/drivers/infiniband/hw/ipath/ipath_mad.c
index d98d5f103700..3d1432d1e3f4 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -934,7 +934,6 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
struct ib_pma_portsamplescontrol *p =
(struct ib_pma_portsamplescontrol *)pmp->data;
struct ipath_ibdev *dev = to_idev(ibdev);
- struct ipath_cregs const *crp = dev->dd->ipath_cregs;
unsigned long flags;
u8 port_select = p->port_select;
@@ -956,10 +955,7 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
p->counter_width = 4; /* 32 bit counters */
p->counter_mask0_9 = COUNTER_MASK0_9;
spin_lock_irqsave(&dev->pending_lock, flags);
- if (crp->cr_psstat)
- p->sample_status = ipath_read_creg32(dev->dd, crp->cr_psstat);
- else
- p->sample_status = dev->pma_sample_status;
+ p->sample_status = dev->pma_sample_status;
p->sample_start = cpu_to_be32(dev->pma_sample_start);
p->sample_interval = cpu_to_be32(dev->pma_sample_interval);
p->tag = cpu_to_be16(dev->pma_tag);
@@ -979,9 +975,8 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
struct ib_pma_portsamplescontrol *p =
(struct ib_pma_portsamplescontrol *)pmp->data;
struct ipath_ibdev *dev = to_idev(ibdev);
- struct ipath_cregs const *crp = dev->dd->ipath_cregs;
unsigned long flags;
- u8 status;
+ u32 start;
int ret;
if (pmp->attr_mod != 0 ||
@@ -991,67 +986,59 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
goto bail;
}
- spin_lock_irqsave(&dev->pending_lock, flags);
- if (crp->cr_psstat)
- status = ipath_read_creg32(dev->dd, crp->cr_psstat);
- else
- status = dev->pma_sample_status;
- if (status == IB_PMA_SAMPLE_STATUS_DONE) {
- dev->pma_sample_start = be32_to_cpu(p->sample_start);
- dev->pma_sample_interval = be32_to_cpu(p->sample_interval);
- dev->pma_tag = be16_to_cpu(p->tag);
- dev->pma_counter_select[0] = p->counter_select[0];
- dev->pma_counter_select[1] = p->counter_select[1];
- dev->pma_counter_select[2] = p->counter_select[2];
- dev->pma_counter_select[3] = p->counter_select[3];
- dev->pma_counter_select[4] = p->counter_select[4];
- if (crp->cr_psstat) {
- ipath_write_creg(dev->dd, crp->cr_psinterval,
- dev->pma_sample_interval);
- ipath_write_creg(dev->dd, crp->cr_psstart,
- dev->pma_sample_start);
- } else
- dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_STARTED;
+ start = be32_to_cpu(p->sample_start);
+ if (start != 0) {
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_DONE) {
+ dev->pma_sample_status =
+ IB_PMA_SAMPLE_STATUS_STARTED;
+ dev->pma_sample_start = start;
+ dev->pma_sample_interval =
+ be32_to_cpu(p->sample_interval);
+ dev->pma_tag = be16_to_cpu(p->tag);
+ if (p->counter_select[0])
+ dev->pma_counter_select[0] =
+ p->counter_select[0];
+ if (p->counter_select[1])
+ dev->pma_counter_select[1] =
+ p->counter_select[1];
+ if (p->counter_select[2])
+ dev->pma_counter_select[2] =
+ p->counter_select[2];
+ if (p->counter_select[3])
+ dev->pma_counter_select[3] =
+ p->counter_select[3];
+ if (p->counter_select[4])
+ dev->pma_counter_select[4] =
+ p->counter_select[4];
+ }
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
}
- spin_unlock_irqrestore(&dev->pending_lock, flags);
-
ret = recv_pma_get_portsamplescontrol(pmp, ibdev, port);
bail:
return ret;
}
-static u64 get_counter(struct ipath_ibdev *dev,
- struct ipath_cregs const *crp,
- __be16 sel)
+static u64 get_counter(struct ipath_ibdev *dev, __be16 sel)
{
u64 ret;
switch (sel) {
case IB_PMA_PORT_XMIT_DATA:
- ret = (crp->cr_psxmitdatacount) ?
- ipath_read_creg32(dev->dd, crp->cr_psxmitdatacount) :
- dev->ipath_sword;
+ ret = dev->ipath_sword;
break;
case IB_PMA_PORT_RCV_DATA:
- ret = (crp->cr_psrcvdatacount) ?
- ipath_read_creg32(dev->dd, crp->cr_psrcvdatacount) :
- dev->ipath_rword;
+ ret = dev->ipath_rword;
break;
case IB_PMA_PORT_XMIT_PKTS:
- ret = (crp->cr_psxmitpktscount) ?
- ipath_read_creg32(dev->dd, crp->cr_psxmitpktscount) :
- dev->ipath_spkts;
+ ret = dev->ipath_spkts;
break;
case IB_PMA_PORT_RCV_PKTS:
- ret = (crp->cr_psrcvpktscount) ?
- ipath_read_creg32(dev->dd, crp->cr_psrcvpktscount) :
- dev->ipath_rpkts;
+ ret = dev->ipath_rpkts;
break;
case IB_PMA_PORT_XMIT_WAIT:
- ret = (crp->cr_psxmitwaitcount) ?
- ipath_read_creg32(dev->dd, crp->cr_psxmitwaitcount) :
- dev->ipath_xmit_wait;
+ ret = dev->ipath_xmit_wait;
break;
default:
ret = 0;
@@ -1066,21 +1053,14 @@ static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
struct ib_pma_portsamplesresult *p =
(struct ib_pma_portsamplesresult *)pmp->data;
struct ipath_ibdev *dev = to_idev(ibdev);
- struct ipath_cregs const *crp = dev->dd->ipath_cregs;
- u8 status;
int i;
memset(pmp->data, 0, sizeof(pmp->data));
p->tag = cpu_to_be16(dev->pma_tag);
- if (crp->cr_psstat)
- status = ipath_read_creg32(dev->dd, crp->cr_psstat);
- else
- status = dev->pma_sample_status;
- p->sample_status = cpu_to_be16(status);
+ p->sample_status = cpu_to_be16(dev->pma_sample_status);
for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
- p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 :
- cpu_to_be32(
- get_counter(dev, crp, dev->pma_counter_select[i]));
+ p->counter[i] = cpu_to_be32(
+ get_counter(dev, dev->pma_counter_select[i]));
return reply((struct ib_smp *) pmp);
}
@@ -1091,23 +1071,16 @@ static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
struct ib_pma_portsamplesresult_ext *p =
(struct ib_pma_portsamplesresult_ext *)pmp->data;
struct ipath_ibdev *dev = to_idev(ibdev);
- struct ipath_cregs const *crp = dev->dd->ipath_cregs;
- u8 status;
int i;
memset(pmp->data, 0, sizeof(pmp->data));
p->tag = cpu_to_be16(dev->pma_tag);
- if (crp->cr_psstat)
- status = ipath_read_creg32(dev->dd, crp->cr_psstat);
- else
- status = dev->pma_sample_status;
- p->sample_status = cpu_to_be16(status);
+ p->sample_status = cpu_to_be16(dev->pma_sample_status);
/* 64 bits */
p->extended_width = __constant_cpu_to_be32(0x80000000);
for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
- p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 :
- cpu_to_be64(
- get_counter(dev, crp, dev->pma_counter_select[i]));
+ p->counter[i] = cpu_to_be64(
+ get_counter(dev, dev->pma_counter_select[i]));
return reply((struct ib_smp *) pmp);
}
@@ -1140,8 +1113,6 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
dev->z_local_link_integrity_errors;
cntrs.excessive_buffer_overrun_errors -=
dev->z_excessive_buffer_overrun_errors;
- cntrs.vl15_dropped -= dev->z_vl15_dropped;
- cntrs.vl15_dropped += dev->n_vl15_dropped;
memset(pmp->data, 0, sizeof(pmp->data));
@@ -1185,10 +1156,10 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
cntrs.excessive_buffer_overrun_errors = 0xFUL;
p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
cntrs.excessive_buffer_overrun_errors;
- if (cntrs.vl15_dropped > 0xFFFFUL)
+ if (dev->n_vl15_dropped > 0xFFFFUL)
p->vl15_dropped = __constant_cpu_to_be16(0xFFFF);
else
- p->vl15_dropped = cpu_to_be16((u16)cntrs.vl15_dropped);
+ p->vl15_dropped = cpu_to_be16((u16)dev->n_vl15_dropped);
if (cntrs.port_xmit_data > 0xFFFFFFFFUL)
p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF);
else
@@ -1291,10 +1262,8 @@ static int recv_pma_set_portcounters(struct ib_perf *pmp,
dev->z_excessive_buffer_overrun_errors =
cntrs.excessive_buffer_overrun_errors;
- if (p->counter_select & IB_PMA_SEL_PORT_VL15_DROPPED) {
+ if (p->counter_select & IB_PMA_SEL_PORT_VL15_DROPPED)
dev->n_vl15_dropped = 0;
- dev->z_vl15_dropped = cntrs.vl15_dropped;
- }
if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA)
dev->z_port_xmit_data = cntrs.port_xmit_data;
@@ -1465,7 +1434,7 @@ static int process_subn(struct ib_device *ibdev, int mad_flags,
* before checking for other consumers.
* Just tell the caller to process it normally.
*/
- ret = IB_MAD_RESULT_SUCCESS;
+ ret = IB_MAD_RESULT_FAILURE;
goto bail;
default:
smp->status |= IB_SMP_UNSUP_METHOD;
@@ -1547,7 +1516,7 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
* before checking for other consumers.
* Just tell the caller to process it normally.
*/
- ret = IB_MAD_RESULT_SUCCESS;
+ ret = IB_MAD_RESULT_FAILURE;
goto bail;
default:
pmp->status |= IB_SMP_UNSUP_METHOD;
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_qp.c b/trunk/drivers/infiniband/hw/ipath/ipath_qp.c
index 80dc623cee40..b997ff88401b 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_qp.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_qp.c
@@ -387,8 +387,8 @@ int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err)
struct ib_wc wc;
int ret = 0;
- ipath_dbg("QP%d/%d in error state (%d)\n",
- qp->ibqp.qp_num, qp->remote_qpn, err);
+ ipath_dbg("QP%d/%d in error state\n",
+ qp->ibqp.qp_num, qp->remote_qpn);
spin_lock(&dev->pending_lock);
/* XXX What if its already removed by the timeout code? */
@@ -855,6 +855,8 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
* See ipath_mmap() for details.
*/
if (udata && udata->outlen >= sizeof(__u64)) {
+ int err;
+
if (!qp->r_rq.wq) {
__u64 offset = 0;
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_rc.c b/trunk/drivers/infiniband/hw/ipath/ipath_rc.c
index 459e46e2c016..120a61b03bc4 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_rc.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_rc.c
@@ -647,7 +647,6 @@ static void send_rc_ack(struct ipath_qp *qp)
queue_ack:
spin_lock_irqsave(&qp->s_lock, flags);
- dev->n_rc_qacks++;
qp->s_flags |= IPATH_S_ACK_PENDING;
qp->s_nak_state = qp->r_nak_state;
qp->s_ack_psn = qp->r_ack_psn;
@@ -799,13 +798,11 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc)
static inline void update_last_psn(struct ipath_qp *qp, u32 psn)
{
- if (qp->s_last_psn != psn) {
- qp->s_last_psn = psn;
- if (qp->s_wait_credit) {
- qp->s_wait_credit = 0;
- tasklet_hi_schedule(&qp->s_task);
- }
+ if (qp->s_wait_credit) {
+ qp->s_wait_credit = 0;
+ tasklet_hi_schedule(&qp->s_task);
}
+ qp->s_last_psn = psn;
}
/**
@@ -1656,6 +1653,13 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
case OP(SEND_FIRST):
if (!ipath_get_rwqe(qp, 0)) {
rnr_nak:
+ /*
+ * A RNR NAK will ACK earlier sends and RDMA writes.
+ * Don't queue the NAK if a RDMA read or atomic
+ * is pending though.
+ */
+ if (qp->r_nak_state)
+ goto done;
qp->r_nak_state = IB_RNR_NAK | qp->r_min_rnr_timer;
qp->r_ack_psn = qp->r_psn;
goto send_ack;
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_registers.h b/trunk/drivers/infiniband/hw/ipath/ipath_registers.h
index 6d2a17f9c1da..708eba3165d7 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_registers.h
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_registers.h
@@ -82,7 +82,8 @@
/* kr_rcvctrl bits */
#define INFINIPATH_R_PORTENABLE_SHIFT 0
-#define INFINIPATH_R_QPMAP_ENABLE (1ULL << 38)
+#define INFINIPATH_R_INTRAVAIL_SHIFT 16
+#define INFINIPATH_R_TAILUPD 0x80000000
/* kr_intstatus, kr_intclear, kr_intmask bits */
#define INFINIPATH_I_RCVURG_SHIFT 0
@@ -271,6 +272,20 @@
#define INFINIPATH_EXTC_LEDGBLOK_ON 0x00000002ULL
#define INFINIPATH_EXTC_LEDGBLERR_OFF 0x00000001ULL
+/* kr_mdio bits */
+#define INFINIPATH_MDIO_CLKDIV_MASK 0x7FULL
+#define INFINIPATH_MDIO_CLKDIV_SHIFT 32
+#define INFINIPATH_MDIO_COMMAND_MASK 0x7ULL
+#define INFINIPATH_MDIO_COMMAND_SHIFT 26
+#define INFINIPATH_MDIO_DEVADDR_MASK 0x1FULL
+#define INFINIPATH_MDIO_DEVADDR_SHIFT 21
+#define INFINIPATH_MDIO_REGADDR_MASK 0x1FULL
+#define INFINIPATH_MDIO_REGADDR_SHIFT 16
+#define INFINIPATH_MDIO_DATA_MASK 0xFFFFULL
+#define INFINIPATH_MDIO_DATA_SHIFT 0
+#define INFINIPATH_MDIO_CMDVALID 0x0000000040000000ULL
+#define INFINIPATH_MDIO_RDDATAVALID 0x0000000080000000ULL
+
/* kr_partitionkey bits */
#define INFINIPATH_PKEY_SIZE 16
#define INFINIPATH_PKEY_MASK 0xFFFF
@@ -288,6 +303,8 @@
/* kr_xgxsconfig bits */
#define INFINIPATH_XGXS_RESET 0x7ULL
+#define INFINIPATH_XGXS_MDIOADDR_MASK 0xfULL
+#define INFINIPATH_XGXS_MDIOADDR_SHIFT 4
#define INFINIPATH_XGXS_RX_POL_SHIFT 19
#define INFINIPATH_XGXS_RX_POL_MASK 0xfULL
@@ -453,20 +470,6 @@ struct ipath_cregs {
ipath_creg cr_unsupvlcnt;
ipath_creg cr_wordrcvcnt;
ipath_creg cr_wordsendcnt;
- ipath_creg cr_vl15droppedpktcnt;
- ipath_creg cr_rxotherlocalphyerrcnt;
- ipath_creg cr_excessbufferovflcnt;
- ipath_creg cr_locallinkintegrityerrcnt;
- ipath_creg cr_rxvlerrcnt;
- ipath_creg cr_rxdlidfltrcnt;
- ipath_creg cr_psstat;
- ipath_creg cr_psstart;
- ipath_creg cr_psinterval;
- ipath_creg cr_psrcvdatacount;
- ipath_creg cr_psrcvpktscount;
- ipath_creg cr_psxmitdatacount;
- ipath_creg cr_psxmitpktscount;
- ipath_creg cr_psxmitwaitcount;
};
#endif /* _IPATH_REGISTERS_H */
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_ruc.c b/trunk/drivers/infiniband/hw/ipath/ipath_ruc.c
index a59bdbd0ed87..54c61a972de2 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_ruc.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -98,15 +98,11 @@ void ipath_insert_rnr_queue(struct ipath_qp *qp)
while (qp->s_rnr_timeout >= nqp->s_rnr_timeout) {
qp->s_rnr_timeout -= nqp->s_rnr_timeout;
l = l->next;
- if (l->next == &dev->rnrwait) {
- nqp = NULL;
+ if (l->next == &dev->rnrwait)
break;
- }
nqp = list_entry(l->next, struct ipath_qp,
timerwait);
}
- if (nqp)
- nqp->s_rnr_timeout -= qp->s_rnr_timeout;
list_add(&qp->timerwait, l);
}
spin_unlock_irqrestore(&dev->pending_lock, flags);
@@ -483,14 +479,9 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp)
static void want_buffer(struct ipath_devdata *dd)
{
- unsigned long flags;
-
- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
- dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
+ set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
dd->ipath_sendctrl);
- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
}
/**
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_srq.c b/trunk/drivers/infiniband/hw/ipath/ipath_srq.c
index f772102e4713..2fef36f4b675 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_srq.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_srq.c
@@ -94,8 +94,8 @@ int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
/**
* ipath_create_srq - create a shared receive queue
* @ibpd: the protection domain of the SRQ to create
- * @srq_init_attr: the attributes of the SRQ
- * @udata: data from libipathverbs when creating a user SRQ
+ * @attr: the attributes of the SRQ
+ * @udata: not used by the InfiniPath verbs driver
*/
struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
struct ib_srq_init_attr *srq_init_attr,
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_stats.c b/trunk/drivers/infiniband/hw/ipath/ipath_stats.c
index d2725cd11bdc..f0271415cd5b 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_stats.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_stats.c
@@ -133,16 +133,15 @@ u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
static void ipath_qcheck(struct ipath_devdata *dd)
{
static u64 last_tot_hdrqfull;
- struct ipath_portdata *pd = dd->ipath_pd[0];
size_t blen = 0;
char buf[128];
*buf = 0;
- if (pd->port_hdrqfull != dd->ipath_p0_hdrqfull) {
+ if (dd->ipath_pd[0]->port_hdrqfull != dd->ipath_p0_hdrqfull) {
blen = snprintf(buf, sizeof buf, "port 0 hdrqfull %u",
- pd->port_hdrqfull -
+ dd->ipath_pd[0]->port_hdrqfull -
dd->ipath_p0_hdrqfull);
- dd->ipath_p0_hdrqfull = pd->port_hdrqfull;
+ dd->ipath_p0_hdrqfull = dd->ipath_pd[0]->port_hdrqfull;
}
if (ipath_stats.sps_etidfull != dd->ipath_last_tidfull) {
blen += snprintf(buf + blen, sizeof buf - blen,
@@ -174,7 +173,7 @@ static void ipath_qcheck(struct ipath_devdata *dd)
if (blen)
ipath_dbg("%s\n", buf);
- if (pd->port_head != (u32)
+ if (dd->ipath_port0head != (u32)
le64_to_cpu(*dd->ipath_hdrqtailptr)) {
if (dd->ipath_lastport0rcv_cnt ==
ipath_stats.sps_port0pkts) {
@@ -182,7 +181,7 @@ static void ipath_qcheck(struct ipath_devdata *dd)
"port0 hd=%llx tl=%x; port0pkts %llx\n",
(unsigned long long)
le64_to_cpu(*dd->ipath_hdrqtailptr),
- pd->port_head,
+ dd->ipath_port0head,
(unsigned long long)
ipath_stats.sps_port0pkts);
}
@@ -238,7 +237,7 @@ static void ipath_chk_errormask(struct ipath_devdata *dd)
void ipath_get_faststats(unsigned long opaque)
{
struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
- int i;
+ u32 val;
static unsigned cnt;
unsigned long flags;
u64 traffic_wds;
@@ -322,11 +321,12 @@ void ipath_get_faststats(unsigned long opaque)
/* limit qfull messages to ~one per minute per port */
if ((++cnt & 0x10)) {
- for (i = (int) dd->ipath_cfgports; --i >= 0; ) {
- struct ipath_portdata *pd = dd->ipath_pd[i];
-
- if (pd && pd->port_lastrcvhdrqtail != -1)
- pd->port_lastrcvhdrqtail = -1;
+ for (val = dd->ipath_cfgports - 1; ((int)val) >= 0;
+ val--) {
+ if (dd->ipath_lastegrheads[val] != -1)
+ dd->ipath_lastegrheads[val] = -1;
+ if (dd->ipath_lastrcvhdrqtails[val] != -1)
+ dd->ipath_lastrcvhdrqtails[val] = -1;
}
}
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_sysfs.c b/trunk/drivers/infiniband/hw/ipath/ipath_sysfs.c
index 56dfc8a2344c..aa27ca9f03b1 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_sysfs.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_sysfs.c
@@ -363,60 +363,6 @@ static ssize_t show_unit(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_unit);
}
-static ssize_t show_jint_max_packets(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
-
- return scnprintf(buf, PAGE_SIZE, "%hu\n", dd->ipath_jint_max_packets);
-}
-
-static ssize_t store_jint_max_packets(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- u16 v = 0;
- int ret;
-
- ret = ipath_parse_ushort(buf, &v);
- if (ret < 0)
- ipath_dev_err(dd, "invalid jint_max_packets.\n");
- else
- dd->ipath_f_config_jint(dd, dd->ipath_jint_idle_ticks, v);
-
- return ret;
-}
-
-static ssize_t show_jint_idle_ticks(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
-
- return scnprintf(buf, PAGE_SIZE, "%hu\n", dd->ipath_jint_idle_ticks);
-}
-
-static ssize_t store_jint_idle_ticks(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- u16 v = 0;
- int ret;
-
- ret = ipath_parse_ushort(buf, &v);
- if (ret < 0)
- ipath_dev_err(dd, "invalid jint_idle_ticks.\n");
- else
- dd->ipath_f_config_jint(dd, v, dd->ipath_jint_max_packets);
-
- return ret;
-}
-
#define DEVICE_COUNTER(name, attr) \
static ssize_t show_counter_##name(struct device *dev, \
struct device_attribute *attr, \
@@ -724,257 +670,6 @@ static ssize_t show_logged_errs(struct device *dev,
return count;
}
-/*
- * New sysfs entries to control various IB config. These all turn into
- * accesses via ipath_f_get/set_ib_cfg.
- *
- * Get/Set heartbeat enable. Or of 1=enabled, 2=auto
- */
-static ssize_t show_hrtbt_enb(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- int ret;
-
- ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_HRTBT);
- if (ret >= 0)
- ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
- return ret;
-}
-
-static ssize_t store_hrtbt_enb(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- int ret, r;
- u16 val;
-
- ret = ipath_parse_ushort(buf, &val);
- if (ret >= 0 && val > 3)
- ret = -EINVAL;
- if (ret < 0) {
- ipath_dev_err(dd, "attempt to set invalid Heartbeat enable\n");
- goto bail;
- }
-
- /*
- * Set the "intentional" heartbeat enable per either of
- * "Enable" and "Auto", as these are normally set together.
- * This bit is consulted when leaving loopback mode,
- * because entering loopback mode overrides it and automatically
- * disables heartbeat.
- */
- r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT, val);
- if (r < 0)
- ret = r;
- else if (val == IPATH_IB_HRTBT_OFF)
- dd->ipath_flags |= IPATH_NO_HRTBT;
- else
- dd->ipath_flags &= ~IPATH_NO_HRTBT;
-
-bail:
- return ret;
-}
-
-/*
- * Get/Set Link-widths enabled. Or of 1=1x, 2=4x (this is human/IB centric,
- * _not_ the particular encoding of any given chip)
- */
-static ssize_t show_lwid_enb(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- int ret;
-
- ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB);
- if (ret >= 0)
- ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
- return ret;
-}
-
-static ssize_t store_lwid_enb(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- int ret, r;
- u16 val;
-
- ret = ipath_parse_ushort(buf, &val);
- if (ret >= 0 && (val == 0 || val > 3))
- ret = -EINVAL;
- if (ret < 0) {
- ipath_dev_err(dd,
- "attempt to set invalid Link Width (enable)\n");
- goto bail;
- }
-
- r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB, val);
- if (r < 0)
- ret = r;
-
-bail:
- return ret;
-}
-
-/* Get current link width */
-static ssize_t show_lwid(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- int ret;
-
- ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LWID);
- if (ret >= 0)
- ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
- return ret;
-}
-
-/*
- * Get/Set Link-speeds enabled. Or of 1=SDR 2=DDR.
- */
-static ssize_t show_spd_enb(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- int ret;
-
- ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB);
- if (ret >= 0)
- ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
- return ret;
-}
-
-static ssize_t store_spd_enb(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- int ret, r;
- u16 val;
-
- ret = ipath_parse_ushort(buf, &val);
- if (ret >= 0 && (val == 0 || val > (IPATH_IB_SDR | IPATH_IB_DDR)))
- ret = -EINVAL;
- if (ret < 0) {
- ipath_dev_err(dd,
- "attempt to set invalid Link Speed (enable)\n");
- goto bail;
- }
-
- r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB, val);
- if (r < 0)
- ret = r;
-
-bail:
- return ret;
-}
-
-/* Get current link speed */
-static ssize_t show_spd(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- int ret;
-
- ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_SPD);
- if (ret >= 0)
- ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
- return ret;
-}
-
-/*
- * Get/Set RX polarity-invert enable. 0=no, 1=yes.
- */
-static ssize_t show_rx_polinv_enb(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- int ret;
-
- ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB);
- if (ret >= 0)
- ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
- return ret;
-}
-
-static ssize_t store_rx_polinv_enb(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- int ret, r;
- u16 val;
-
- ret = ipath_parse_ushort(buf, &val);
- if (ret < 0 || val > 1)
- goto invalid;
-
- r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB, val);
- if (r < 0) {
- ret = r;
- goto bail;
- }
-
- goto bail;
-invalid:
- ipath_dev_err(dd, "attempt to set invalid Rx Polarity (enable)\n");
-bail:
- return ret;
-}
-/*
- * Get/Set RX lane-reversal enable. 0=no, 1=yes.
- */
-static ssize_t show_lanerev_enb(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- int ret;
-
- ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LREV_ENB);
- if (ret >= 0)
- ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
- return ret;
-}
-
-static ssize_t store_lanerev_enb(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct ipath_devdata *dd = dev_get_drvdata(dev);
- int ret, r;
- u16 val;
-
- ret = ipath_parse_ushort(buf, &val);
- if (ret >= 0 && val > 1) {
- ret = -EINVAL;
- ipath_dev_err(dd,
- "attempt to set invalid Lane reversal (enable)\n");
- goto bail;
- }
-
- r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LREV_ENB, val);
- if (r < 0)
- ret = r;
-
-bail:
- return ret;
-}
-
static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL);
static DRIVER_ATTR(version, S_IRUGO, show_version, NULL);
@@ -1011,10 +706,6 @@ static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv);
static DEVICE_ATTR(led_override, S_IWUSR, NULL, store_led_override);
static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
-static DEVICE_ATTR(jint_max_packets, S_IWUSR | S_IRUGO,
- show_jint_max_packets, store_jint_max_packets);
-static DEVICE_ATTR(jint_idle_ticks, S_IWUSR | S_IRUGO,
- show_jint_idle_ticks, store_jint_idle_ticks);
static struct attribute *dev_attributes[] = {
&dev_attr_guid.attr,
@@ -1041,34 +732,6 @@ static struct attribute_group dev_attr_group = {
.attrs = dev_attributes
};
-static DEVICE_ATTR(hrtbt_enable, S_IWUSR | S_IRUGO, show_hrtbt_enb,
- store_hrtbt_enb);
-static DEVICE_ATTR(link_width_enable, S_IWUSR | S_IRUGO, show_lwid_enb,
- store_lwid_enb);
-static DEVICE_ATTR(link_width, S_IRUGO, show_lwid, NULL);
-static DEVICE_ATTR(link_speed_enable, S_IWUSR | S_IRUGO, show_spd_enb,
- store_spd_enb);
-static DEVICE_ATTR(link_speed, S_IRUGO, show_spd, NULL);
-static DEVICE_ATTR(rx_pol_inv_enable, S_IWUSR | S_IRUGO, show_rx_polinv_enb,
- store_rx_polinv_enb);
-static DEVICE_ATTR(rx_lane_rev_enable, S_IWUSR | S_IRUGO, show_lanerev_enb,
- store_lanerev_enb);
-
-static struct attribute *dev_ibcfg_attributes[] = {
- &dev_attr_hrtbt_enable.attr,
- &dev_attr_link_width_enable.attr,
- &dev_attr_link_width.attr,
- &dev_attr_link_speed_enable.attr,
- &dev_attr_link_speed.attr,
- &dev_attr_rx_pol_inv_enable.attr,
- &dev_attr_rx_lane_rev_enable.attr,
- NULL
-};
-
-static struct attribute_group dev_ibcfg_attr_group = {
- .attrs = dev_ibcfg_attributes
-};
-
/**
* ipath_expose_reset - create a device reset file
* @dev: the device structure
@@ -1107,26 +770,6 @@ int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd)
if (ret)
goto bail_attrs;
- if (dd->ipath_flags & IPATH_HAS_MULT_IB_SPEED) {
- ret = device_create_file(dev, &dev_attr_jint_idle_ticks);
- if (ret)
- goto bail_counter;
- ret = device_create_file(dev, &dev_attr_jint_max_packets);
- if (ret)
- goto bail_idle;
-
- ret = sysfs_create_group(&dev->kobj, &dev_ibcfg_attr_group);
- if (ret)
- goto bail_max;
- }
-
- return 0;
-
-bail_max:
- device_remove_file(dev, &dev_attr_jint_max_packets);
-bail_idle:
- device_remove_file(dev, &dev_attr_jint_idle_ticks);
-bail_counter:
sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
bail_attrs:
sysfs_remove_group(&dev->kobj, &dev_attr_group);
@@ -1137,13 +780,6 @@ int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd)
void ipath_device_remove_group(struct device *dev, struct ipath_devdata *dd)
{
sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
-
- if (dd->ipath_flags & IPATH_HAS_MULT_IB_SPEED) {
- sysfs_remove_group(&dev->kobj, &dev_ibcfg_attr_group);
- device_remove_file(dev, &dev_attr_jint_idle_ticks);
- device_remove_file(dev, &dev_attr_jint_max_packets);
- }
-
sysfs_remove_group(&dev->kobj, &dev_attr_group);
device_remove_file(dev, &dev_attr_reset);
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_ud.c b/trunk/drivers/infiniband/hw/ipath/ipath_ud.c
index de67eed08ed0..b3df6f3c705e 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_ud.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_ud.c
@@ -301,6 +301,8 @@ int ipath_make_ud_req(struct ipath_qp *qp)
/* header size in 32-bit words LRH+BTH+DETH = (8+12+8)/4. */
qp->s_hdrwords = 7;
+ if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM)
+ qp->s_hdrwords++;
qp->s_cur_size = wqe->length;
qp->s_cur_sge = &qp->s_sge;
qp->s_wqe = wqe;
@@ -325,7 +327,6 @@ int ipath_make_ud_req(struct ipath_qp *qp)
ohdr = &qp->s_hdr.u.oth;
}
if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
- qp->s_hdrwords++;
ohdr->u.ud.imm_data = wqe->wr.imm_data;
bth0 = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE << 24;
} else
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c
index 32d8f882e56c..c4c998446c7b 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -943,7 +943,7 @@ static int ipath_verbs_send_pio(struct ipath_qp *qp, u32 *hdr, u32 hdrwords,
* ipath_verbs_send - send a packet
* @qp: the QP to send on
* @hdr: the packet header
- * @hdrwords: the number of 32-bit words in the header
+ * @hdrwords: the number of words in the header
* @ss: the SGE to send
* @len: the length of the packet in bytes
*/
@@ -955,10 +955,7 @@ int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr,
int ret;
u32 dwords = (len + 3) >> 2;
- /*
- * Calculate the send buffer trigger address.
- * The +1 counts for the pbc control dword following the pbc length.
- */
+ /* +1 is for the qword padding of pbc */
plen = hdrwords + dwords + 1;
/* Drop non-VL15 packets if we are not in the active state */
@@ -1133,34 +1130,20 @@ static int ipath_query_device(struct ib_device *ibdev,
return 0;
}
-const u8 ipath_cvt_physportstate[32] = {
- [INFINIPATH_IBCS_LT_STATE_DISABLED] = IB_PHYSPORTSTATE_DISABLED,
- [INFINIPATH_IBCS_LT_STATE_LINKUP] = IB_PHYSPORTSTATE_LINKUP,
- [INFINIPATH_IBCS_LT_STATE_POLLACTIVE] = IB_PHYSPORTSTATE_POLL,
- [INFINIPATH_IBCS_LT_STATE_POLLQUIET] = IB_PHYSPORTSTATE_POLL,
- [INFINIPATH_IBCS_LT_STATE_SLEEPDELAY] = IB_PHYSPORTSTATE_SLEEP,
- [INFINIPATH_IBCS_LT_STATE_SLEEPQUIET] = IB_PHYSPORTSTATE_SLEEP,
- [INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE] =
- IB_PHYSPORTSTATE_CFG_TRAIN,
- [INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG] =
- IB_PHYSPORTSTATE_CFG_TRAIN,
- [INFINIPATH_IBCS_LT_STATE_CFGWAITRMT] =
- IB_PHYSPORTSTATE_CFG_TRAIN,
- [INFINIPATH_IBCS_LT_STATE_CFGIDLE] = IB_PHYSPORTSTATE_CFG_TRAIN,
- [INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN] =
- IB_PHYSPORTSTATE_LINK_ERR_RECOVER,
- [INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT] =
- IB_PHYSPORTSTATE_LINK_ERR_RECOVER,
- [INFINIPATH_IBCS_LT_STATE_RECOVERIDLE] =
- IB_PHYSPORTSTATE_LINK_ERR_RECOVER,
- [0x10] = IB_PHYSPORTSTATE_CFG_TRAIN,
- [0x11] = IB_PHYSPORTSTATE_CFG_TRAIN,
- [0x12] = IB_PHYSPORTSTATE_CFG_TRAIN,
- [0x13] = IB_PHYSPORTSTATE_CFG_TRAIN,
- [0x14] = IB_PHYSPORTSTATE_CFG_TRAIN,
- [0x15] = IB_PHYSPORTSTATE_CFG_TRAIN,
- [0x16] = IB_PHYSPORTSTATE_CFG_TRAIN,
- [0x17] = IB_PHYSPORTSTATE_CFG_TRAIN
+const u8 ipath_cvt_physportstate[16] = {
+ [INFINIPATH_IBCS_LT_STATE_DISABLED] = 3,
+ [INFINIPATH_IBCS_LT_STATE_LINKUP] = 5,
+ [INFINIPATH_IBCS_LT_STATE_POLLACTIVE] = 2,
+ [INFINIPATH_IBCS_LT_STATE_POLLQUIET] = 2,
+ [INFINIPATH_IBCS_LT_STATE_SLEEPDELAY] = 1,
+ [INFINIPATH_IBCS_LT_STATE_SLEEPQUIET] = 1,
+ [INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE] = 4,
+ [INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG] = 4,
+ [INFINIPATH_IBCS_LT_STATE_CFGWAITRMT] = 4,
+ [INFINIPATH_IBCS_LT_STATE_CFGIDLE] = 4,
+ [INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN] = 6,
+ [INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT] = 6,
+ [INFINIPATH_IBCS_LT_STATE_RECOVERIDLE] = 6,
};
u32 ipath_get_cr_errpkey(struct ipath_devdata *dd)
@@ -1185,9 +1168,8 @@ static int ipath_query_port(struct ib_device *ibdev,
ibcstat = dd->ipath_lastibcstat;
props->state = ((ibcstat >> 4) & 0x3) + 1;
/* See phys_state_show() */
- props->phys_state = /* MEA: assumes shift == 0 */
- ipath_cvt_physportstate[dd->ipath_lastibcstat &
- dd->ibcs_lts_mask];
+ props->phys_state = ipath_cvt_physportstate[
+ dd->ipath_lastibcstat & 0xf];
props->port_cap_flags = dev->port_cap_flags;
props->gid_tbl_len = 1;
props->max_msg_sz = 0x80000000;
@@ -1659,7 +1641,6 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
cntrs.local_link_integrity_errors;
idev->z_excessive_buffer_overrun_errors =
cntrs.excessive_buffer_overrun_errors;
- idev->z_vl15_dropped = cntrs.vl15_dropped;
/*
* The system image GUID is supposed to be the same for all
diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h
index 3d59736b49b2..6ccb54f104a3 100644
--- a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h
+++ b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h
@@ -554,7 +554,6 @@ struct ipath_ibdev {
u32 z_pkey_violations; /* starting count for PMA */
u32 z_local_link_integrity_errors; /* starting count for PMA */
u32 z_excessive_buffer_overrun_errors; /* starting count for PMA */
- u32 z_vl15_dropped; /* starting count for PMA */
u32 n_rc_resends;
u32 n_rc_acks;
u32 n_rc_qacks;
@@ -599,7 +598,6 @@ struct ipath_verbs_counters {
u64 port_rcv_packets;
u32 local_link_integrity_errors;
u32 excessive_buffer_overrun_errors;
- u32 vl15_dropped;
};
static inline struct ipath_mr *to_imr(struct ib_mr *ibmr)
@@ -832,17 +830,7 @@ unsigned ipath_get_pkey(struct ipath_devdata *, unsigned);
extern const enum ib_wc_opcode ib_ipath_wc_opcode[];
-/*
- * Below converts HCA-specific LinkTrainingState to IB PhysPortState
- * values.
- */
extern const u8 ipath_cvt_physportstate[];
-#define IB_PHYSPORTSTATE_SLEEP 1
-#define IB_PHYSPORTSTATE_POLL 2
-#define IB_PHYSPORTSTATE_DISABLED 3
-#define IB_PHYSPORTSTATE_CFG_TRAIN 4
-#define IB_PHYSPORTSTATE_LINKUP 5
-#define IB_PHYSPORTSTATE_LINK_ERR_RECOVER 6
extern const int ib_ipath_state_ops[];
diff --git a/trunk/drivers/infiniband/hw/mlx4/cq.c b/trunk/drivers/infiniband/hw/mlx4/cq.c
index 7950aa6e8184..9d32c49cc651 100644
--- a/trunk/drivers/infiniband/hw/mlx4/cq.c
+++ b/trunk/drivers/infiniband/hw/mlx4/cq.c
@@ -313,7 +313,6 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
struct mlx4_ib_srq *srq;
int is_send;
int is_error;
- u32 g_mlpath_rqpn;
u16 wqe_ctr;
cqe = next_cqe_sw(cq);
@@ -427,10 +426,10 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
wc->slid = be16_to_cpu(cqe->rlid);
wc->sl = cqe->sl >> 4;
- g_mlpath_rqpn = be32_to_cpu(cqe->g_mlpath_rqpn);
- wc->src_qp = g_mlpath_rqpn & 0xffffff;
- wc->dlid_path_bits = (g_mlpath_rqpn >> 24) & 0x7f;
- wc->wc_flags |= g_mlpath_rqpn & 0x80000000 ? IB_WC_GRH : 0;
+ wc->src_qp = be32_to_cpu(cqe->g_mlpath_rqpn) & 0xffffff;
+ wc->dlid_path_bits = (be32_to_cpu(cqe->g_mlpath_rqpn) >> 24) & 0x7f;
+ wc->wc_flags |= be32_to_cpu(cqe->g_mlpath_rqpn) & 0x80000000 ?
+ IB_WC_GRH : 0;
wc->pkey_index = be32_to_cpu(cqe->immed_rss_invalid) & 0x7f;
}
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_dev.h b/trunk/drivers/infiniband/hw/mthca/mthca_dev.h
index 7bbdd1f4e6c7..15aa32eb78b6 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -60,12 +60,13 @@
enum {
MTHCA_FLAG_DDR_HIDDEN = 1 << 1,
MTHCA_FLAG_SRQ = 1 << 2,
- MTHCA_FLAG_MSI_X = 1 << 3,
- MTHCA_FLAG_NO_LAM = 1 << 4,
- MTHCA_FLAG_FMR = 1 << 5,
- MTHCA_FLAG_MEMFREE = 1 << 6,
- MTHCA_FLAG_PCIE = 1 << 7,
- MTHCA_FLAG_SINAI_OPT = 1 << 8
+ MTHCA_FLAG_MSI = 1 << 3,
+ MTHCA_FLAG_MSI_X = 1 << 4,
+ MTHCA_FLAG_NO_LAM = 1 << 5,
+ MTHCA_FLAG_FMR = 1 << 6,
+ MTHCA_FLAG_MEMFREE = 1 << 7,
+ MTHCA_FLAG_PCIE = 1 << 8,
+ MTHCA_FLAG_SINAI_OPT = 1 << 9
};
enum {
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_eq.c b/trunk/drivers/infiniband/hw/mthca/mthca_eq.c
index b60eb5df96e8..b29de51b7f35 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -827,7 +827,8 @@ int mthca_init_eq_table(struct mthca_dev *dev)
if (err)
goto err_out_free;
- if (dev->mthca_flags & MTHCA_FLAG_MSI_X) {
+ if (dev->mthca_flags & MTHCA_FLAG_MSI ||
+ dev->mthca_flags & MTHCA_FLAG_MSI_X) {
dev->eq_table.clr_mask = 0;
} else {
dev->eq_table.clr_mask =
@@ -838,7 +839,8 @@ int mthca_init_eq_table(struct mthca_dev *dev)
dev->eq_table.arm_mask = 0;
- intr = dev->eq_table.inta_pin;
+ intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ?
+ 128 : dev->eq_table.inta_pin;
err = mthca_create_eq(dev, dev->limits.num_cqs + MTHCA_NUM_SPARE_EQE,
(dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr,
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_main.c b/trunk/drivers/infiniband/hw/mthca/mthca_main.c
index 5cf8250d4e16..60de6f93869e 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_main.c
@@ -65,9 +65,14 @@ static int msi_x = 1;
module_param(msi_x, int, 0444);
MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero");
+static int msi = 0;
+module_param(msi, int, 0444);
+MODULE_PARM_DESC(msi, "attempt to use MSI if nonzero (deprecated, use MSI-X instead)");
+
#else /* CONFIG_PCI_MSI */
#define msi_x (0)
+#define msi (0)
#endif /* CONFIG_PCI_MSI */
@@ -811,11 +816,13 @@ static int mthca_setup_hca(struct mthca_dev *dev)
err = mthca_NOP(dev, &status);
if (err || status) {
- if (dev->mthca_flags & MTHCA_FLAG_MSI_X) {
+ if (dev->mthca_flags & (MTHCA_FLAG_MSI | MTHCA_FLAG_MSI_X)) {
mthca_warn(dev, "NOP command failed to generate interrupt "
"(IRQ %d).\n",
- dev->eq_table.eq[MTHCA_EQ_CMD].msi_x_vector);
- mthca_warn(dev, "Trying again with MSI-X disabled.\n");
+ dev->mthca_flags & MTHCA_FLAG_MSI_X ?
+ dev->eq_table.eq[MTHCA_EQ_CMD].msi_x_vector :
+ dev->pdev->irq);
+ mthca_warn(dev, "Trying again with MSI/MSI-X disabled.\n");
} else {
mthca_err(dev, "NOP command failed to generate interrupt "
"(IRQ %d), aborting.\n",
@@ -998,7 +1005,7 @@ static struct {
.flags = 0 },
[ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 8, 200),
.flags = MTHCA_FLAG_PCIE },
- [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 3, 0),
+ [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 2, 0),
.flags = MTHCA_FLAG_MEMFREE |
MTHCA_FLAG_PCIE },
[SINAI] = { .latest_fw = MTHCA_FW_VER(1, 2, 0),
@@ -1121,12 +1128,29 @@ static int __mthca_init_one(struct pci_dev *pdev, int hca_type)
if (msi_x && !mthca_enable_msi_x(mdev))
mdev->mthca_flags |= MTHCA_FLAG_MSI_X;
+ else if (msi) {
+ static int warned;
+
+ if (!warned) {
+ printk(KERN_WARNING PFX "WARNING: MSI support will be "
+ "removed from the ib_mthca driver in January 2008.\n");
+ printk(KERN_WARNING " If you are using MSI and cannot "
+ "switch to MSI-X, please tell "
+ ".\n");
+ ++warned;
+ }
+
+ if (!pci_enable_msi(pdev))
+ mdev->mthca_flags |= MTHCA_FLAG_MSI;
+ }
err = mthca_setup_hca(mdev);
- if (err == -EBUSY && (mdev->mthca_flags & MTHCA_FLAG_MSI_X)) {
+ if (err == -EBUSY && (mdev->mthca_flags & (MTHCA_FLAG_MSI | MTHCA_FLAG_MSI_X))) {
if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
pci_disable_msix(pdev);
- mdev->mthca_flags &= ~MTHCA_FLAG_MSI_X;
+ if (mdev->mthca_flags & MTHCA_FLAG_MSI)
+ pci_disable_msi(pdev);
+ mdev->mthca_flags &= ~(MTHCA_FLAG_MSI_X | MTHCA_FLAG_MSI);
err = mthca_setup_hca(mdev);
}
@@ -1168,6 +1192,8 @@ static int __mthca_init_one(struct pci_dev *pdev, int hca_type)
err_close:
if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
pci_disable_msix(pdev);
+ if (mdev->mthca_flags & MTHCA_FLAG_MSI)
+ pci_disable_msi(pdev);
mthca_close_hca(mdev);
@@ -1220,6 +1246,8 @@ static void __mthca_remove_one(struct pci_dev *pdev)
if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
pci_disable_msix(pdev);
+ if (mdev->mthca_flags & MTHCA_FLAG_MSI)
+ pci_disable_msi(pdev);
ib_dealloc_device(&mdev->ib_dev);
mthca_release_regions(pdev, mdev->mthca_flags &
diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h
index fe250c60607d..eb7edab0e836 100644
--- a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -56,43 +56,42 @@
/* constants */
enum {
- IPOIB_PACKET_SIZE = 2048,
- IPOIB_BUF_SIZE = IPOIB_PACKET_SIZE + IB_GRH_BYTES,
+ IPOIB_PACKET_SIZE = 2048,
+ IPOIB_BUF_SIZE = IPOIB_PACKET_SIZE + IB_GRH_BYTES,
- IPOIB_ENCAP_LEN = 4,
+ IPOIB_ENCAP_LEN = 4,
- IPOIB_CM_MTU = 0x10000 - 0x10, /* padding to align header to 16 */
- IPOIB_CM_BUF_SIZE = IPOIB_CM_MTU + IPOIB_ENCAP_LEN,
- IPOIB_CM_HEAD_SIZE = IPOIB_CM_BUF_SIZE % PAGE_SIZE,
- IPOIB_CM_RX_SG = ALIGN(IPOIB_CM_BUF_SIZE, PAGE_SIZE) / PAGE_SIZE,
- IPOIB_RX_RING_SIZE = 128,
- IPOIB_TX_RING_SIZE = 64,
+ IPOIB_CM_MTU = 0x10000 - 0x10, /* padding to align header to 16 */
+ IPOIB_CM_BUF_SIZE = IPOIB_CM_MTU + IPOIB_ENCAP_LEN,
+ IPOIB_CM_HEAD_SIZE = IPOIB_CM_BUF_SIZE % PAGE_SIZE,
+ IPOIB_CM_RX_SG = ALIGN(IPOIB_CM_BUF_SIZE, PAGE_SIZE) / PAGE_SIZE,
+ IPOIB_RX_RING_SIZE = 128,
+ IPOIB_TX_RING_SIZE = 64,
IPOIB_MAX_QUEUE_SIZE = 8192,
IPOIB_MIN_QUEUE_SIZE = 2,
- IPOIB_CM_MAX_CONN_QP = 4096,
- IPOIB_NUM_WC = 4,
+ IPOIB_NUM_WC = 4,
IPOIB_MAX_PATH_REC_QUEUE = 3,
- IPOIB_MAX_MCAST_QUEUE = 3,
-
- IPOIB_FLAG_OPER_UP = 0,
- IPOIB_FLAG_INITIALIZED = 1,
- IPOIB_FLAG_ADMIN_UP = 2,
- IPOIB_PKEY_ASSIGNED = 3,
- IPOIB_PKEY_STOP = 4,
- IPOIB_FLAG_SUBINTERFACE = 5,
- IPOIB_MCAST_RUN = 6,
- IPOIB_STOP_REAPER = 7,
- IPOIB_MCAST_STARTED = 8,
- IPOIB_FLAG_ADMIN_CM = 9,
+ IPOIB_MAX_MCAST_QUEUE = 3,
+
+ IPOIB_FLAG_OPER_UP = 0,
+ IPOIB_FLAG_INITIALIZED = 1,
+ IPOIB_FLAG_ADMIN_UP = 2,
+ IPOIB_PKEY_ASSIGNED = 3,
+ IPOIB_PKEY_STOP = 4,
+ IPOIB_FLAG_SUBINTERFACE = 5,
+ IPOIB_MCAST_RUN = 6,
+ IPOIB_STOP_REAPER = 7,
+ IPOIB_MCAST_STARTED = 8,
+ IPOIB_FLAG_ADMIN_CM = 9,
IPOIB_FLAG_UMCAST = 10,
IPOIB_MAX_BACKOFF_SECONDS = 16,
- IPOIB_MCAST_FLAG_FOUND = 0, /* used in set_multicast_list */
+ IPOIB_MCAST_FLAG_FOUND = 0, /* used in set_multicast_list */
IPOIB_MCAST_FLAG_SENDONLY = 1,
- IPOIB_MCAST_FLAG_BUSY = 2, /* joining or already joined */
+ IPOIB_MCAST_FLAG_BUSY = 2, /* joining or already joined */
IPOIB_MCAST_FLAG_ATTACHED = 3,
};
@@ -118,7 +117,7 @@ struct ipoib_pseudoheader {
struct ipoib_mcast {
struct ib_sa_mcmember_rec mcmember;
struct ib_sa_multicast *mc;
- struct ipoib_ah *ah;
+ struct ipoib_ah *ah;
struct rb_node rb_node;
struct list_head list;
@@ -187,29 +186,27 @@ enum ipoib_cm_state {
};
struct ipoib_cm_rx {
- struct ib_cm_id *id;
- struct ib_qp *qp;
- struct ipoib_cm_rx_buf *rx_ring;
- struct list_head list;
- struct net_device *dev;
- unsigned long jiffies;
- enum ipoib_cm_state state;
- int recv_count;
+ struct ib_cm_id *id;
+ struct ib_qp *qp;
+ struct list_head list;
+ struct net_device *dev;
+ unsigned long jiffies;
+ enum ipoib_cm_state state;
};
struct ipoib_cm_tx {
- struct ib_cm_id *id;
- struct ib_qp *qp;
+ struct ib_cm_id *id;
+ struct ib_qp *qp;
struct list_head list;
struct net_device *dev;
struct ipoib_neigh *neigh;
struct ipoib_path *path;
struct ipoib_tx_buf *tx_ring;
- unsigned tx_head;
- unsigned tx_tail;
- unsigned long flags;
- u32 mtu;
- struct ib_wc ibwc[IPOIB_NUM_WC];
+ unsigned tx_head;
+ unsigned tx_tail;
+ unsigned long flags;
+ u32 mtu;
+ struct ib_wc ibwc[IPOIB_NUM_WC];
};
struct ipoib_cm_rx_buf {
@@ -218,28 +215,25 @@ struct ipoib_cm_rx_buf {
};
struct ipoib_cm_dev_priv {
- struct ib_srq *srq;
+ struct ib_srq *srq;
struct ipoib_cm_rx_buf *srq_ring;
- struct ib_cm_id *id;
- struct list_head passive_ids; /* state: LIVE */
- struct list_head rx_error_list; /* state: ERROR */
- struct list_head rx_flush_list; /* state: FLUSH, drain not started */
- struct list_head rx_drain_list; /* state: FLUSH, drain started */
- struct list_head rx_reap_list; /* state: FLUSH, drain done */
+ struct ib_cm_id *id;
+ struct list_head passive_ids; /* state: LIVE */
+ struct list_head rx_error_list; /* state: ERROR */
+ struct list_head rx_flush_list; /* state: FLUSH, drain not started */
+ struct list_head rx_drain_list; /* state: FLUSH, drain started */
+ struct list_head rx_reap_list; /* state: FLUSH, drain done */
struct work_struct start_task;
struct work_struct reap_task;
struct work_struct skb_task;
struct work_struct rx_reap_task;
struct delayed_work stale_task;
struct sk_buff_head skb_queue;
- struct list_head start_list;
- struct list_head reap_list;
- struct ib_wc ibwc[IPOIB_NUM_WC];
- struct ib_sge rx_sge[IPOIB_CM_RX_SG];
+ struct list_head start_list;
+ struct list_head reap_list;
+ struct ib_wc ibwc[IPOIB_NUM_WC];
+ struct ib_sge rx_sge[IPOIB_CM_RX_SG];
struct ib_recv_wr rx_wr;
- int nonsrq_conn_qp;
- int max_cm_mtu;
- int num_frags;
};
/*
@@ -275,30 +269,30 @@ struct ipoib_dev_priv {
struct work_struct pkey_event_task;
struct ib_device *ca;
- u8 port;
- u16 pkey;
- u16 pkey_index;
- struct ib_pd *pd;
- struct ib_mr *mr;
- struct ib_cq *cq;
- struct ib_qp *qp;
- u32 qkey;
+ u8 port;
+ u16 pkey;
+ u16 pkey_index;
+ struct ib_pd *pd;
+ struct ib_mr *mr;
+ struct ib_cq *cq;
+ struct ib_qp *qp;
+ u32 qkey;
union ib_gid local_gid;
- u16 local_lid;
+ u16 local_lid;
unsigned int admin_mtu;
unsigned int mcast_mtu;
struct ipoib_rx_buf *rx_ring;
- spinlock_t tx_lock;
+ spinlock_t tx_lock;
struct ipoib_tx_buf *tx_ring;
- unsigned tx_head;
- unsigned tx_tail;
- struct ib_sge tx_sge;
+ unsigned tx_head;
+ unsigned tx_tail;
+ struct ib_sge tx_sge;
struct ib_send_wr tx_wr;
- unsigned tx_outstanding;
+ unsigned tx_outstanding;
struct ib_wc ibwc[IPOIB_NUM_WC];
@@ -323,10 +317,10 @@ struct ipoib_dev_priv {
struct ipoib_ah {
struct net_device *dev;
- struct ib_ah *ah;
+ struct ib_ah *ah;
struct list_head list;
- struct kref ref;
- unsigned last_send;
+ struct kref ref;
+ unsigned last_send;
};
struct ipoib_path {
@@ -337,11 +331,11 @@ struct ipoib_path {
struct list_head neigh_list;
- int query_id;
+ int query_id;
struct ib_sa_query *query;
struct completion done;
- struct rb_node rb_node;
+ struct rb_node rb_node;
struct list_head list;
};
@@ -350,7 +344,7 @@ struct ipoib_neigh {
#ifdef CONFIG_INFINIBAND_IPOIB_CM
struct ipoib_cm_tx *cm;
#endif
- union ib_gid dgid;
+ union ib_gid dgid;
struct sk_buff_head queue;
struct neighbour *neighbour;
@@ -461,14 +455,12 @@ void ipoib_drain_cq(struct net_device *dev);
#ifdef CONFIG_INFINIBAND_IPOIB_CM
-#define IPOIB_FLAGS_RC 0x80
-#define IPOIB_FLAGS_UC 0x40
+#define IPOIB_FLAGS_RC 0x80
+#define IPOIB_FLAGS_UC 0x40
/* We don't support UC connections at the moment */
#define IPOIB_CM_SUPPORTED(ha) (ha[0] & (IPOIB_FLAGS_RC))
-extern int ipoib_max_conn_qp;
-
static inline int ipoib_cm_admin_enabled(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -499,18 +491,6 @@ static inline void ipoib_cm_set(struct ipoib_neigh *neigh, struct ipoib_cm_tx *t
neigh->cm = tx;
}
-static inline int ipoib_cm_has_srq(struct net_device *dev)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- return !!priv->cm.srq;
-}
-
-static inline unsigned int ipoib_cm_max_mtu(struct net_device *dev)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- return priv->cm.max_cm_mtu;
-}
-
void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_tx *tx);
int ipoib_cm_dev_open(struct net_device *dev);
void ipoib_cm_dev_stop(struct net_device *dev);
@@ -520,7 +500,7 @@ void ipoib_cm_dev_cleanup(struct net_device *dev);
struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path *path,
struct ipoib_neigh *neigh);
void ipoib_cm_destroy_tx(struct ipoib_cm_tx *tx);
-void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb,
+void ipoib_cm_skb_too_long(struct net_device* dev, struct sk_buff *skb,
unsigned int mtu);
void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc);
void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc);
@@ -528,8 +508,6 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc);
struct ipoib_cm_tx;
-#define ipoib_max_conn_qp 0
-
static inline int ipoib_cm_admin_enabled(struct net_device *dev)
{
return 0;
@@ -555,16 +533,6 @@ static inline void ipoib_cm_set(struct ipoib_neigh *neigh, struct ipoib_cm_tx *t
{
}
-static inline int ipoib_cm_has_srq(struct net_device *dev)
-{
- return 0;
-}
-
-static inline unsigned int ipoib_cm_max_mtu(struct net_device *dev)
-{
- return 0;
-}
-
static inline
void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_tx *tx)
{
@@ -614,7 +582,7 @@ int ipoib_cm_add_mode_attr(struct net_device *dev)
return 0;
}
-static inline void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb,
+static inline void ipoib_cm_skb_too_long(struct net_device* dev, struct sk_buff *skb,
unsigned int mtu)
{
dev_kfree_skb_any(skb);
@@ -656,12 +624,12 @@ extern struct ib_sa_client ipoib_sa_client;
extern int ipoib_debug_level;
#define ipoib_dbg(priv, format, arg...) \
- do { \
+ do { \
if (ipoib_debug_level > 0) \
ipoib_printk(KERN_DEBUG, priv, format , ## arg); \
} while (0)
#define ipoib_dbg_mcast(priv, format, arg...) \
- do { \
+ do { \
if (mcast_debug_level > 0) \
ipoib_printk(KERN_DEBUG, priv, format , ## arg); \
} while (0)
@@ -674,7 +642,7 @@ extern int ipoib_debug_level;
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG_DATA
#define ipoib_dbg_data(priv, format, arg...) \
- do { \
+ do { \
if (data_debug_level > 0) \
ipoib_printk(KERN_DEBUG, priv, format , ## arg); \
} while (0)
diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 1818f958c250..059cf92b60a5 100644
--- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -39,15 +39,6 @@
#include
#include
-#include "ipoib.h"
-
-int ipoib_max_conn_qp = 128;
-
-module_param_named(max_nonsrq_conn_qp, ipoib_max_conn_qp, int, 0444);
-MODULE_PARM_DESC(max_nonsrq_conn_qp,
- "Max number of connected-mode QPs per interface "
- "(applied only if shared receive queue is not available)");
-
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG_DATA
static int data_debug_level;
@@ -56,6 +47,8 @@ MODULE_PARM_DESC(cm_data_debug_level,
"Enable data path debug tracing for connected mode if > 0");
#endif
+#include "ipoib.h"
+
#define IPOIB_CM_IETF_ID 0x1000000000000000ULL
#define IPOIB_CM_RX_UPDATE_TIME (256 * HZ)
@@ -88,7 +81,7 @@ static void ipoib_cm_dma_unmap_rx(struct ipoib_dev_priv *priv, int frags,
ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
}
-static int ipoib_cm_post_receive_srq(struct net_device *dev, int id)
+static int ipoib_cm_post_receive(struct net_device *dev, int id)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_recv_wr *bad_wr;
@@ -96,13 +89,13 @@ static int ipoib_cm_post_receive_srq(struct net_device *dev, int id)
priv->cm.rx_wr.wr_id = id | IPOIB_OP_CM | IPOIB_OP_RECV;
- for (i = 0; i < priv->cm.num_frags; ++i)
+ for (i = 0; i < IPOIB_CM_RX_SG; ++i)
priv->cm.rx_sge[i].addr = priv->cm.srq_ring[id].mapping[i];
ret = ib_post_srq_recv(priv->cm.srq, &priv->cm.rx_wr, &bad_wr);
if (unlikely(ret)) {
ipoib_warn(priv, "post srq failed for buf %d (%d)\n", id, ret);
- ipoib_cm_dma_unmap_rx(priv, priv->cm.num_frags - 1,
+ ipoib_cm_dma_unmap_rx(priv, IPOIB_CM_RX_SG - 1,
priv->cm.srq_ring[id].mapping);
dev_kfree_skb_any(priv->cm.srq_ring[id].skb);
priv->cm.srq_ring[id].skb = NULL;
@@ -111,33 +104,7 @@ static int ipoib_cm_post_receive_srq(struct net_device *dev, int id)
return ret;
}
-static int ipoib_cm_post_receive_nonsrq(struct net_device *dev,
- struct ipoib_cm_rx *rx, int id)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- struct ib_recv_wr *bad_wr;
- int i, ret;
-
- priv->cm.rx_wr.wr_id = id | IPOIB_OP_CM | IPOIB_OP_RECV;
-
- for (i = 0; i < IPOIB_CM_RX_SG; ++i)
- priv->cm.rx_sge[i].addr = rx->rx_ring[id].mapping[i];
-
- ret = ib_post_recv(rx->qp, &priv->cm.rx_wr, &bad_wr);
- if (unlikely(ret)) {
- ipoib_warn(priv, "post recv failed for buf %d (%d)\n", id, ret);
- ipoib_cm_dma_unmap_rx(priv, IPOIB_CM_RX_SG - 1,
- rx->rx_ring[id].mapping);
- dev_kfree_skb_any(rx->rx_ring[id].skb);
- rx->rx_ring[id].skb = NULL;
- }
-
- return ret;
-}
-
-static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev,
- struct ipoib_cm_rx_buf *rx_ring,
- int id, int frags,
+static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev, int id, int frags,
u64 mapping[IPOIB_CM_RX_SG])
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -174,7 +141,7 @@ static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev,
goto partial_error;
}
- rx_ring[id].skb = skb;
+ priv->cm.srq_ring[id].skb = skb;
return skb;
partial_error:
@@ -188,23 +155,7 @@ static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev,
return NULL;
}
-static void ipoib_cm_free_rx_ring(struct net_device *dev,
- struct ipoib_cm_rx_buf *rx_ring)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- int i;
-
- for (i = 0; i < ipoib_recvq_size; ++i)
- if (rx_ring[i].skb) {
- ipoib_cm_dma_unmap_rx(priv, IPOIB_CM_RX_SG - 1,
- rx_ring[i].mapping);
- dev_kfree_skb_any(rx_ring[i].skb);
- }
-
- kfree(rx_ring);
-}
-
-static void ipoib_cm_start_rx_drain(struct ipoib_dev_priv *priv)
+static void ipoib_cm_start_rx_drain(struct ipoib_dev_priv* priv)
{
struct ib_send_wr *bad_wr;
struct ipoib_cm_rx *p;
@@ -257,18 +208,12 @@ static struct ib_qp *ipoib_cm_create_rx_qp(struct net_device *dev,
.qp_type = IB_QPT_RC,
.qp_context = p,
};
-
- if (!ipoib_cm_has_srq(dev)) {
- attr.cap.max_recv_wr = ipoib_recvq_size;
- attr.cap.max_recv_sge = IPOIB_CM_RX_SG;
- }
-
return ib_create_qp(priv->pd, &attr);
}
static int ipoib_cm_modify_rx_qp(struct net_device *dev,
- struct ib_cm_id *cm_id, struct ib_qp *qp,
- unsigned psn)
+ struct ib_cm_id *cm_id, struct ib_qp *qp,
+ unsigned psn)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_qp_attr qp_attr;
@@ -321,60 +266,6 @@ static int ipoib_cm_modify_rx_qp(struct net_device *dev,
return 0;
}
-static int ipoib_cm_nonsrq_init_rx(struct net_device *dev, struct ib_cm_id *cm_id,
- struct ipoib_cm_rx *rx)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- int ret;
- int i;
-
- rx->rx_ring = kcalloc(ipoib_recvq_size, sizeof *rx->rx_ring, GFP_KERNEL);
- if (!rx->rx_ring)
- return -ENOMEM;
-
- spin_lock_irq(&priv->lock);
-
- if (priv->cm.nonsrq_conn_qp >= ipoib_max_conn_qp) {
- spin_unlock_irq(&priv->lock);
- ib_send_cm_rej(cm_id, IB_CM_REJ_NO_QP, NULL, 0, NULL, 0);
- ret = -EINVAL;
- goto err_free;
- } else
- ++priv->cm.nonsrq_conn_qp;
-
- spin_unlock_irq(&priv->lock);
-
- for (i = 0; i < ipoib_recvq_size; ++i) {
- if (!ipoib_cm_alloc_rx_skb(dev, rx->rx_ring, i, IPOIB_CM_RX_SG - 1,
- rx->rx_ring[i].mapping)) {
- ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
- ret = -ENOMEM;
- goto err_count;
- }
- ret = ipoib_cm_post_receive_nonsrq(dev, rx, i);
- if (ret) {
- ipoib_warn(priv, "ipoib_cm_post_receive_nonsrq "
- "failed for buf %d\n", i);
- ret = -EIO;
- goto err_count;
- }
- }
-
- rx->recv_count = ipoib_recvq_size;
-
- return 0;
-
-err_count:
- spin_lock_irq(&priv->lock);
- --priv->cm.nonsrq_conn_qp;
- spin_unlock_irq(&priv->lock);
-
-err_free:
- ipoib_cm_free_rx_ring(dev, rx->rx_ring);
-
- return ret;
-}
-
static int ipoib_cm_send_rep(struct net_device *dev, struct ib_cm_id *cm_id,
struct ib_qp *qp, struct ib_cm_req_event_param *req,
unsigned psn)
@@ -390,7 +281,7 @@ static int ipoib_cm_send_rep(struct net_device *dev, struct ib_cm_id *cm_id,
rep.private_data_len = sizeof data;
rep.flow_control = 0;
rep.rnr_retry_count = req->rnr_retry_count;
- rep.srq = ipoib_cm_has_srq(dev);
+ rep.srq = 1;
rep.qp_num = qp->qp_num;
rep.starting_psn = psn;
return ib_send_cm_rep(cm_id, &rep);
@@ -426,12 +317,6 @@ static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even
if (ret)
goto err_modify;
- if (!ipoib_cm_has_srq(dev)) {
- ret = ipoib_cm_nonsrq_init_rx(dev, cm_id, p);
- if (ret)
- goto err_modify;
- }
-
spin_lock_irq(&priv->lock);
queue_delayed_work(ipoib_workqueue,
&priv->cm.stale_task, IPOIB_CM_RX_DELAY);
@@ -516,14 +401,12 @@ static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space,
void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- struct ipoib_cm_rx_buf *rx_ring;
unsigned int wr_id = wc->wr_id & ~(IPOIB_OP_CM | IPOIB_OP_RECV);
struct sk_buff *skb, *newskb;
struct ipoib_cm_rx *p;
unsigned long flags;
u64 mapping[IPOIB_CM_RX_SG];
int frags;
- int has_srq;
ipoib_dbg_data(priv, "cm recv completion: id %d, status: %d\n",
wr_id, wc->status);
@@ -541,32 +424,18 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
return;
}
- p = wc->qp->qp_context;
-
- has_srq = ipoib_cm_has_srq(dev);
- rx_ring = has_srq ? priv->cm.srq_ring : p->rx_ring;
-
- skb = rx_ring[wr_id].skb;
+ skb = priv->cm.srq_ring[wr_id].skb;
if (unlikely(wc->status != IB_WC_SUCCESS)) {
ipoib_dbg(priv, "cm recv error "
"(status=%d, wrid=%d vend_err %x)\n",
wc->status, wr_id, wc->vendor_err);
++dev->stats.rx_dropped;
- if (has_srq)
- goto repost;
- else {
- if (!--p->recv_count) {
- spin_lock_irqsave(&priv->lock, flags);
- list_move(&p->list, &priv->cm.rx_reap_list);
- spin_unlock_irqrestore(&priv->lock, flags);
- queue_work(ipoib_workqueue, &priv->cm.rx_reap_task);
- }
- return;
- }
+ goto repost;
}
if (unlikely(!(wr_id & IPOIB_CM_RX_UPDATE_MASK))) {
+ p = wc->qp->qp_context;
if (p && time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_UPDATE_TIME)) {
spin_lock_irqsave(&priv->lock, flags);
p->jiffies = jiffies;
@@ -581,7 +450,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
frags = PAGE_ALIGN(wc->byte_len - min(wc->byte_len,
(unsigned)IPOIB_CM_HEAD_SIZE)) / PAGE_SIZE;
- newskb = ipoib_cm_alloc_rx_skb(dev, rx_ring, wr_id, frags, mapping);
+ newskb = ipoib_cm_alloc_rx_skb(dev, wr_id, frags, mapping);
if (unlikely(!newskb)) {
/*
* If we can't allocate a new RX buffer, dump
@@ -592,8 +461,8 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
goto repost;
}
- ipoib_cm_dma_unmap_rx(priv, frags, rx_ring[wr_id].mapping);
- memcpy(rx_ring[wr_id].mapping, mapping, (frags + 1) * sizeof *mapping);
+ ipoib_cm_dma_unmap_rx(priv, frags, priv->cm.srq_ring[wr_id].mapping);
+ memcpy(priv->cm.srq_ring[wr_id].mapping, mapping, (frags + 1) * sizeof *mapping);
ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n",
wc->byte_len, wc->slid);
@@ -614,17 +483,9 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
netif_receive_skb(skb);
repost:
- if (has_srq) {
- if (unlikely(ipoib_cm_post_receive_srq(dev, wr_id)))
- ipoib_warn(priv, "ipoib_cm_post_receive_srq failed "
- "for buf %d\n", wr_id);
- } else {
- if (unlikely(ipoib_cm_post_receive_nonsrq(dev, p, wr_id))) {
- --p->recv_count;
- ipoib_warn(priv, "ipoib_cm_post_receive_nonsrq failed "
- "for buf %d\n", wr_id);
- }
- }
+ if (unlikely(ipoib_cm_post_receive(dev, wr_id)))
+ ipoib_warn(priv, "ipoib_cm_post_receive failed "
+ "for buf %d\n", wr_id);
}
static inline int post_send(struct ipoib_dev_priv *priv,
@@ -634,10 +495,10 @@ static inline int post_send(struct ipoib_dev_priv *priv,
{
struct ib_send_wr *bad_wr;
- priv->tx_sge.addr = addr;
- priv->tx_sge.length = len;
+ priv->tx_sge.addr = addr;
+ priv->tx_sge.length = len;
- priv->tx_wr.wr_id = wr_id | IPOIB_OP_CM;
+ priv->tx_wr.wr_id = wr_id | IPOIB_OP_CM;
return ib_post_send(tx->qp, &priv->tx_wr, &bad_wr);
}
@@ -679,7 +540,7 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
tx_req->mapping = addr;
if (unlikely(post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1),
- addr, skb->len))) {
+ addr, skb->len))) {
ipoib_warn(priv, "post_send failed\n");
++dev->stats.tx_errors;
ib_dma_unmap_single(priv->ca, addr, skb->len, DMA_TO_DEVICE);
@@ -796,33 +657,10 @@ int ipoib_cm_dev_open(struct net_device *dev)
return ret;
}
-static void ipoib_cm_free_rx_reap_list(struct net_device *dev)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- struct ipoib_cm_rx *rx, *n;
- LIST_HEAD(list);
-
- spin_lock_irq(&priv->lock);
- list_splice_init(&priv->cm.rx_reap_list, &list);
- spin_unlock_irq(&priv->lock);
-
- list_for_each_entry_safe(rx, n, &list, list) {
- ib_destroy_cm_id(rx->id);
- ib_destroy_qp(rx->qp);
- if (!ipoib_cm_has_srq(dev)) {
- ipoib_cm_free_rx_ring(priv->dev, rx->rx_ring);
- spin_lock_irq(&priv->lock);
- --priv->cm.nonsrq_conn_qp;
- spin_unlock_irq(&priv->lock);
- }
- kfree(rx);
- }
-}
-
void ipoib_cm_dev_stop(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- struct ipoib_cm_rx *p;
+ struct ipoib_cm_rx *p, *n;
unsigned long begin;
LIST_HEAD(list);
int ret;
@@ -868,9 +706,15 @@ void ipoib_cm_dev_stop(struct net_device *dev)
spin_lock_irq(&priv->lock);
}
+ list_splice_init(&priv->cm.rx_reap_list, &list);
+
spin_unlock_irq(&priv->lock);
- ipoib_cm_free_rx_reap_list(dev);
+ list_for_each_entry_safe(p, n, &list, list) {
+ ib_destroy_cm_id(p->id);
+ ib_destroy_qp(p->qp);
+ kfree(p);
+ }
cancel_delayed_work(&priv->cm.stale_task);
}
@@ -955,7 +799,7 @@ static struct ib_qp *ipoib_cm_create_tx_qp(struct net_device *dev, struct ipoib_
.sq_sig_type = IB_SIGNAL_ALL_WR,
.qp_type = IB_QPT_RC,
.qp_context = tx
- };
+ };
return ib_create_qp(priv->pd, &attr);
}
@@ -972,28 +816,28 @@ static int ipoib_cm_send_req(struct net_device *dev,
data.qpn = cpu_to_be32(priv->qp->qp_num);
data.mtu = cpu_to_be32(IPOIB_CM_BUF_SIZE);
- req.primary_path = pathrec;
- req.alternate_path = NULL;
- req.service_id = cpu_to_be64(IPOIB_CM_IETF_ID | qpn);
- req.qp_num = qp->qp_num;
- req.qp_type = qp->qp_type;
- req.private_data = &data;
- req.private_data_len = sizeof data;
- req.flow_control = 0;
+ req.primary_path = pathrec;
+ req.alternate_path = NULL;
+ req.service_id = cpu_to_be64(IPOIB_CM_IETF_ID | qpn);
+ req.qp_num = qp->qp_num;
+ req.qp_type = qp->qp_type;
+ req.private_data = &data;
+ req.private_data_len = sizeof data;
+ req.flow_control = 0;
- req.starting_psn = 0; /* FIXME */
+ req.starting_psn = 0; /* FIXME */
/*
* Pick some arbitrary defaults here; we could make these
* module parameters if anyone cared about setting them.
*/
- req.responder_resources = 4;
- req.remote_cm_response_timeout = 20;
- req.local_cm_response_timeout = 20;
- req.retry_count = 0; /* RFC draft warns against retries */
- req.rnr_retry_count = 0; /* RFC draft warns against retries */
- req.max_cm_retries = 15;
- req.srq = ipoib_cm_has_srq(dev);
+ req.responder_resources = 4;
+ req.remote_cm_response_timeout = 20;
+ req.local_cm_response_timeout = 20;
+ req.retry_count = 0; /* RFC draft warns against retries */
+ req.rnr_retry_count = 0; /* RFC draft warns against retries */
+ req.max_cm_retries = 15;
+ req.srq = 1;
return ib_send_cm_req(id, &req);
}
@@ -1306,7 +1150,7 @@ static void ipoib_cm_skb_reap(struct work_struct *work)
spin_unlock_irq(&priv->tx_lock);
}
-void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb,
+void ipoib_cm_skb_too_long(struct net_device* dev, struct sk_buff *skb,
unsigned int mtu)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -1322,8 +1166,20 @@ void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb,
static void ipoib_cm_rx_reap(struct work_struct *work)
{
- ipoib_cm_free_rx_reap_list(container_of(work, struct ipoib_dev_priv,
- cm.rx_reap_task)->dev);
+ struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
+ cm.rx_reap_task);
+ struct ipoib_cm_rx *p, *n;
+ LIST_HEAD(list);
+
+ spin_lock_irq(&priv->lock);
+ list_splice_init(&priv->cm.rx_reap_list, &list);
+ spin_unlock_irq(&priv->lock);
+
+ list_for_each_entry_safe(p, n, &list, list) {
+ ib_destroy_cm_id(p->id);
+ ib_destroy_qp(p->qp);
+ kfree(p);
+ }
}
static void ipoib_cm_stale_task(struct work_struct *work)
@@ -1356,7 +1212,7 @@ static void ipoib_cm_stale_task(struct work_struct *work)
}
-static ssize_t show_mode(struct device *d, struct device_attribute *attr,
+static ssize_t show_mode(struct device *d, struct device_attribute *attr,
char *buf)
{
struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(d));
@@ -1399,40 +1255,16 @@ int ipoib_cm_add_mode_attr(struct net_device *dev)
return device_create_file(&dev->dev, &dev_attr_mode);
}
-static void ipoib_cm_create_srq(struct net_device *dev, int max_sge)
+int ipoib_cm_dev_init(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_srq_init_attr srq_init_attr = {
.attr = {
.max_wr = ipoib_recvq_size,
- .max_sge = max_sge
+ .max_sge = IPOIB_CM_RX_SG
}
};
-
- priv->cm.srq = ib_create_srq(priv->pd, &srq_init_attr);
- if (IS_ERR(priv->cm.srq)) {
- if (PTR_ERR(priv->cm.srq) != -ENOSYS)
- printk(KERN_WARNING "%s: failed to allocate SRQ, error %ld\n",
- priv->ca->name, PTR_ERR(priv->cm.srq));
- priv->cm.srq = NULL;
- return;
- }
-
- priv->cm.srq_ring = kzalloc(ipoib_recvq_size * sizeof *priv->cm.srq_ring,
- GFP_KERNEL);
- if (!priv->cm.srq_ring) {
- printk(KERN_WARNING "%s: failed to allocate CM SRQ ring (%d entries)\n",
- priv->ca->name, ipoib_recvq_size);
- ib_destroy_srq(priv->cm.srq);
- priv->cm.srq = NULL;
- }
-}
-
-int ipoib_cm_dev_init(struct net_device *dev)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- int i, ret;
- struct ib_device_attr attr;
+ int ret, i;
INIT_LIST_HEAD(&priv->cm.passive_ids);
INIT_LIST_HEAD(&priv->cm.reap_list);
@@ -1449,53 +1281,43 @@ int ipoib_cm_dev_init(struct net_device *dev)
skb_queue_head_init(&priv->cm.skb_queue);
- ret = ib_query_device(priv->ca, &attr);
- if (ret) {
- printk(KERN_WARNING "ib_query_device() failed with %d\n", ret);
+ priv->cm.srq = ib_create_srq(priv->pd, &srq_init_attr);
+ if (IS_ERR(priv->cm.srq)) {
+ ret = PTR_ERR(priv->cm.srq);
+ priv->cm.srq = NULL;
return ret;
}
- ipoib_dbg(priv, "max_srq_sge=%d\n", attr.max_srq_sge);
-
- attr.max_srq_sge = min_t(int, IPOIB_CM_RX_SG, attr.max_srq_sge);
- ipoib_cm_create_srq(dev, attr.max_srq_sge);
- if (ipoib_cm_has_srq(dev)) {
- priv->cm.max_cm_mtu = attr.max_srq_sge * PAGE_SIZE - 0x10;
- priv->cm.num_frags = attr.max_srq_sge;
- ipoib_dbg(priv, "max_cm_mtu = 0x%x, num_frags=%d\n",
- priv->cm.max_cm_mtu, priv->cm.num_frags);
- } else {
- priv->cm.max_cm_mtu = IPOIB_CM_MTU;
- priv->cm.num_frags = IPOIB_CM_RX_SG;
+ priv->cm.srq_ring = kzalloc(ipoib_recvq_size * sizeof *priv->cm.srq_ring,
+ GFP_KERNEL);
+ if (!priv->cm.srq_ring) {
+ printk(KERN_WARNING "%s: failed to allocate CM ring (%d entries)\n",
+ priv->ca->name, ipoib_recvq_size);
+ ipoib_cm_dev_cleanup(dev);
+ return -ENOMEM;
}
- for (i = 0; i < priv->cm.num_frags; ++i)
+ for (i = 0; i < IPOIB_CM_RX_SG; ++i)
priv->cm.rx_sge[i].lkey = priv->mr->lkey;
priv->cm.rx_sge[0].length = IPOIB_CM_HEAD_SIZE;
- for (i = 1; i < priv->cm.num_frags; ++i)
+ for (i = 1; i < IPOIB_CM_RX_SG; ++i)
priv->cm.rx_sge[i].length = PAGE_SIZE;
priv->cm.rx_wr.next = NULL;
priv->cm.rx_wr.sg_list = priv->cm.rx_sge;
- priv->cm.rx_wr.num_sge = priv->cm.num_frags;
-
- if (ipoib_cm_has_srq(dev)) {
- for (i = 0; i < ipoib_recvq_size; ++i) {
- if (!ipoib_cm_alloc_rx_skb(dev, priv->cm.srq_ring, i,
- priv->cm.num_frags - 1,
- priv->cm.srq_ring[i].mapping)) {
- ipoib_warn(priv, "failed to allocate "
- "receive buffer %d\n", i);
- ipoib_cm_dev_cleanup(dev);
- return -ENOMEM;
- }
+ priv->cm.rx_wr.num_sge = IPOIB_CM_RX_SG;
- if (ipoib_cm_post_receive_srq(dev, i)) {
- ipoib_warn(priv, "ipoib_cm_post_receive_srq "
- "failed for buf %d\n", i);
- ipoib_cm_dev_cleanup(dev);
- return -EIO;
- }
+ for (i = 0; i < ipoib_recvq_size; ++i) {
+ if (!ipoib_cm_alloc_rx_skb(dev, i, IPOIB_CM_RX_SG - 1,
+ priv->cm.srq_ring[i].mapping)) {
+ ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
+ ipoib_cm_dev_cleanup(dev);
+ return -ENOMEM;
+ }
+ if (ipoib_cm_post_receive(dev, i)) {
+ ipoib_warn(priv, "ipoib_ib_post_receive failed for buf %d\n", i);
+ ipoib_cm_dev_cleanup(dev);
+ return -EIO;
}
}
@@ -1506,7 +1328,7 @@ int ipoib_cm_dev_init(struct net_device *dev)
void ipoib_cm_dev_cleanup(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- int ret;
+ int i, ret;
if (!priv->cm.srq)
return;
@@ -1520,7 +1342,13 @@ void ipoib_cm_dev_cleanup(struct net_device *dev)
priv->cm.srq = NULL;
if (!priv->cm.srq_ring)
return;
-
- ipoib_cm_free_rx_ring(dev, priv->cm.srq_ring);
+ for (i = 0; i < ipoib_recvq_size; ++i)
+ if (priv->cm.srq_ring[i].skb) {
+ ipoib_cm_dma_unmap_rx(priv, IPOIB_CM_RX_SG - 1,
+ priv->cm.srq_ring[i].mapping);
+ dev_kfree_skb_any(priv->cm.srq_ring[i].skb);
+ priv->cm.srq_ring[i].skb = NULL;
+ }
+ kfree(priv->cm.srq_ring);
priv->cm.srq_ring = NULL;
}
diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index 8b882bbd1d05..44c174182a82 100644
--- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -124,7 +124,7 @@ static int ipoib_mcg_seq_show(struct seq_file *file, void *iter_ptr)
return 0;
}
-static const struct seq_operations ipoib_mcg_seq_ops = {
+static struct seq_operations ipoib_mcg_seq_ops = {
.start = ipoib_mcg_seq_start,
.next = ipoib_mcg_seq_next,
.stop = ipoib_mcg_seq_stop,
@@ -230,7 +230,7 @@ static int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr)
return 0;
}
-static const struct seq_operations ipoib_path_seq_ops = {
+static struct seq_operations ipoib_path_seq_ops = {
.start = ipoib_path_seq_start,
.next = ipoib_path_seq_next,
.stop = ipoib_path_seq_stop,
diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 52bc2bd5799a..5063dd509ad2 100644
--- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -345,12 +345,12 @@ static inline int post_send(struct ipoib_dev_priv *priv,
{
struct ib_send_wr *bad_wr;
- priv->tx_sge.addr = addr;
- priv->tx_sge.length = len;
+ priv->tx_sge.addr = addr;
+ priv->tx_sge.length = len;
- priv->tx_wr.wr_id = wr_id;
+ priv->tx_wr.wr_id = wr_id;
priv->tx_wr.wr.ud.remote_qpn = qpn;
- priv->tx_wr.wr.ud.ah = address;
+ priv->tx_wr.wr.ud.ah = address;
return ib_post_send(priv->qp, &priv->tx_wr, &bad_wr);
}
diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c
index a082466f4a83..c9f6077b615e 100644
--- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -182,20 +182,17 @@ static int ipoib_change_mtu(struct net_device *dev, int new_mtu)
struct ipoib_dev_priv *priv = netdev_priv(dev);
/* dev->mtu > 2K ==> connected mode */
- if (ipoib_cm_admin_enabled(dev)) {
- if (new_mtu > ipoib_cm_max_mtu(dev))
- return -EINVAL;
-
+ if (ipoib_cm_admin_enabled(dev) && new_mtu <= IPOIB_CM_MTU) {
if (new_mtu > priv->mcast_mtu)
ipoib_warn(priv, "mtu > %d will cause multicast packet drops.\n",
priv->mcast_mtu);
-
dev->mtu = new_mtu;
return 0;
}
- if (new_mtu > IPOIB_PACKET_SIZE - IPOIB_ENCAP_LEN)
+ if (new_mtu > IPOIB_PACKET_SIZE - IPOIB_ENCAP_LEN) {
return -EINVAL;
+ }
priv->admin_mtu = new_mtu;
@@ -477,8 +474,8 @@ static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid)
INIT_LIST_HEAD(&path->neigh_list);
memcpy(path->pathrec.dgid.raw, gid, sizeof (union ib_gid));
- path->pathrec.sgid = priv->local_gid;
- path->pathrec.pkey = cpu_to_be16(priv->pkey);
+ path->pathrec.sgid = priv->local_gid;
+ path->pathrec.pkey = cpu_to_be16(priv->pkey);
path->pathrec.numb_path = 1;
path->pathrec.traffic_class = priv->broadcast->mcmember.traffic_class;
@@ -672,6 +669,16 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (unlikely(!spin_trylock_irqsave(&priv->tx_lock, flags)))
return NETDEV_TX_LOCKED;
+ /*
+ * Check if our queue is stopped. Since we have the LLTX bit
+ * set, we can't rely on netif_stop_queue() preventing our
+ * xmit function from being called with a full queue.
+ */
+ if (unlikely(netif_queue_stopped(dev))) {
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+ return NETDEV_TX_BUSY;
+ }
+
if (likely(skb->dst && skb->dst->neighbour)) {
if (unlikely(!*to_ipoib_neigh(skb->dst->neighbour))) {
ipoib_path_lookup(skb, dev);
@@ -943,34 +950,34 @@ static void ipoib_setup(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- dev->open = ipoib_open;
- dev->stop = ipoib_stop;
- dev->change_mtu = ipoib_change_mtu;
- dev->hard_start_xmit = ipoib_start_xmit;
- dev->tx_timeout = ipoib_timeout;
- dev->header_ops = &ipoib_header_ops;
- dev->set_multicast_list = ipoib_set_mcast_list;
- dev->neigh_setup = ipoib_neigh_setup_dev;
+ dev->open = ipoib_open;
+ dev->stop = ipoib_stop;
+ dev->change_mtu = ipoib_change_mtu;
+ dev->hard_start_xmit = ipoib_start_xmit;
+ dev->tx_timeout = ipoib_timeout;
+ dev->header_ops = &ipoib_header_ops;
+ dev->set_multicast_list = ipoib_set_mcast_list;
+ dev->neigh_setup = ipoib_neigh_setup_dev;
netif_napi_add(dev, &priv->napi, ipoib_poll, 100);
- dev->watchdog_timeo = HZ;
+ dev->watchdog_timeo = HZ;
- dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+ dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
/*
* We add in INFINIBAND_ALEN to allow for the destination
* address "pseudoheader" for skbs without neighbour struct.
*/
- dev->hard_header_len = IPOIB_ENCAP_LEN + INFINIBAND_ALEN;
- dev->addr_len = INFINIBAND_ALEN;
- dev->type = ARPHRD_INFINIBAND;
- dev->tx_queue_len = ipoib_sendq_size * 2;
- dev->features = NETIF_F_VLAN_CHALLENGED | NETIF_F_LLTX;
+ dev->hard_header_len = IPOIB_ENCAP_LEN + INFINIBAND_ALEN;
+ dev->addr_len = INFINIBAND_ALEN;
+ dev->type = ARPHRD_INFINIBAND;
+ dev->tx_queue_len = ipoib_sendq_size * 2;
+ dev->features = NETIF_F_VLAN_CHALLENGED | NETIF_F_LLTX;
/* MTU will be reset when mcast join happens */
- dev->mtu = IPOIB_PACKET_SIZE - IPOIB_ENCAP_LEN;
- priv->mcast_mtu = priv->admin_mtu = dev->mtu;
+ dev->mtu = IPOIB_PACKET_SIZE - IPOIB_ENCAP_LEN;
+ priv->mcast_mtu = priv->admin_mtu = dev->mtu;
memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN);
@@ -1261,9 +1268,6 @@ static int __init ipoib_init_module(void)
ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size);
ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE);
ipoib_sendq_size = max(ipoib_sendq_size, IPOIB_MIN_QUEUE_SIZE);
-#ifdef CONFIG_INFINIBAND_IPOIB_CM
- ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP);
-#endif
ret = ipoib_register_debugfs();
if (ret)
diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 2628339e3a99..9bcfc7ad6aa6 100644
--- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -702,7 +702,7 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
out:
if (mcast && mcast->ah) {
- if (skb->dst &&
+ if (skb->dst &&
skb->dst->neighbour &&
!*to_ipoib_neigh(skb->dst->neighbour)) {
struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour,
@@ -710,7 +710,7 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
if (neigh) {
kref_get(&mcast->ah->ref);
- neigh->ah = mcast->ah;
+ neigh->ah = mcast->ah;
list_add_tail(&neigh->list, &mcast->neigh_list);
}
}
@@ -788,6 +788,10 @@ void ipoib_mcast_restart_task(struct work_struct *work)
memcpy(mgid.raw, mclist->dmi_addr + 4, sizeof mgid);
+ /* Add in the P_Key */
+ mgid.raw[4] = (priv->pkey >> 8) & 0xff;
+ mgid.raw[5] = priv->pkey & 0xff;
+
mcast = __ipoib_mcast_find(dev, &mgid);
if (!mcast || test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
struct ipoib_mcast *nmcast;
diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 433e99ac227b..3c6e45db0ab5 100644
--- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -172,12 +172,8 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
size = ipoib_sendq_size + ipoib_recvq_size + 1;
ret = ipoib_cm_dev_init(dev);
- if (!ret) {
- if (ipoib_cm_has_srq(dev))
- size += ipoib_recvq_size + 1; /* 1 extra for rx_drain_qp */
- else
- size += ipoib_recvq_size * ipoib_max_conn_qp;
- }
+ if (!ret)
+ size += ipoib_recvq_size + 1 /* 1 extra for rx_drain_qp */;
priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0);
if (IS_ERR(priv->cq)) {
@@ -201,12 +197,12 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
priv->dev->dev_addr[2] = (priv->qp->qp_num >> 8) & 0xff;
priv->dev->dev_addr[3] = (priv->qp->qp_num ) & 0xff;
- priv->tx_sge.lkey = priv->mr->lkey;
+ priv->tx_sge.lkey = priv->mr->lkey;
- priv->tx_wr.opcode = IB_WR_SEND;
- priv->tx_wr.sg_list = &priv->tx_sge;
- priv->tx_wr.num_sge = 1;
- priv->tx_wr.send_flags = IB_SEND_SIGNALED;
+ priv->tx_wr.opcode = IB_WR_SEND;
+ priv->tx_wr.sg_list = &priv->tx_sge;
+ priv->tx_wr.num_sge = 1;
+ priv->tx_wr.send_flags = IB_SEND_SIGNALED;
return 0;
diff --git a/trunk/drivers/infiniband/ulp/iser/Kconfig b/trunk/drivers/infiniband/ulp/iser/Kconfig
index 77dedba829e6..fe604c8d2996 100644
--- a/trunk/drivers/infiniband/ulp/iser/Kconfig
+++ b/trunk/drivers/infiniband/ulp/iser/Kconfig
@@ -8,5 +8,5 @@ config INFINIBAND_ISER
that speak iSCSI over iSER over InfiniBand.
The iSER protocol is defined by IETF.
- See
- and
+ See
+ and
diff --git a/trunk/drivers/infiniband/ulp/iser/iscsi_iser.c b/trunk/drivers/infiniband/ulp/iser/iscsi_iser.c
index dfa5a4544187..bad8dacafd10 100644
--- a/trunk/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/trunk/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -551,7 +551,6 @@ static struct scsi_host_template iscsi_iser_sht = {
.module = THIS_MODULE,
.name = "iSCSI Initiator over iSER, v." DRV_VER,
.queuecommand = iscsi_queuecommand,
- .change_queue_depth = iscsi_change_queue_depth,
.can_queue = ISCSI_DEF_XMIT_CMDS_MAX - 1,
.sg_tablesize = ISCSI_ISER_SG_TABLESIZE,
.max_sectors = 1024,
diff --git a/trunk/drivers/infiniband/ulp/iser/iser_initiator.c b/trunk/drivers/infiniband/ulp/iser/iser_initiator.c
index ba1b455949c0..a6f2303ed14a 100644
--- a/trunk/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/trunk/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -561,7 +561,7 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
if (opcode == ISCSI_OP_SCSI_CMD_RSP) {
itt = get_itt(hdr->itt); /* mask out cid and age bits */
if (!(itt < session->cmds_max))
- iser_err("itt can't be matched to task!!! "
+ iser_err("itt can't be matched to task!!!"
"conn %p opcode %d cmds_max %d itt %d\n",
conn->iscsi_conn,opcode,session->cmds_max,itt);
/* use the mapping given with the cmds array indexed by itt */
diff --git a/trunk/drivers/infiniband/ulp/iser/iser_verbs.c b/trunk/drivers/infiniband/ulp/iser/iser_verbs.c
index 714b8db02b29..654a4dce0236 100644
--- a/trunk/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/trunk/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -105,7 +105,7 @@ static int iser_create_device_ib_res(struct iser_device *device)
}
/**
- * iser_free_device_ib_res - destroy/dealloc/dereg the DMA MR,
+ * iser_free_device_ib_res - destory/dealloc/dereg the DMA MR,
* CQ and PD created with the device associated with the adapator.
*/
static void iser_free_device_ib_res(struct iser_device *device)
@@ -475,11 +475,13 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve
iser_disconnected_handler(cma_id);
break;
case RDMA_CM_EVENT_DEVICE_REMOVAL:
- iser_err("Device removal is currently unsupported\n");
BUG();
break;
+ case RDMA_CM_EVENT_CONNECT_RESPONSE:
+ BUG();
+ break;
+ case RDMA_CM_EVENT_CONNECT_REQUEST:
default:
- iser_err("Unexpected RDMA CM event (%d)\n", event->event);
break;
}
return ret;
diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.c b/trunk/drivers/infiniband/ulp/srp/ib_srp.c
index f2d2c7e2c76b..bdb6f8517401 100644
--- a/trunk/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.c
@@ -272,8 +272,7 @@ static void srp_path_rec_completion(int status,
target->status = status;
if (status)
- shost_printk(KERN_ERR, target->scsi_host,
- PFX "Got failed path rec status %d\n", status);
+ printk(KERN_ERR PFX "Got failed path rec status %d\n", status);
else
target->path = *pathrec;
complete(&target->done);
@@ -304,8 +303,7 @@ static int srp_lookup_path(struct srp_target_port *target)
wait_for_completion(&target->done);
if (target->status < 0)
- shost_printk(KERN_WARNING, target->scsi_host,
- PFX "Path record query failed\n");
+ printk(KERN_WARNING PFX "Path record query failed\n");
return target->status;
}
@@ -381,10 +379,9 @@ static int srp_send_req(struct srp_target_port *target)
* the second 8 bytes to the local node GUID.
*/
if (srp_target_is_topspin(target)) {
- shost_printk(KERN_DEBUG, target->scsi_host,
- PFX "Topspin/Cisco initiator port ID workaround "
- "activated for target GUID %016llx\n",
- (unsigned long long) be64_to_cpu(target->ioc_guid));
+ printk(KERN_DEBUG PFX "Topspin/Cisco initiator port ID workaround "
+ "activated for target GUID %016llx\n",
+ (unsigned long long) be64_to_cpu(target->ioc_guid));
memset(req->priv.initiator_port_id, 0, 8);
memcpy(req->priv.initiator_port_id + 8,
&target->srp_host->dev->dev->node_guid, 8);
@@ -403,8 +400,7 @@ static void srp_disconnect_target(struct srp_target_port *target)
init_completion(&target->done);
if (ib_send_cm_dreq(target->cm_id, NULL, 0)) {
- shost_printk(KERN_DEBUG, target->scsi_host,
- PFX "Sending CM DREQ failed\n");
+ printk(KERN_DEBUG PFX "Sending CM DREQ failed\n");
return;
}
wait_for_completion(&target->done);
@@ -572,8 +568,7 @@ static int srp_reconnect_target(struct srp_target_port *target)
return ret;
err:
- shost_printk(KERN_ERR, target->scsi_host,
- PFX "reconnect failed (%d), removing target port.\n", ret);
+ printk(KERN_ERR PFX "reconnect failed (%d), removing target port.\n", ret);
/*
* We couldn't reconnect, so kill our target port off.
@@ -688,9 +683,8 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
if (scmnd->sc_data_direction != DMA_FROM_DEVICE &&
scmnd->sc_data_direction != DMA_TO_DEVICE) {
- shost_printk(KERN_WARNING, target->scsi_host,
- PFX "Unhandled data direction %d\n",
- scmnd->sc_data_direction);
+ printk(KERN_WARNING PFX "Unhandled data direction %d\n",
+ scmnd->sc_data_direction);
return -EINVAL;
}
@@ -792,9 +786,8 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
} else {
scmnd = req->scmnd;
if (!scmnd)
- shost_printk(KERN_ERR, target->scsi_host,
- "Null scmnd for RSP w/tag %016llx\n",
- (unsigned long long) rsp->tag);
+ printk(KERN_ERR "Null scmnd for RSP w/tag %016llx\n",
+ (unsigned long long) rsp->tag);
scmnd->result = rsp->status;
if (rsp->flags & SRP_RSP_FLAG_SNSVALID) {
@@ -838,8 +831,7 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
if (0) {
int i;
- shost_printk(KERN_ERR, target->scsi_host,
- PFX "recv completion, opcode 0x%02x\n", opcode);
+ printk(KERN_ERR PFX "recv completion, opcode 0x%02x\n", opcode);
for (i = 0; i < wc->byte_len; ++i) {
if (i % 8 == 0)
@@ -860,13 +852,11 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
case SRP_T_LOGOUT:
/* XXX Handle target logout */
- shost_printk(KERN_WARNING, target->scsi_host,
- PFX "Got target logout request\n");
+ printk(KERN_WARNING PFX "Got target logout request\n");
break;
default:
- shost_printk(KERN_WARNING, target->scsi_host,
- PFX "Unhandled SRP opcode 0x%02x\n", opcode);
+ printk(KERN_WARNING PFX "Unhandled SRP opcode 0x%02x\n", opcode);
break;
}
@@ -882,10 +872,9 @@ static void srp_completion(struct ib_cq *cq, void *target_ptr)
ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
while (ib_poll_cq(cq, 1, &wc) > 0) {
if (wc.status) {
- shost_printk(KERN_ERR, target->scsi_host,
- PFX "failed %s status %d\n",
- wc.wr_id & SRP_OP_RECV ? "receive" : "send",
- wc.status);
+ printk(KERN_ERR PFX "failed %s status %d\n",
+ wc.wr_id & SRP_OP_RECV ? "receive" : "send",
+ wc.status);
target->qp_in_error = 1;
break;
}
@@ -941,18 +930,13 @@ static int srp_post_recv(struct srp_target_port *target)
* req_lim and tx_head. Lock cannot be dropped between call here and
* call to __srp_post_send().
*/
-static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
- enum srp_request_type req_type)
+static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target)
{
- s32 min = (req_type == SRP_REQ_TASK_MGMT) ? 1 : 2;
-
if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
return NULL;
- if (target->req_lim < min) {
+ if (unlikely(target->req_lim < 1))
++target->zero_req_lim;
- return NULL;
- }
return target->tx_ring[target->tx_head & SRP_SQ_SIZE];
}
@@ -1009,7 +993,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
return 0;
}
- iu = __srp_get_tx_iu(target, SRP_REQ_NORMAL);
+ iu = __srp_get_tx_iu(target);
if (!iu)
goto err;
@@ -1038,13 +1022,12 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
len = srp_map_data(scmnd, target, req);
if (len < 0) {
- shost_printk(KERN_ERR, target->scsi_host,
- PFX "Failed to map data\n");
+ printk(KERN_ERR PFX "Failed to map data\n");
goto err;
}
if (__srp_post_recv(target)) {
- shost_printk(KERN_ERR, target->scsi_host, PFX "Recv failed\n");
+ printk(KERN_ERR PFX "Recv failed\n");
goto err_unmap;
}
@@ -1052,7 +1035,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
DMA_TO_DEVICE);
if (__srp_post_send(target, iu, len)) {
- shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n");
+ printk(KERN_ERR PFX "Send failed\n");
goto err_unmap;
}
@@ -1107,7 +1090,6 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
struct ib_cm_event *event,
struct srp_target_port *target)
{
- struct Scsi_Host *shost = target->scsi_host;
struct ib_class_port_info *cpi;
int opcode;
@@ -1133,22 +1115,19 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
memcpy(target->path.dgid.raw,
event->param.rej_rcvd.ari, 16);
- shost_printk(KERN_DEBUG, shost,
- PFX "Topspin/Cisco redirect to target port GID %016llx%016llx\n",
- (unsigned long long) be64_to_cpu(target->path.dgid.global.subnet_prefix),
- (unsigned long long) be64_to_cpu(target->path.dgid.global.interface_id));
+ printk(KERN_DEBUG PFX "Topspin/Cisco redirect to target port GID %016llx%016llx\n",
+ (unsigned long long) be64_to_cpu(target->path.dgid.global.subnet_prefix),
+ (unsigned long long) be64_to_cpu(target->path.dgid.global.interface_id));
target->status = SRP_PORT_REDIRECT;
} else {
- shost_printk(KERN_WARNING, shost,
- " REJ reason: IB_CM_REJ_PORT_REDIRECT\n");
+ printk(KERN_WARNING " REJ reason: IB_CM_REJ_PORT_REDIRECT\n");
target->status = -ECONNRESET;
}
break;
case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
- shost_printk(KERN_WARNING, shost,
- " REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
+ printk(KERN_WARNING " REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
target->status = -ECONNRESET;
break;
@@ -1159,21 +1138,20 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
u32 reason = be32_to_cpu(rej->reason);
if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
- shost_printk(KERN_WARNING, shost,
- PFX "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
+ printk(KERN_WARNING PFX
+ "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
else
- shost_printk(KERN_WARNING, shost,
- PFX "SRP LOGIN REJECTED, reason 0x%08x\n", reason);
+ printk(KERN_WARNING PFX
+ "SRP LOGIN REJECTED, reason 0x%08x\n", reason);
} else
- shost_printk(KERN_WARNING, shost,
- " REJ reason: IB_CM_REJ_CONSUMER_DEFINED,"
- " opcode 0x%02x\n", opcode);
+ printk(KERN_WARNING " REJ reason: IB_CM_REJ_CONSUMER_DEFINED,"
+ " opcode 0x%02x\n", opcode);
target->status = -ECONNRESET;
break;
default:
- shost_printk(KERN_WARNING, shost, " REJ reason 0x%x\n",
- event->param.rej_rcvd.reason);
+ printk(KERN_WARNING " REJ reason 0x%x\n",
+ event->param.rej_rcvd.reason);
target->status = -ECONNRESET;
}
}
@@ -1188,8 +1166,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
switch (event->event) {
case IB_CM_REQ_ERROR:
- shost_printk(KERN_DEBUG, target->scsi_host,
- PFX "Sending CM REQ failed\n");
+ printk(KERN_DEBUG PFX "Sending CM REQ failed\n");
comp = 1;
target->status = -ECONNRESET;
break;
@@ -1207,8 +1184,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
target->scsi_host->can_queue = min(target->req_lim,
target->scsi_host->can_queue);
} else {
- shost_printk(KERN_WARNING, target->scsi_host,
- PFX "Unhandled RSP opcode %#x\n", opcode);
+ printk(KERN_WARNING PFX "Unhandled RSP opcode %#x\n", opcode);
target->status = -ECONNRESET;
break;
}
@@ -1254,23 +1230,20 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
break;
case IB_CM_REJ_RECEIVED:
- shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
+ printk(KERN_DEBUG PFX "REJ received\n");
comp = 1;
srp_cm_rej_handler(cm_id, event, target);
break;
case IB_CM_DREQ_RECEIVED:
- shost_printk(KERN_WARNING, target->scsi_host,
- PFX "DREQ received - connection closed\n");
+ printk(KERN_WARNING PFX "DREQ received - connection closed\n");
if (ib_send_cm_drep(cm_id, NULL, 0))
- shost_printk(KERN_ERR, target->scsi_host,
- PFX "Sending CM DREP failed\n");
+ printk(KERN_ERR PFX "Sending CM DREP failed\n");
break;
case IB_CM_TIMEWAIT_EXIT:
- shost_printk(KERN_ERR, target->scsi_host,
- PFX "connection closed\n");
+ printk(KERN_ERR PFX "connection closed\n");
comp = 1;
target->status = 0;
@@ -1282,8 +1255,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
break;
default:
- shost_printk(KERN_WARNING, target->scsi_host,
- PFX "Unhandled CM event %d\n", event->event);
+ printk(KERN_WARNING PFX "Unhandled CM event %d\n", event->event);
break;
}
@@ -1311,7 +1283,7 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
init_completion(&req->done);
- iu = __srp_get_tx_iu(target, SRP_REQ_TASK_MGMT);
+ iu = __srp_get_tx_iu(target);
if (!iu)
goto out;
@@ -1360,7 +1332,7 @@ static int srp_abort(struct scsi_cmnd *scmnd)
struct srp_request *req;
int ret = SUCCESS;
- shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
+ printk(KERN_ERR "SRP abort called\n");
if (target->qp_in_error)
return FAILED;
@@ -1390,7 +1362,7 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
struct srp_target_port *target = host_to_target(scmnd->device->host);
struct srp_request *req, *tmp;
- shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
+ printk(KERN_ERR "SRP reset_device called\n");
if (target->qp_in_error)
return FAILED;
@@ -1417,7 +1389,7 @@ static int srp_reset_host(struct scsi_cmnd *scmnd)
struct srp_target_port *target = host_to_target(scmnd->device->host);
int ret = FAILED;
- shost_printk(KERN_ERR, target->scsi_host, PFX "SRP reset_host called\n");
+ printk(KERN_ERR PFX "SRP reset_host called\n");
if (!srp_reconnect_target(target))
ret = SUCCESS;
@@ -1571,7 +1543,6 @@ static struct scsi_host_template srp_template = {
.this_id = -1,
.cmd_per_lun = SRP_SQ_SIZE,
.use_clustering = ENABLE_CLUSTERING,
- .use_sg_chaining = ENABLE_SG_CHAINING,
.shost_attrs = srp_host_attrs
};
@@ -1843,9 +1814,8 @@ static ssize_t srp_create_target(struct class_device *class_dev,
ib_get_cached_gid(host->dev->dev, host->port, 0, &target->path.sgid);
- shost_printk(KERN_DEBUG, target->scsi_host, PFX
- "new target: id_ext %016llx ioc_guid %016llx pkey %04x "
- "service_id %016llx dgid %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ printk(KERN_DEBUG PFX "new target: id_ext %016llx ioc_guid %016llx pkey %04x "
+ "service_id %016llx dgid %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
(unsigned long long) be64_to_cpu(target->id_ext),
(unsigned long long) be64_to_cpu(target->ioc_guid),
be16_to_cpu(target->path.pkey),
@@ -1872,8 +1842,7 @@ static ssize_t srp_create_target(struct class_device *class_dev,
target->qp_in_error = 0;
ret = srp_connect_target(target);
if (ret) {
- shost_printk(KERN_ERR, target->scsi_host,
- PFX "Connection failed\n");
+ printk(KERN_ERR PFX "Connection failed\n");
goto err_cm_id;
}
diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.h b/trunk/drivers/infiniband/ulp/srp/ib_srp.h
index 4a3c1f37e4c2..e3573e7038c4 100644
--- a/trunk/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.h
@@ -79,11 +79,6 @@ enum srp_target_state {
SRP_TARGET_REMOVED
};
-enum srp_request_type {
- SRP_REQ_NORMAL,
- SRP_REQ_TASK_MGMT,
-};
-
struct srp_device {
struct list_head dev_list;
struct ib_device *dev;
diff --git a/trunk/drivers/lguest/x86/core.c b/trunk/drivers/lguest/x86/core.c
index 96d0fd07c57d..482aec2a9631 100644
--- a/trunk/drivers/lguest/x86/core.c
+++ b/trunk/drivers/lguest/x86/core.c
@@ -459,7 +459,7 @@ void __init lguest_arch_host_init(void)
/* We don't need the complexity of CPUs coming and going while we're
* doing this. */
- get_online_cpus();
+ lock_cpu_hotplug();
if (cpu_has_pge) { /* We have a broader idea of "global". */
/* Remember that this was originally set (for cleanup). */
cpu_had_pge = 1;
@@ -469,20 +469,20 @@ void __init lguest_arch_host_init(void)
/* Turn off the feature in the global feature set. */
clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
}
- put_online_cpus();
+ unlock_cpu_hotplug();
};
/*:*/
void __exit lguest_arch_host_fini(void)
{
/* If we had PGE before we started, turn it back on now. */
- get_online_cpus();
+ lock_cpu_hotplug();
if (cpu_had_pge) {
set_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
/* adjust_pge's argument "1" means set PGE. */
on_each_cpu(adjust_pge, (void *)1, 0, 1);
}
- put_online_cpus();
+ unlock_cpu_hotplug();
}
diff --git a/trunk/drivers/media/Kconfig b/trunk/drivers/media/Kconfig
index 8f4a45346de7..1604f0490404 100644
--- a/trunk/drivers/media/Kconfig
+++ b/trunk/drivers/media/Kconfig
@@ -69,13 +69,11 @@ source "drivers/media/common/Kconfig"
config VIDEO_TUNER
tristate
depends on I2C
- select TUNER_XC2028 if !VIDEO_TUNER_CUSTOMIZE
select TUNER_MT20XX if !VIDEO_TUNER_CUSTOMIZE
select TUNER_TDA8290 if !VIDEO_TUNER_CUSTOMIZE
select TUNER_TEA5761 if !VIDEO_TUNER_CUSTOMIZE
select TUNER_TEA5767 if !VIDEO_TUNER_CUSTOMIZE
select TUNER_SIMPLE if !VIDEO_TUNER_CUSTOMIZE
- select TUNER_TDA9887 if !VIDEO_TUNER_CUSTOMIZE
menuconfig VIDEO_TUNER_CUSTOMIZE
bool "Customize analog tuner modules to build"
@@ -91,13 +89,6 @@ menuconfig VIDEO_TUNER_CUSTOMIZE
if VIDEO_TUNER_CUSTOMIZE
-config TUNER_XC2028
- tristate "XCeive xc2028/xc3028 tuners"
- depends on I2C
- default m if VIDEO_TUNER_CUSTOMIZE
- help
- Say Y here to include support for the xc2028/xc3028 tuners.
-
config TUNER_MT20XX
tristate "Microtune 2032 / 2050 tuners"
depends on I2C
@@ -106,10 +97,8 @@ config TUNER_MT20XX
Say Y here to include support for the MT2032 / MT2050 tuner.
config TUNER_TDA8290
- tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo"
+ tristate "TDA 8290+8275(a) tuner combo"
depends on I2C
- select DVB_TDA827X
- select DVB_TDA18271
default m if VIDEO_TUNER_CUSTOMIZE
help
Say Y here to include support for Philips TDA8290+8275(a) tuner.
@@ -131,19 +120,10 @@ config TUNER_TEA5767
config TUNER_SIMPLE
tristate "Simple tuner support"
depends on I2C
- select TUNER_TDA9887
default m if VIDEO_TUNER_CUSTOMIZE
help
Say Y here to include support for various simple tuners.
-config TUNER_TDA9887
- tristate "TDA 9885/6/7 analog IF demodulator"
- depends on I2C
- default m if VIDEO_TUNER_CUSTOMIZE
- help
- Say Y here to include support for Philips TDA9885/6/7
- analog IF demodulator.
-
endif # VIDEO_TUNER_CUSTOMIZE
config VIDEOBUF_GEN
diff --git a/trunk/drivers/media/common/Kconfig b/trunk/drivers/media/common/Kconfig
index 06ca75911b7f..c5092ef1082f 100644
--- a/trunk/drivers/media/common/Kconfig
+++ b/trunk/drivers/media/common/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_SAA7146
tristate
- depends on I2C && PCI
+ depends on I2C
config VIDEO_SAA7146_VV
tristate
diff --git a/trunk/drivers/media/common/ir-functions.c b/trunk/drivers/media/common/ir-functions.c
index bb2a027b9483..e7c3ab951a44 100644
--- a/trunk/drivers/media/common/ir-functions.c
+++ b/trunk/drivers/media/common/ir-functions.c
@@ -258,7 +258,7 @@ int ir_decode_biphase(u32 *samples, int count, int low, int high)
* saa7134 */
/* decode raw bit pattern to RC5 code */
-static u32 ir_rc5_decode(unsigned int code)
+u32 ir_rc5_decode(unsigned int code)
{
unsigned int org_code = code;
unsigned int pair;
@@ -371,6 +371,7 @@ EXPORT_SYMBOL_GPL(ir_dump_samples);
EXPORT_SYMBOL_GPL(ir_decode_biphase);
EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
+EXPORT_SYMBOL_GPL(ir_rc5_decode);
EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup);
diff --git a/trunk/drivers/media/common/ir-keymaps.c b/trunk/drivers/media/common/ir-keymaps.c
index a4a937c90534..185e8a860c1a 100644
--- a/trunk/drivers/media/common/ir-keymaps.c
+++ b/trunk/drivers/media/common/ir-keymaps.c
@@ -1331,12 +1331,7 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
[ 0x35 ] = KEY_FASTFORWARD,
[ 0x36 ] = KEY_TV,
[ 0x37 ] = KEY_RADIO, /* FM */
- [ 0x38 ] = KEY_DVD,
-
- [ 0x3e ] = KEY_F21, /* MCE +VOL, on Y04G0033 */
- [ 0x3a ] = KEY_F22, /* MCE -VOL, on Y04G0033 */
- [ 0x3b ] = KEY_F23, /* MCE +CH, on Y04G0033 */
- [ 0x3f ] = KEY_F24 /* MCE -CH, on Y04G0033 */
+ [ 0x38 ] = KEY_DVD
};
EXPORT_SYMBOL_GPL(ir_codes_winfast);
@@ -1848,142 +1843,3 @@ IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = {
};
EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce);
-
-/* Pinnacle PCTV HD 800i mini remote */
-IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE] = {
-
- [0x0f] = KEY_1,
- [0x15] = KEY_2,
- [0x10] = KEY_3,
- [0x18] = KEY_4,
- [0x1b] = KEY_5,
- [0x1e] = KEY_6,
- [0x11] = KEY_7,
- [0x21] = KEY_8,
- [0x12] = KEY_9,
- [0x27] = KEY_0,
-
- [0x24] = KEY_ZOOM,
- [0x2a] = KEY_SUBTITLE,
-
- [0x00] = KEY_MUTE,
- [0x01] = KEY_ENTER, /* Pinnacle Logo */
- [0x39] = KEY_POWER,
-
- [0x03] = KEY_VOLUMEUP,
- [0x09] = KEY_VOLUMEDOWN,
- [0x06] = KEY_CHANNELUP,
- [0x0c] = KEY_CHANNELDOWN,
-
- [0x2d] = KEY_REWIND,
- [0x30] = KEY_PLAYPAUSE,
- [0x33] = KEY_FASTFORWARD,
- [0x3c] = KEY_STOP,
- [0x36] = KEY_RECORD,
- [0x3f] = KEY_EPG, /* Labeled "?" */
-};
-EXPORT_SYMBOL_GPL(ir_codes_pinnacle_pctv_hd);
-
-/*
- * Igor Kuznetsov
- * Andrey J. Melnikov
- *
- * Keytable is used by BeholdTV 60x series, M6 series at
- * least, and probably other cards too.
- * The "ascii-art picture" below (in comments, first row
- * is the keycode in hex, and subsequent row(s) shows
- * the button labels (several variants when appropriate)
- * helps to descide which keycodes to assign to the buttons.
- */
-IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = {
-
- /* 0x1c 0x12 *
- * TV/FM POWER *
- * */
- [ 0x1c ] = KEY_TUNER, /*XXX KEY_TV KEY_RADIO */
- [ 0x12 ] = KEY_POWER,
-
- /* 0x01 0x02 0x03 *
- * 1 2 3 *
- * *
- * 0x04 0x05 0x06 *
- * 4 5 6 *
- * *
- * 0x07 0x08 0x09 *
- * 7 8 9 *
- * */
- [ 0x01 ] = KEY_1,
- [ 0x02 ] = KEY_2,
- [ 0x03 ] = KEY_3,
- [ 0x04 ] = KEY_4,
- [ 0x05 ] = KEY_5,
- [ 0x06 ] = KEY_6,
- [ 0x07 ] = KEY_7,
- [ 0x08 ] = KEY_8,
- [ 0x09 ] = KEY_9,
-
- /* 0x0a 0x00 0x17 *
- * RECALL 0 MODE *
- * */
- [ 0x0a ] = KEY_AGAIN,
- [ 0x00 ] = KEY_0,
- [ 0x17 ] = KEY_MODE,
-
- /* 0x14 0x10 *
- * ASPECT FULLSCREEN *
- * */
- [ 0x14 ] = KEY_SCREEN,
- [ 0x10 ] = KEY_ZOOM,
-
- /* 0x0b *
- * Up *
- * *
- * 0x18 0x16 0x0c *
- * Left Ok Right *
- * *
- * 0x015 *
- * Down *
- * */
- [ 0x0b ] = KEY_CHANNELUP, /*XXX KEY_UP */
- [ 0x18 ] = KEY_VOLUMEDOWN, /*XXX KEY_LEFT */
- [ 0x16 ] = KEY_OK, /*XXX KEY_ENTER */
- [ 0x0c ] = KEY_VOLUMEUP, /*XXX KEY_RIGHT */
- [ 0x15 ] = KEY_CHANNELDOWN, /*XXX KEY_DOWN */
-
- /* 0x11 0x0d *
- * MUTE INFO *
- * */
- [ 0x11 ] = KEY_MUTE,
- [ 0x0d ] = KEY_INFO,
-
- /* 0x0f 0x1b 0x1a *
- * RECORD PLAY/PAUSE STOP *
- * *
- * 0x0e 0x1f 0x1e *
- *TELETEXT AUDIO SOURCE *
- * RED YELLOW *
- * */
- [ 0x0f ] = KEY_RECORD,
- [ 0x1b ] = KEY_PLAYPAUSE,
- [ 0x1a ] = KEY_STOP,
- [ 0x0e ] = KEY_TEXT,
- [ 0x1f ] = KEY_RED, /*XXX KEY_AUDIO */
- [ 0x1e ] = KEY_YELLOW, /*XXX KEY_SOURCE */
-
- /* 0x1d 0x13 0x19 *
- * SLEEP PREVIEW DVB *
- * GREEN BLUE *
- * */
- [ 0x1d ] = KEY_SLEEP,
- [ 0x13 ] = KEY_GREEN,
- [ 0x19 ] = KEY_BLUE, /*XXX KEY_SAT */
-
- /* 0x58 0x5c *
- * FREEZE SNAPSHOT *
- * */
- [ 0x58 ] = KEY_SLOW,
- [ 0x5c ] = KEY_SAVE,
-
-};
-
-EXPORT_SYMBOL_GPL(ir_codes_behold);
diff --git a/trunk/drivers/media/common/saa7146_fops.c b/trunk/drivers/media/common/saa7146_fops.c
index f0703d8bc3e8..67d1b1b1b254 100644
--- a/trunk/drivers/media/common/saa7146_fops.c
+++ b/trunk/drivers/media/common/saa7146_fops.c
@@ -61,7 +61,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
videobuf_waiton(&buf->vb,0,0);
videobuf_dma_unmap(q, dma);
videobuf_dma_free(dma);
- buf->vb.state = VIDEOBUF_NEEDS_INIT;
+ buf->vb.state = STATE_NEEDS_INIT;
}
@@ -83,7 +83,7 @@ int saa7146_buffer_queue(struct saa7146_dev *dev,
buf->activate(dev,buf,NULL);
} else {
list_add_tail(&buf->vb.queue,&q->queue);
- buf->vb.state = VIDEOBUF_QUEUED;
+ buf->vb.state = STATE_QUEUED;
DEB_D(("adding buffer %p to queue. (active buffer present)\n", buf));
}
return 0;
@@ -174,7 +174,7 @@ void saa7146_buffer_timeout(unsigned long data)
spin_lock_irqsave(&dev->slock,flags);
if (q->curr) {
DEB_D(("timeout on %p\n", q->curr));
- saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR);
+ saa7146_buffer_finish(dev,q,STATE_ERROR);
}
/* we don't restart the transfer here like other drivers do. when
@@ -366,7 +366,7 @@ static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
}
poll_wait(file, &buf->done, wait);
- if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) {
+ if (buf->state == STATE_DONE || buf->state == STATE_ERROR) {
DEB_D(("poll succeeded!\n"));
return POLLIN|POLLRDNORM;
}
@@ -538,7 +538,6 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
// fixme: -1 should be an insmod parameter *for the extension* (like "video_nr");
if (video_register_device(vfd, type, -1) < 0) {
ERR(("cannot register v4l2 device. skipping.\n"));
- video_device_release(vfd);
return -1;
}
diff --git a/trunk/drivers/media/common/saa7146_vbi.c b/trunk/drivers/media/common/saa7146_vbi.c
index c32dda973e92..6103484e4442 100644
--- a/trunk/drivers/media/common/saa7146_vbi.c
+++ b/trunk/drivers/media/common/saa7146_vbi.c
@@ -205,7 +205,7 @@ static int buffer_activate(struct saa7146_dev *dev,
struct saa7146_buf *next)
{
struct saa7146_vv *vv = dev->vv_data;
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
DEB_VBI(("dev:%p, buf:%p, next:%p\n",dev,buf,next));
saa7146_set_vbi_capture(dev,buf,next);
@@ -238,7 +238,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
if (buf->vb.size != size)
saa7146_dma_free(dev,q,buf);
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ if (STATE_NEEDS_INIT == buf->vb.state) {
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
buf->vb.width = llength;
@@ -257,7 +257,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
if (0 != err)
return err;
}
- buf->vb.state = VIDEOBUF_PREPARED;
+ buf->vb.state = STATE_PREPARED;
buf->activate = buffer_activate;
return 0;
@@ -335,7 +335,7 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file)
saa7146_write(dev, MC1, MASK_20);
if (vv->vbi_q.curr) {
- saa7146_buffer_finish(dev,&vv->vbi_q,VIDEOBUF_DONE);
+ saa7146_buffer_finish(dev,&vv->vbi_q,STATE_DONE);
}
videobuf_queue_cancel(&fh->vbi_q);
@@ -458,7 +458,7 @@ static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
/* this must be += 2, one count for each field */
vv->vbi_fieldcount+=2;
vv->vbi_q.curr->vb.field_count = vv->vbi_fieldcount;
- saa7146_buffer_finish(dev,&vv->vbi_q,VIDEOBUF_DONE);
+ saa7146_buffer_finish(dev,&vv->vbi_q,STATE_DONE);
} else {
DEB_VBI(("dev:%p\n",dev));
}
diff --git a/trunk/drivers/media/common/saa7146_video.c b/trunk/drivers/media/common/saa7146_video.c
index c31ab480d8e1..ae36d101006b 100644
--- a/trunk/drivers/media/common/saa7146_video.c
+++ b/trunk/drivers/media/common/saa7146_video.c
@@ -1235,7 +1235,7 @@ static int buffer_activate (struct saa7146_dev *dev,
{
struct saa7146_vv *vv = dev->vv_data;
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
saa7146_set_capture(dev,buf,next);
mod_timer(&vv->video_q.timeout, jiffies+BUFFER_TIMEOUT);
@@ -1281,7 +1281,7 @@ static int buffer_prepare(struct videobuf_queue *q,
saa7146_dma_free(dev,q,buf);
}
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ if (STATE_NEEDS_INIT == buf->vb.state) {
struct saa7146_format *sfmt;
buf->vb.bytesperline = fh->video_fmt.bytesperline;
@@ -1314,7 +1314,7 @@ static int buffer_prepare(struct videobuf_queue *q,
if (err)
goto oops;
}
- buf->vb.state = VIDEOBUF_PREPARED;
+ buf->vb.state = STATE_PREPARED;
buf->activate = buffer_activate;
return 0;
@@ -1453,7 +1453,7 @@ static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
/* only finish the buffer if we have one... */
if( NULL != q->curr ) {
- saa7146_buffer_finish(dev,q,VIDEOBUF_DONE);
+ saa7146_buffer_finish(dev,q,STATE_DONE);
}
saa7146_buffer_next(dev,q,0);
diff --git a/trunk/drivers/media/dvb/b2c2/flexcop.c b/trunk/drivers/media/dvb/b2c2/flexcop.c
index 2ddafd071c97..29ec4183118e 100644
--- a/trunk/drivers/media/dvb/b2c2/flexcop.c
+++ b/trunk/drivers/media/dvb/b2c2/flexcop.c
@@ -212,6 +212,7 @@ void flexcop_reset_block_300(struct flexcop_device *fc)
fc->write_ibi_reg(fc,ctrl_208,v208_save);
}
+EXPORT_SYMBOL(flexcop_reset_block_300);
struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len)
{
diff --git a/trunk/drivers/media/dvb/bt8xx/bt878.c b/trunk/drivers/media/dvb/bt8xx/bt878.c
index c7bbb40223f5..85e36a1d6d78 100644
--- a/trunk/drivers/media/dvb/bt8xx/bt878.c
+++ b/trunk/drivers/media/dvb/bt8xx/bt878.c
@@ -378,37 +378,23 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *
EXPORT_SYMBOL(bt878_device_control);
-#define BROOKTREE_878_DEVICE(vend, dev, name) \
- { \
- .vendor = PCI_VENDOR_ID_BROOKTREE, \
- .device = PCI_DEVICE_ID_BROOKTREE_878, \
- .subvendor = (vend), .subdevice = (dev), \
- .driver_data = (unsigned long) name \
- }
-static struct pci_device_id bt878_pci_tbl[] __devinitdata = {
- BROOKTREE_878_DEVICE(0x0071, 0x0101, "Nebula Electronics DigiTV"),
- BROOKTREE_878_DEVICE(0x1461, 0x0761, "AverMedia AverTV DVB-T 761"),
- BROOKTREE_878_DEVICE(0x11bd, 0x001c, "Pinnacle PCTV Sat"),
- BROOKTREE_878_DEVICE(0x11bd, 0x0026, "Pinnacle PCTV SAT CI"),
- BROOKTREE_878_DEVICE(0x1822, 0x0001, "Twinhan VisionPlus DVB"),
- BROOKTREE_878_DEVICE(0x270f, 0xfc00,
- "ChainTech digitop DST-1000 DVB-S"),
- BROOKTREE_878_DEVICE(0x1461, 0x0771, "AVermedia AverTV DVB-T 771"),
- BROOKTREE_878_DEVICE(0x18ac, 0xdb10, "DViCO FusionHDTV DVB-T Lite"),
- BROOKTREE_878_DEVICE(0x18ac, 0xdb11, "Ultraview DVB-T Lite"),
- BROOKTREE_878_DEVICE(0x18ac, 0xd500, "DViCO FusionHDTV 5 Lite"),
- BROOKTREE_878_DEVICE(0x7063, 0x2000, "pcHDTV HD-2000 TV"),
- BROOKTREE_878_DEVICE(0x1822, 0x0026, "DNTV Live! Mini"),
- { }
+static struct cards card_list[] __devinitdata = {
+
+ { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
+ { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" },
+ { 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" },
+ { 0x002611bd, BTTV_BOARD_TWINHAN_DST, "Pinnacle PCTV SAT CI" },
+ { 0x00011822, BTTV_BOARD_TWINHAN_DST, "Twinhan VisionPlus DVB" },
+ { 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" },
+ { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" },
+ { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" },
+ { 0xdb1118ac, BTTV_BOARD_DVICO_DVBT_LITE, "Ultraview DVB-T Lite" },
+ { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" },
+ { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV" },
+ { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini" }
};
-MODULE_DEVICE_TABLE(pci, bt878_pci_tbl);
-
-static const char * __devinit card_name(const struct pci_device_id *id)
-{
- return id->driver_data ? (const char *)id->driver_data : "Unknown";
-}
/***********************/
/* PCI device handling */
@@ -417,13 +403,15 @@ static const char * __devinit card_name(const struct pci_device_id *id)
static int __devinit bt878_probe(struct pci_dev *dev,
const struct pci_device_id *pci_id)
{
- int result = 0;
+ int result = 0, has_dvb = 0, i;
unsigned char lat;
struct bt878 *bt;
#if defined(__powerpc__)
unsigned int cmd;
#endif
unsigned int cardid;
+ unsigned short id;
+ struct cards *dvb_cards;
printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
bt878_num);
@@ -435,11 +423,25 @@ static int __devinit bt878_probe(struct pci_dev *dev,
if (pci_enable_device(dev))
return -EIO;
- cardid = dev->subsystem_device << 16;
- cardid |= dev->subsystem_vendor;
+ pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &id);
+ cardid = id << 16;
+ pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &id);
+ cardid |= id;
+
+ for (i = 0, dvb_cards = card_list; i < ARRAY_SIZE(card_list); i++, dvb_cards++) {
+ if (cardid == dvb_cards->pci_id) {
+ printk("%s: card id=[0x%x],[ %s ] has DVB functions.\n",
+ __func__, cardid, dvb_cards->name);
+ has_dvb = 1;
+ }
+ }
- printk(KERN_INFO "%s: card id=[0x%x],[ %s ] has DVB functions.\n",
- __func__, cardid, card_name(pci_id));
+ if (!has_dvb) {
+ printk("%s: card id=[0x%x], Unknown card.\nExiting..\n", __func__, cardid);
+ result = -EINVAL;
+
+ goto fail0;
+ }
bt = &bt878[bt878_num];
bt->dev = dev;
@@ -570,6 +572,14 @@ static void __devexit bt878_remove(struct pci_dev *pci_dev)
return;
}
+static struct pci_device_id bt878_pci_tbl[] __devinitdata = {
+ {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BROOKTREE_878,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, bt878_pci_tbl);
+
static struct pci_driver bt878_pci_driver = {
.name = "bt878",
.id_table = bt878_pci_tbl,
diff --git a/trunk/drivers/media/dvb/bt8xx/bt878.h b/trunk/drivers/media/dvb/bt8xx/bt878.h
index 375fd2892a11..d593bc145628 100644
--- a/trunk/drivers/media/dvb/bt8xx/bt878.h
+++ b/trunk/drivers/media/dvb/bt8xx/bt878.h
@@ -101,6 +101,12 @@
#define BTTV_BOARD_DVICO_DVBT_LITE 0x80
#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87
+struct cards {
+ __u32 pci_id;
+ __u16 card_id;
+ char *name;
+};
+
extern int bt878_num;
struct bt878 {
diff --git a/trunk/drivers/media/dvb/bt8xx/dst.c b/trunk/drivers/media/dvb/bt8xx/dst.c
index 307ff35bdf13..b7a17e69ca4d 100644
--- a/trunk/drivers/media/dvb/bt8xx/dst.c
+++ b/trunk/drivers/media/dvb/bt8xx/dst.c
@@ -71,7 +71,6 @@ MODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)");
} \
} while(0)
-static int dst_command(struct dst_state *state, u8 *data, u8 len);
static void dst_packsize(struct dst_state *state, int psize)
{
@@ -81,8 +80,7 @@ static void dst_packsize(struct dst_state *state, int psize)
bt878_device_control(state->bt, DST_IG_TS, &bits);
}
-static int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb,
- u32 outhigh, int delay)
+int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb, u32 outhigh, int delay)
{
union dst_gpio_packet enb;
union dst_gpio_packet bits;
@@ -111,8 +109,9 @@ static int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb,
return 0;
}
+EXPORT_SYMBOL(dst_gpio_outb);
-static int dst_gpio_inb(struct dst_state *state, u8 *result)
+int dst_gpio_inb(struct dst_state *state, u8 *result)
{
union dst_gpio_packet rd_packet;
int err;
@@ -126,6 +125,7 @@ static int dst_gpio_inb(struct dst_state *state, u8 *result)
return 0;
}
+EXPORT_SYMBOL(dst_gpio_inb);
int rdc_reset_state(struct dst_state *state)
{
@@ -145,7 +145,7 @@ int rdc_reset_state(struct dst_state *state)
}
EXPORT_SYMBOL(rdc_reset_state);
-static int rdc_8820_reset(struct dst_state *state)
+int rdc_8820_reset(struct dst_state *state)
{
dprintk(verbose, DST_DEBUG, 1, "Resetting DST");
if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) {
@@ -160,8 +160,9 @@ static int rdc_8820_reset(struct dst_state *state)
return 0;
}
+EXPORT_SYMBOL(rdc_8820_reset);
-static int dst_pio_enable(struct dst_state *state)
+int dst_pio_enable(struct dst_state *state)
{
if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {
dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
@@ -171,6 +172,7 @@ static int dst_pio_enable(struct dst_state *state)
return 0;
}
+EXPORT_SYMBOL(dst_pio_enable);
int dst_pio_disable(struct dst_state *state)
{
@@ -609,7 +611,7 @@ static int dst_type_print(struct dst_state *state, u8 type)
return 0;
}
-static struct tuner_types tuner_list[] = {
+struct tuner_types tuner_list[] = {
{
.tuner_type = TUNER_TYPE_L64724,
.tuner_name = "L 64724",
@@ -1222,7 +1224,7 @@ static int dst_probe(struct dst_state *state)
return 0;
}
-static int dst_command(struct dst_state *state, u8 *data, u8 len)
+int dst_command(struct dst_state *state, u8 *data, u8 len)
{
u8 reply;
@@ -1285,6 +1287,7 @@ static int dst_command(struct dst_state *state, u8 *data, u8 len)
return -EIO;
}
+EXPORT_SYMBOL(dst_command);
static int dst_get_signal(struct dst_state *state)
{
diff --git a/trunk/drivers/media/dvb/bt8xx/dst_common.h b/trunk/drivers/media/dvb/bt8xx/dst_common.h
index d88cf2add82b..87623d203a89 100644
--- a/trunk/drivers/media/dvb/bt8xx/dst_common.h
+++ b/trunk/drivers/media/dvb/bt8xx/dst_common.h
@@ -165,8 +165,10 @@ struct dst_config
};
int rdc_reset_state(struct dst_state *state);
+int rdc_8820_reset(struct dst_state *state);
int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode);
+int dst_pio_enable(struct dst_state *state);
int dst_pio_disable(struct dst_state *state);
int dst_error_recovery(struct dst_state* state);
int dst_error_bailout(struct dst_state *state);
@@ -177,6 +179,9 @@ int read_dst(struct dst_state *state, u8 * ret, u8 len);
u8 dst_check_sum(u8 * buf, u32 len);
struct dst_state* dst_attach(struct dst_state* state, struct dvb_adapter *dvb_adapter);
struct dvb_device *dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter);
+int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int delay);
+
+int dst_command(struct dst_state* state, u8 * data, u8 len);
#endif // DST_COMMON_H
diff --git a/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c b/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c
index 925cfa6221ad..445f02665577 100644
--- a/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -1202,10 +1202,6 @@ void dvb_frontend_detach(struct dvb_frontend* fe)
fe->ops.tuner_ops.release(fe);
symbol_put_addr(fe->ops.tuner_ops.release);
}
- if (fe->ops.analog_ops.release) {
- fe->ops.analog_ops.release(fe);
- symbol_put_addr(fe->ops.analog_ops.release);
- }
ptr = (void*)fe->ops.release;
if (ptr) {
fe->ops.release(fe);
@@ -1219,8 +1215,6 @@ void dvb_frontend_detach(struct dvb_frontend* fe)
fe->ops.release_sec(fe);
if (fe->ops.tuner_ops.release)
fe->ops.tuner_ops.release(fe);
- if (fe->ops.analog_ops.release)
- fe->ops.analog_ops.release(fe);
if (fe->ops.release)
fe->ops.release(fe);
}
diff --git a/trunk/drivers/media/dvb/dvb-core/dvb_frontend.h b/trunk/drivers/media/dvb/dvb-core/dvb_frontend.h
index aa4133f0bd19..a5262e852c82 100644
--- a/trunk/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/trunk/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -84,9 +84,6 @@ struct dvb_tuner_ops {
/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
- /** This is to allow setting tuner-specific configs */
- int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
-
int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
@@ -101,28 +98,6 @@ struct dvb_tuner_ops {
int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
};
-struct analog_demod_info {
- char *name;
-};
-
-struct analog_demod_ops {
-
- struct analog_demod_info info;
-
- void (*set_params)(struct dvb_frontend *fe,
- struct analog_parameters *params);
- int (*has_signal)(struct dvb_frontend *fe);
- int (*is_stereo)(struct dvb_frontend *fe);
- int (*get_afc)(struct dvb_frontend *fe);
- void (*tuner_status)(struct dvb_frontend *fe);
- void (*standby)(struct dvb_frontend *fe);
- void (*release)(struct dvb_frontend *fe);
- int (*i2c_gate_ctrl)(struct dvb_frontend *fe, int enable);
-
- /** This is to allow setting tuner-specific configuration */
- int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
-};
-
struct dvb_frontend_ops {
struct dvb_frontend_info info;
@@ -168,7 +143,6 @@ struct dvb_frontend_ops {
int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
struct dvb_tuner_ops tuner_ops;
- struct analog_demod_ops analog_ops;
};
#define MAX_EVENT 8
@@ -185,19 +159,18 @@ struct dvb_fe_events {
struct dvb_frontend {
struct dvb_frontend_ops ops;
struct dvb_adapter *dvb;
- void *demodulator_priv;
- void *tuner_priv;
- void *frontend_priv;
- void *sec_priv;
- void *analog_demod_priv;
+ void* demodulator_priv;
+ void* tuner_priv;
+ void* frontend_priv;
+ void* sec_priv;
};
-extern int dvb_register_frontend(struct dvb_adapter *dvb,
- struct dvb_frontend *fe);
+extern int dvb_register_frontend(struct dvb_adapter* dvb,
+ struct dvb_frontend* fe);
-extern int dvb_unregister_frontend(struct dvb_frontend *fe);
+extern int dvb_unregister_frontend(struct dvb_frontend* fe);
-extern void dvb_frontend_detach(struct dvb_frontend *fe);
+extern void dvb_frontend_detach(struct dvb_frontend* fe);
extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
diff --git a/trunk/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/trunk/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
index ac9d93cf83c6..9878183ba3f0 100644
--- a/trunk/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+++ b/trunk/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -261,6 +261,11 @@ EXPORT_SYMBOL(dvb_ringbuffer_init);
EXPORT_SYMBOL(dvb_ringbuffer_empty);
EXPORT_SYMBOL(dvb_ringbuffer_free);
EXPORT_SYMBOL(dvb_ringbuffer_avail);
+EXPORT_SYMBOL(dvb_ringbuffer_flush);
EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
EXPORT_SYMBOL(dvb_ringbuffer_read);
EXPORT_SYMBOL(dvb_ringbuffer_write);
+EXPORT_SYMBOL(dvb_ringbuffer_pkt_write);
+EXPORT_SYMBOL(dvb_ringbuffer_pkt_read);
+EXPORT_SYMBOL(dvb_ringbuffer_pkt_dispose);
+EXPORT_SYMBOL(dvb_ringbuffer_pkt_next);
diff --git a/trunk/drivers/media/dvb/dvb-usb/af9005.c b/trunk/drivers/media/dvb/dvb-usb/af9005.c
index e7f76f515b4f..7db6eee50e39 100644
--- a/trunk/drivers/media/dvb/dvb-usb/af9005.c
+++ b/trunk/drivers/media/dvb/dvb-usb/af9005.c
@@ -1026,7 +1026,6 @@ static int af9005_usb_probe(struct usb_interface *intf,
static struct usb_device_id af9005_usb_table[] = {
{USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9005)},
{USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE)},
- {USB_DEVICE(USB_VID_ANSONIC, USB_PID_ANSONIC_DVBT_USB)},
{0},
};
@@ -1076,7 +1075,7 @@ static struct dvb_usb_device_properties af9005_properties = {
.rc_key_map_size = 0,
.rc_query = af9005_rc_query,
- .num_device_descs = 3,
+ .num_device_descs = 2,
.devices = {
{.name = "Afatech DVB-T USB1.1 stick",
.cold_ids = {&af9005_usb_table[0], NULL},
@@ -1086,10 +1085,6 @@ static struct dvb_usb_device_properties af9005_properties = {
.cold_ids = {&af9005_usb_table[1], NULL},
.warm_ids = {NULL},
},
- {.name = "Ansonic DVB-T USB1.1 stick",
- .cold_ids = {&af9005_usb_table[2], NULL},
- .warm_ids = {NULL},
- },
{NULL},
}
};
diff --git a/trunk/drivers/media/dvb/dvb-usb/au6610.c b/trunk/drivers/media/dvb/dvb-usb/au6610.c
index f3ff81314696..18e0b16fb2a9 100644
--- a/trunk/drivers/media/dvb/dvb-usb/au6610.c
+++ b/trunk/drivers/media/dvb/dvb-usb/au6610.c
@@ -79,12 +79,12 @@ static int au6610_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i;
- if (num > 2)
- return -EINVAL;
-
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
+ if (num > 2)
+ return -EINVAL;
+
for (i = 0; i < num; i++) {
/* write/read request */
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
diff --git a/trunk/drivers/media/dvb/dvb-usb/cxusb.c b/trunk/drivers/media/dvb/dvb-usb/cxusb.c
index c58365005ac1..04e31cf7d530 100644
--- a/trunk/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/trunk/drivers/media/dvb/dvb-usb/cxusb.c
@@ -15,7 +15,7 @@
*
* Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
* Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org)
- * Copyright (C) 2006, 2007 Chris Pascoe (c.pascoe@itee.uq.edu.au)
+ * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -30,16 +30,11 @@
#include "mt352.h"
#include "mt352_priv.h"
#include "zl10353.h"
-#include "tuner-xc2028.h"
-#include "tuner-xc2028-types.h"
/* debug */
-static int dvb_usb_cxusb_debug;
+int dvb_usb_cxusb_debug;
module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
-#define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args)
-#define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \
- dprintk(dvb_usb_cxusb_debug,0x01,args)
static int cxusb_ctrl_msg(struct dvb_usb_device *d,
u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
@@ -51,9 +46,11 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d,
sndbuf[0] = cmd;
memcpy(&sndbuf[1], wbuf, wlen);
if (wo)
- return dvb_usb_generic_write(d, sndbuf, 1+wlen);
+ dvb_usb_generic_write(d, sndbuf, 1+wlen);
else
- return dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
+ dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
+
+ return 0;
}
/* GPIO */
@@ -75,34 +72,6 @@ static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
st->gpio_write_state[GPIO_TUNER] = onoff;
}
-static int cxusb_bluebird_gpio_rw(struct dvb_usb_device *d, u8 changemask,
- u8 newval)
-{
- u8 o[2], gpio_state;
- int rc;
-
- o[0] = 0xff & ~changemask; /* mask of bits to keep */
- o[1] = newval & changemask; /* new values for bits */
-
- rc = cxusb_ctrl_msg(d, CMD_BLUEBIRD_GPIO_RW, o, 2, &gpio_state, 1);
- if (rc < 0 || (gpio_state & changemask) != (newval & changemask))
- deb_info("bluebird_gpio_write failed.\n");
-
- return rc < 0 ? rc : gpio_state;
-}
-
-static void cxusb_bluebird_gpio_pulse(struct dvb_usb_device *d, u8 pin, int low)
-{
- cxusb_bluebird_gpio_rw(d, pin, low ? 0 : pin);
- msleep(5);
- cxusb_bluebird_gpio_rw(d, pin, low ? pin : 0);
-}
-
-static void cxusb_nano2_led(struct dvb_usb_device *d, int onoff)
-{
- cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40);
-}
-
/* I2C */
static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
@@ -113,6 +82,9 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
+ if (num > 2)
+ warn("more than two i2c messages at a time is not handled yet. TODO.");
+
for (i = 0; i < num; i++) {
if (d->udev->descriptor.idVendor == USB_VID_MEDION)
@@ -125,22 +97,8 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
break;
}
- if (msg[i].flags & I2C_M_RD) {
- /* read only */
- u8 obuf[3], ibuf[1+msg[i].len];
- obuf[0] = 0;
- obuf[1] = msg[i].len;
- obuf[2] = msg[i].addr;
- if (cxusb_ctrl_msg(d, CMD_I2C_READ,
- obuf, 3,
- ibuf, 1+msg[i].len) < 0) {
- warn("i2c read failed");
- break;
- }
- memcpy(msg[i].buf, &ibuf[1], msg[i].len);
- } else if (i+1 < num && (msg[i+1].flags & I2C_M_RD) &&
- msg[i].addr == msg[i+1].addr) {
- /* write to then read from same address */
+ /* read request */
+ if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
u8 obuf[3+msg[i].len], ibuf[1+msg[i+1].len];
obuf[0] = msg[i].len;
obuf[1] = msg[i+1].len;
@@ -158,8 +116,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len);
i++;
- } else {
- /* write only */
+ } else { /* write */
u8 obuf[2+msg[i].len], ibuf;
obuf[0] = msg[i].addr;
obuf[1] = msg[i].len;
@@ -174,7 +131,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
}
mutex_unlock(&d->i2c_mutex);
- return i == num ? num : -EREMOTEIO;
+ return i;
}
static u32 cxusb_i2c_func(struct i2c_adapter *adapter)
@@ -205,17 +162,6 @@ static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff)
return 0;
}
-static int cxusb_nano2_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
- int rc = 0;
-
- rc = cxusb_power_ctrl(d, onoff);
- if (!onoff)
- cxusb_nano2_led(d, 0);
-
- return rc;
-}
-
static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
u8 buf[2] = { 0x03, 0x00 };
@@ -251,34 +197,6 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
return 0;
}
-static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
- int *state)
-{
- struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
- u8 ircode[4];
- int i;
- struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
- .buf = ircode, .len = 4 };
-
- *event = 0;
- *state = REMOTE_NO_KEY_PRESSED;
-
- if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1)
- return 0;
-
- for (i = 0; i < d->props.rc_key_map_size; i++) {
- if (keymap[i].custom == ircode[1] &&
- keymap[i].data == ircode[2]) {
- *event = keymap[i].event;
- *state = REMOTE_KEY_PRESSED;
-
- return 0;
- }
- }
-
- return 0;
-}
-
static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
{ 0xfe, 0x02, KEY_TV },
{ 0xfe, 0x0e, KEY_MP3 },
@@ -433,20 +351,6 @@ static struct mt352_config cxusb_mt352_config = {
.demod_init = cxusb_mt352_demod_init,
};
-static struct zl10353_config cxusb_zl10353_xc3028_config = {
- .demod_address = 0x0f,
- .if2 = 45600,
- .no_tuner = 1,
- .parallel_ts = 1,
-};
-
-static struct mt352_config cxusb_mt352_xc3028_config = {
- .demod_address = 0x0f,
- .if2 = 4560,
- .no_tuner = 1,
- .demod_init = cxusb_mt352_demod_init,
-};
-
/* Callbacks for DVB USB */
static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
{
@@ -482,51 +386,6 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
return 0;
}
-static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg)
-{
- struct dvb_usb_device *d = ptr;
-
- switch (command) {
- case XC2028_TUNER_RESET:
- deb_info("%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
- cxusb_bluebird_gpio_pulse(d, 0x01, 1);
- break;
- case XC2028_RESET_CLK:
- deb_info("%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
- break;
- default:
- deb_info("%s: unknown command %d, arg %d\n", __FUNCTION__,
- command, arg);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
-{
- struct dvb_frontend *fe;
- struct xc2028_config cfg = {
- .i2c_adap = &adap->dev->i2c_adap,
- .i2c_addr = 0x61,
- .video_dev = adap->dev,
- .callback = dvico_bluebird_xc2028_callback,
- };
- static struct xc2028_ctrl ctl = {
- .fname = "xc3028-dvico-au-01.fw",
- .max_len = 64,
- .scode_table = ZARLINK456,
- };
-
- fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
- if (fe == NULL || fe->ops.tuner_ops.set_config == NULL)
- return -EIO;
-
- fe->ops.tuner_ops.set_config(fe, &ctl);
-
- return 0;
-}
-
static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
{
u8 b;
@@ -588,120 +447,27 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
return -EIO;
}
-static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
-{
- u8 ircode[4];
- int i;
- struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
- .buf = ircode, .len = 4 };
-
- if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
- err("set interface failed");
-
- cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
-
- /* reset the tuner and demodulator */
- cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0);
- cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
- cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
-
- if ((adap->fe = dvb_attach(zl10353_attach,
- &cxusb_zl10353_xc3028_config,
- &adap->dev->i2c_adap)) == NULL)
- return -EIO;
-
- /* try to determine if there is no IR decoder on the I2C bus */
- for (i = 0; adap->dev->props.rc_key_map != NULL && i < 5; i++) {
- msleep(20);
- if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1)
- goto no_IR;
- if (ircode[0] == 0 && ircode[1] == 0)
- continue;
- if (ircode[2] + ircode[3] != 0xff) {
-no_IR:
- adap->dev->props.rc_key_map = NULL;
- info("No IR receiver detected on this device.");
- break;
- }
- }
-
- return 0;
-}
-
-static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
-{
- if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
- err("set interface failed");
-
- cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
-
- /* reset the tuner and demodulator */
- cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0);
- cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
- cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
-
- if ((adap->fe = dvb_attach(zl10353_attach,
- &cxusb_zl10353_xc3028_config,
- &adap->dev->i2c_adap)) != NULL)
- return 0;
-
- if ((adap->fe = dvb_attach(mt352_attach,
- &cxusb_mt352_xc3028_config,
- &adap->dev->i2c_adap)) != NULL)
- return 0;
-
- return -EIO;
-}
-
-/*
- * DViCO has shipped two devices with the same USB ID, but only one of them
- * needs a firmware download. Check the device class details to see if they
- * have non-default values to decide whether the device is actually cold or
- * not, and forget a match if it turns out we selected the wrong device.
- */
-static int bluebird_fx2_identify_state(struct usb_device *udev,
- struct dvb_usb_device_properties *props,
- struct dvb_usb_device_description **desc,
- int *cold)
-{
- int wascold = *cold;
-
- *cold = udev->descriptor.bDeviceClass == 0xff &&
- udev->descriptor.bDeviceSubClass == 0xff &&
- udev->descriptor.bDeviceProtocol == 0xff;
-
- if (*cold && !wascold)
- *desc = NULL;
-
- return 0;
-}
-
/*
* DViCO bluebird firmware needs the "warm" product ID to be patched into the
* firmware file before download.
*/
-static const int dvico_firmware_id_offsets[] = { 6638, 3204 };
+#define BLUEBIRD_01_ID_OFFSET 6638
static int bluebird_patch_dvico_firmware_download(struct usb_device *udev,
const struct firmware *fw)
{
- int pos;
-
- for (pos = 0; pos < ARRAY_SIZE(dvico_firmware_id_offsets); pos++) {
- int idoff = dvico_firmware_id_offsets[pos];
+ if (fw->size < BLUEBIRD_01_ID_OFFSET + 4)
+ return -EINVAL;
- if (fw->size < idoff + 4)
- continue;
+ if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
+ fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
- if (fw->data[idoff] == (USB_VID_DVICO & 0xff) &&
- fw->data[idoff + 1] == USB_VID_DVICO >> 8) {
- fw->data[idoff + 2] =
- le16_to_cpu(udev->descriptor.idProduct) + 1;
- fw->data[idoff + 3] =
- le16_to_cpu(udev->descriptor.idProduct) >> 8;
+ fw->data[BLUEBIRD_01_ID_OFFSET + 2] =
+ le16_to_cpu(udev->descriptor.idProduct) + 1;
+ fw->data[BLUEBIRD_01_ID_OFFSET + 3] =
+ le16_to_cpu(udev->descriptor.idProduct) >> 8;
- return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
- }
+ return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
}
return -EINVAL;
@@ -713,9 +479,6 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties;
static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties;
static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
-static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
-static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties;
-static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties;
static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -724,10 +487,7 @@ static int cxusb_probe(struct usb_interface *intf,
dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&cxusb_bluebird_nano2_needsfirmware_properties,THIS_MODULE,NULL) == 0) {
+ dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0) {
return 0;
}
@@ -748,9 +508,6 @@ static struct usb_device_id cxusb_table [] = {
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -1009,151 +766,6 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
}
};
-static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
- .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
- .usb_ctrl = CYPRESS_FX2,
-
- .size_of_priv = sizeof(struct cxusb_state),
-
- .num_adapters = 1,
- .adapter = {
- {
- .streaming_ctrl = cxusb_streaming_ctrl,
- .frontend_attach = cxusb_dualdig4_frontend_attach,
- .tuner_attach = cxusb_dvico_xc3028_tuner_attach,
- /* parameter for the MPEG2-data transfer */
- .stream = {
- .type = USB_BULK,
- .count = 5,
- .endpoint = 0x02,
- .u = {
- .bulk = {
- .buffersize = 8192,
- }
- }
- },
- },
- },
-
- .power_ctrl = cxusb_power_ctrl,
-
- .i2c_algo = &cxusb_i2c_algo,
-
- .generic_bulk_ctrl_endpoint = 0x01,
-
- .rc_interval = 100,
- .rc_key_map = dvico_mce_rc_keys,
- .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys),
- .rc_query = cxusb_bluebird2_rc_query,
-
- .num_device_descs = 1,
- .devices = {
- { "DViCO FusionHDTV DVB-T Dual Digital 4",
- { NULL },
- { &cxusb_table[13], NULL },
- },
- }
-};
-
-static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
- .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
- .usb_ctrl = CYPRESS_FX2,
- .identify_state = bluebird_fx2_identify_state,
-
- .size_of_priv = sizeof(struct cxusb_state),
-
- .num_adapters = 1,
- .adapter = {
- {
- .streaming_ctrl = cxusb_streaming_ctrl,
- .frontend_attach = cxusb_nano2_frontend_attach,
- .tuner_attach = cxusb_dvico_xc3028_tuner_attach,
- /* parameter for the MPEG2-data transfer */
- .stream = {
- .type = USB_BULK,
- .count = 5,
- .endpoint = 0x02,
- .u = {
- .bulk = {
- .buffersize = 8192,
- }
- }
- },
- },
- },
-
- .power_ctrl = cxusb_nano2_power_ctrl,
-
- .i2c_algo = &cxusb_i2c_algo,
-
- .generic_bulk_ctrl_endpoint = 0x01,
-
- .rc_interval = 100,
- .rc_key_map = dvico_portable_rc_keys,
- .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys),
- .rc_query = cxusb_bluebird2_rc_query,
-
- .num_device_descs = 1,
- .devices = {
- { "DViCO FusionHDTV DVB-T NANO2",
- { NULL },
- { &cxusb_table[14], NULL },
- },
- }
-};
-
-static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties = {
- .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
- .usb_ctrl = DEVICE_SPECIFIC,
- .firmware = "dvb-usb-bluebird-02.fw",
- .download_firmware = bluebird_patch_dvico_firmware_download,
- .identify_state = bluebird_fx2_identify_state,
-
- .size_of_priv = sizeof(struct cxusb_state),
-
- .num_adapters = 1,
- .adapter = {
- {
- .streaming_ctrl = cxusb_streaming_ctrl,
- .frontend_attach = cxusb_nano2_frontend_attach,
- .tuner_attach = cxusb_dvico_xc3028_tuner_attach,
- /* parameter for the MPEG2-data transfer */
- .stream = {
- .type = USB_BULK,
- .count = 5,
- .endpoint = 0x02,
- .u = {
- .bulk = {
- .buffersize = 8192,
- }
- }
- },
- },
- },
-
- .power_ctrl = cxusb_nano2_power_ctrl,
-
- .i2c_algo = &cxusb_i2c_algo,
-
- .generic_bulk_ctrl_endpoint = 0x01,
-
- .rc_interval = 100,
- .rc_key_map = dvico_portable_rc_keys,
- .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys),
- .rc_query = cxusb_rc_query,
-
- .num_device_descs = 1,
- .devices = {
- { "DViCO FusionHDTV DVB-T NANO2 w/o firmware",
- { &cxusb_table[14], NULL },
- { &cxusb_table[15], NULL },
- },
- }
-};
-
static struct usb_driver cxusb_driver = {
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,
diff --git a/trunk/drivers/media/dvb/dvb-usb/cxusb.h b/trunk/drivers/media/dvb/dvb-usb/cxusb.h
index 4768a2c35517..c8ef77554b00 100644
--- a/trunk/drivers/media/dvb/dvb-usb/cxusb.h
+++ b/trunk/drivers/media/dvb/dvb-usb/cxusb.h
@@ -4,9 +4,12 @@
#define DVB_USB_LOG_PREFIX "cxusb"
#include "dvb-usb.h"
-/* usb commands - some of it are guesses, don't have a reference yet */
-#define CMD_BLUEBIRD_GPIO_RW 0x05
+extern int dvb_usb_cxusb_debug;
+#define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args)
+#define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \
+ dprintk(dvb_usb_cxusb_debug,0x01,args)
+/* usb commands - some of it are guesses, don't have a reference yet */
#define CMD_I2C_WRITE 0x08
#define CMD_I2C_READ 0x09
diff --git a/trunk/drivers/media/dvb/dvb-usb/dib0700_core.c b/trunk/drivers/media/dvb/dvb-usb/dib0700_core.c
index c9857d5c6982..3ea294eb96bd 100644
--- a/trunk/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/trunk/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -243,7 +243,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
u8 b[4];
b[0] = REQUEST_ENABLE_VIDEO;
- b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */
+ b[1] = 0x00;
b[2] = (0x01 << 4); /* Master mode */
b[3] = 0x00;
@@ -256,6 +256,9 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
b[2] |= st->channel_state;
+ if (st->channel_state) /* if at least one channel is active */
+ b[1] = (0x01 << 4) | 0x00;
+
deb_info("data for streaming: %x %x\n",b[1],b[2]);
return dib0700_ctrl_wr(adap->dev, b, 4);
diff --git a/trunk/drivers/media/dvb/dvb-usb/dib0700_devices.c b/trunk/drivers/media/dvb/dvb-usb/dib0700_devices.c
index e7093826e975..58452b52002c 100644
--- a/trunk/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/trunk/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -94,28 +94,12 @@ static int bristol_frontend_attach(struct dvb_usb_adapter *adap)
(10 + adap->id) << 1, &bristol_dib3000mc_config[adap->id])) == NULL ? -ENODEV : 0;
}
-static int eeprom_read(struct i2c_adapter *adap,u8 adrs,u8 *pval)
-{
- struct i2c_msg msg[2] = {
- { .addr = 0x50, .flags = 0, .buf = &adrs, .len = 1 },
- { .addr = 0x50, .flags = I2C_M_RD, .buf = pval, .len = 1 },
- };
- if (i2c_transfer(adap, msg, 2) != 2) return -EREMOTEIO;
- return 0;
-}
-
static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
{
- struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap;
+ struct dib0700_state *st = adap->dev->priv;
struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
- s8 a;
- int if1=1220;
- if (adap->dev->udev->descriptor.idVendor == USB_VID_HAUPPAUGE &&
- adap->dev->udev->descriptor.idProduct == USB_PID_HAUPPAUGE_NOVA_T_500_2) {
- if (!eeprom_read(prim_i2c,0x59 + adap->id,&a)) if1=1220+a;
- }
- return dvb_attach(mt2060_attach,adap->fe, tun_i2c,&bristol_mt2060_config[adap->id],
- if1) == NULL ? -ENODEV : 0;
+ return dvb_attach(mt2060_attach,adap->fe, tun_i2c, &bristol_mt2060_config[adap->id],
+ st->mt2060_if1[adap->id]) == NULL ? -ENODEV : 0;
}
/* STK7700D: Pinnacle/Terratec/Hauppauge Dual DVB-T Diversity */
@@ -246,27 +230,6 @@ static struct mt2266_config stk7700d_mt2266_config[2] = {
}
};
-static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
-{
- if (adap->id == 0) {
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
- msleep(10);
- dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
- dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
- dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
- dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
- msleep(10);
- dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
- msleep(10);
- dib7000p_i2c_enumeration(&adap->dev->i2c_adap,1,18,stk7700d_dib7000p_mt2266_config);
- }
-
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
- &stk7700d_dib7000p_mt2266_config[adap->id]);
-
- return adap->fe == NULL ? -ENODEV : 0;
-}
-
static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
{
if (adap->id == 0) {
@@ -452,35 +415,6 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = {
{ 0x1e, 0x38, KEY_YELLOW },
{ 0x1e, 0x3b, KEY_GOTO },
{ 0x1e, 0x3d, KEY_POWER },
-
- /* Key codes for the Leadtek Winfast DTV Dongle */
- { 0x00, 0x42, KEY_POWER },
- { 0x07, 0x7c, KEY_TUNER },
- { 0x0f, 0x4e, KEY_PRINT }, /* PREVIEW */
- { 0x08, 0x40, KEY_SCREEN }, /* full screen toggle*/
- { 0x0f, 0x71, KEY_DOT }, /* frequency */
- { 0x07, 0x43, KEY_0 },
- { 0x0c, 0x41, KEY_1 },
- { 0x04, 0x43, KEY_2 },
- { 0x0b, 0x7f, KEY_3 },
- { 0x0e, 0x41, KEY_4 },
- { 0x06, 0x43, KEY_5 },
- { 0x09, 0x7f, KEY_6 },
- { 0x0d, 0x7e, KEY_7 },
- { 0x05, 0x7c, KEY_8 },
- { 0x0a, 0x40, KEY_9 },
- { 0x0e, 0x4e, KEY_CLEAR },
- { 0x04, 0x7c, KEY_CHANNEL }, /* show channel number */
- { 0x0f, 0x41, KEY_LAST }, /* recall */
- { 0x03, 0x42, KEY_MUTE },
- { 0x06, 0x4c, KEY_RESERVED }, /* PIP button*/
- { 0x01, 0x72, KEY_SHUFFLE }, /* SNAPSHOT */
- { 0x0c, 0x4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
- { 0x0b, 0x70, KEY_RECORD },
- { 0x03, 0x7d, KEY_VOLUMEUP },
- { 0x01, 0x7d, KEY_VOLUMEDOWN },
- { 0x02, 0x42, KEY_CHANNELUP },
- { 0x00, 0x7d, KEY_CHANNELDOWN },
};
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
@@ -644,22 +578,16 @@ static struct mt2060_config stk7700p_mt2060_config = {
static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
{
- struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap;
struct dib0700_state *st = adap->dev->priv;
struct i2c_adapter *tun_i2c;
- s8 a;
- int if1=1220;
- if (adap->dev->udev->descriptor.idVendor == USB_VID_HAUPPAUGE &&
- adap->dev->udev->descriptor.idProduct == USB_PID_HAUPPAUGE_NOVA_T_STICK) {
- if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a;
- }
+
if (st->is_dib7000pc)
tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
else
tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config,
- if1) == NULL ? -ENODEV : 0;
+ st->mt2060_if1[0]) == NULL ? -ENODEV : 0;
}
/* DIB7070 generic */
@@ -781,8 +709,6 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
.agc_config_count = 1,
.agc = &dib7070_agc_config,
.bw = &dib7070_bw_config_12_mhz,
- .tuner_is_baseband = 1,
- .spur_protect = 1,
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
@@ -822,8 +748,6 @@ static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
.agc_config_count = 1,
.agc = &dib7070_agc_config,
.bw = &dib7070_bw_config_12_mhz,
- .tuner_is_baseband = 1,
- .spur_protect = 1,
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
@@ -836,8 +760,6 @@ static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
.agc_config_count = 1,
.agc = &dib7070_agc_config,
.bw = &dib7070_bw_config_12_mhz,
- .tuner_is_baseband = 1,
- .spur_protect = 1,
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
@@ -899,12 +821,6 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500_PC) },
/* 20 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_EXPRESS) },
- { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U7000) },
- { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) },
- { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000) },
- { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100) },
-/* 25 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) },
- { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) },
{ 0 } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -946,7 +862,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
},
- .num_device_descs = 8,
+ .num_device_descs = 7,
.devices = {
{ "DiBcom STK7700P reference design",
{ &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] },
@@ -975,10 +891,6 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "AVerMedia AVerTV DVB-T Express",
{ &dib0700_usb_id_table[20] },
{ NULL },
- },
- { "Gigabyte U7000",
- { &dib0700_usb_id_table[21], NULL },
- { NULL },
}
},
@@ -1049,7 +961,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "DiBcom STK7700D reference design",
{ &dib0700_usb_id_table[14], NULL },
{ NULL },
- }
+ },
},
.rc_interval = DEFAULT_RC_INTERVAL,
@@ -1057,25 +969,6 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
.rc_query = dib0700_rc_query
- }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-
- .num_adapters = 1,
- .adapter = {
- {
- .frontend_attach = stk7700P2_frontend_attach,
- .tuner_attach = stk7700d_tuner_attach,
-
- DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
- },
- },
-
- .num_device_descs = 1,
- .devices = {
- { "ASUS My Cinema U3000 Mini DVBT Tuner",
- { &dib0700_usb_id_table[23], NULL },
- { NULL },
- },
- }
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 1,
@@ -1090,7 +983,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
},
- .num_device_descs = 6,
+ .num_device_descs = 2,
.devices = {
{ "DiBcom STK7070P reference design",
{ &dib0700_usb_id_table[15], NULL },
@@ -1100,29 +993,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[16], NULL },
{ NULL },
},
- { "Artec T14BR DVB-T",
- { &dib0700_usb_id_table[22], NULL },
- { NULL },
- },
- { "ASUS My Cinema U3100 Mini DVBT Tuner",
- { &dib0700_usb_id_table[24], NULL },
- { NULL },
- },
- { "Hauppauge Nova-T Stick",
- { &dib0700_usb_id_table[25], NULL },
- { NULL },
- },
- { "Hauppauge Nova-T MyTV.t",
- { &dib0700_usb_id_table[26], NULL },
- { NULL },
- },
- },
-
- .rc_interval = DEFAULT_RC_INTERVAL,
- .rc_key_map = dib0700_rc_keys,
- .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
- .rc_query = dib0700_rc_query
-
+ }
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 2,
@@ -1153,7 +1024,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "Pinnacle PCTV Dual DVB-T Diversity Stick",
{ &dib0700_usb_id_table[18], NULL },
{ NULL },
- }
+ },
}
},
};
diff --git a/trunk/drivers/media/dvb/dvb-usb/digitv.c b/trunk/drivers/media/dvb/dvb-usb/digitv.c
index 3acbda4aa27e..bca1e0905739 100644
--- a/trunk/drivers/media/dvb/dvb-usb/digitv.c
+++ b/trunk/drivers/media/dvb/dvb-usb/digitv.c
@@ -17,10 +17,9 @@
#include "nxt6000.h"
/* debug */
-static int dvb_usb_digitv_debug;
+int dvb_usb_digitv_debug;
module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
-#define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args)
static int digitv_ctrl_msg(struct dvb_usb_device *d,
u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
diff --git a/trunk/drivers/media/dvb/dvb-usb/digitv.h b/trunk/drivers/media/dvb/dvb-usb/digitv.h
index 908c09f4966b..8b43e3db8691 100644
--- a/trunk/drivers/media/dvb/dvb-usb/digitv.h
+++ b/trunk/drivers/media/dvb/dvb-usb/digitv.h
@@ -8,6 +8,9 @@ struct digitv_state {
int is_nxt6000;
};
+extern int dvb_usb_digitv_debug;
+#define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args)
+
/* protocol (from usblogging and the SDK:
*
* Always 7 bytes bulk message(s) for controlling
diff --git a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index aa4844ef875e..4fa3e895028a 100644
--- a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -15,9 +15,7 @@
#define USB_VID_ALCOR_MICRO 0x058f
#define USB_VID_ALINK 0x05e3
#define USB_VID_ANCHOR 0x0547
-#define USB_VID_ANSONIC 0x10b9
#define USB_VID_ANUBIS_ELECTRONIC 0x10fd
-#define USB_VID_ASUS 0x0b05
#define USB_VID_AVERMEDIA 0x07ca
#define USB_VID_COMPRO 0x185b
#define USB_VID_COMPRO_UNK 0x145f
@@ -46,16 +44,12 @@
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
#define USB_VID_UNIWILL 0x1584
#define USB_VID_WIDEVIEW 0x14aa
-/* dom : pour gigabyte u7000 */
-#define USB_VID_GIGABYTE 0x1044
-
/* Product IDs */
#define USB_PID_ADSTECH_USB2_COLD 0xa333
#define USB_PID_ADSTECH_USB2_WARM 0xa334
#define USB_PID_AFATECH_AF9005 0x9020
#define USB_VID_ALINK_DTU 0xf170
-#define USB_PID_ANSONIC_DVBT_USB 0x6000
#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
@@ -75,7 +69,6 @@
#define USB_PID_DIBCOM_STK7700P 0x1e14
#define USB_PID_DIBCOM_STK7700P_PC 0x1e78
#define USB_PID_DIBCOM_STK7700D 0x1ef0
-#define USB_PID_DIBCOM_STK7700_U7000 0x7001
#define USB_PID_DIBCOM_STK7070P 0x1ebc
#define USB_PID_DIBCOM_STK7070PD 0x1ebe
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
@@ -106,7 +99,6 @@
#define USB_PID_ULTIMA_TVBOX_USB2_WARM 0x810a
#define USB_PID_ARTEC_T14_COLD 0x810b
#define USB_PID_ARTEC_T14_WARM 0x810c
-#define USB_PID_ARTEC_T14BR 0x810f
#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613
#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002
#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e
@@ -128,8 +120,6 @@
#define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950
#define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050
#define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060
-#define USB_PID_HAUPPAUGE_NOVA_T_STICK_3 0x7070
-#define USB_PID_HAUPPAUGE_MYTV_T 0x7080
#define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580
#define USB_PID_AVERMEDIA_EXPRESS 0xb568
#define USB_PID_AVERMEDIA_VOLAR 0xa807
@@ -153,9 +143,6 @@
#define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51
#define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58
#define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59
-#define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78
-#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70
-#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM 0xdb71
#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54
#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55
#define USB_PID_MEDION_MD95700 0x0932
@@ -183,9 +170,6 @@
#define USB_PID_OPERA1_WARM 0x3829
#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514
#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513
-/* dom pour gigabyte u7000 */
-#define USB_PID_GIGABYTE_U7000 0x7001
-#define USB_PID_ASUS_U3000 0x171f
-#define USB_PID_ASUS_U3100 0x173f
+
#endif
diff --git a/trunk/drivers/media/dvb/dvb-usb/gl861.c b/trunk/drivers/media/dvb/dvb-usb/gl861.c
index 6b99d9f4d5b3..f01d99c1c43c 100644
--- a/trunk/drivers/media/dvb/dvb-usb/gl861.c
+++ b/trunk/drivers/media/dvb/dvb-usb/gl861.c
@@ -56,12 +56,12 @@ static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i;
- if (num > 2)
- return -EINVAL;
-
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
+ if (num > 2)
+ return -EINVAL;
+
for (i = 0; i < num; i++) {
/* write/read request */
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
diff --git a/trunk/drivers/media/dvb/dvb-usb/gp8psk.c b/trunk/drivers/media/dvb/dvb-usb/gp8psk.c
index 83e8535014c6..92147ee3e14f 100644
--- a/trunk/drivers/media/dvb/dvb-usb/gp8psk.c
+++ b/trunk/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -171,6 +171,22 @@ static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
return 0;
}
+int gp8psk_bcm4500_reload(struct dvb_usb_device *d)
+{
+ u8 buf;
+ int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
+ /* Turn off 8psk power */
+ if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
+ return -EINVAL;
+ /* Turn On 8psk power */
+ if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
+ return -EINVAL;
+ /* load BCM4500 firmware */
+ if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
+ if (gp8psk_load_bcm4500fw(d))
+ return EINVAL;
+ return 0;
+}
static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
diff --git a/trunk/drivers/media/dvb/dvb-usb/gp8psk.h b/trunk/drivers/media/dvb/dvb-usb/gp8psk.h
index e5cd8149c23d..e83a57506cfa 100644
--- a/trunk/drivers/media/dvb/dvb-usb/gp8psk.h
+++ b/trunk/drivers/media/dvb/dvb-usb/gp8psk.h
@@ -92,5 +92,6 @@ extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d);
extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
u16 index, u8 *b, int blen);
+extern int gp8psk_bcm4500_reload(struct dvb_usb_device *d);
#endif
diff --git a/trunk/drivers/media/dvb/dvb-usb/opera1.c b/trunk/drivers/media/dvb/dvb-usb/opera1.c
index 21935bf7059e..d7c04951ceab 100644
--- a/trunk/drivers/media/dvb/dvb-usb/opera1.c
+++ b/trunk/drivers/media/dvb/dvb-usb/opera1.c
@@ -10,9 +10,7 @@
* see Documentation/dvb/README.dvb-usb for more information
*/
-#define DVB_USB_LOG_PREFIX "opera"
-
-#include "dvb-usb.h"
+#include "opera1.h"
#include "stv0299.h"
#define OPERA_READ_MSG 0
@@ -40,7 +38,7 @@ struct opera_rc_keys {
u32 event;
};
-static int dvb_usb_opera1_debug;
+int dvb_usb_opera1_debug;
module_param_named(debug, dvb_usb_opera1_debug, int, 0644);
MODULE_PARM_DESC(debug,
"set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))."
diff --git a/trunk/drivers/media/dvb/dvb-usb/opera1.h b/trunk/drivers/media/dvb/dvb-usb/opera1.h
new file mode 100644
index 000000000000..53174427902d
--- /dev/null
+++ b/trunk/drivers/media/dvb/dvb-usb/opera1.h
@@ -0,0 +1,9 @@
+#ifndef _OPERA1_H_
+#define _OPERA1_H_
+
+#define DVB_USB_LOG_PREFIX "opera"
+#include "dvb-usb.h"
+
+extern int dvb_usb_opera1_debug;
+#define deb_xfer(args...) dprintk(dvb_usb_opera1_debug,0x02,args)
+#endif
diff --git a/trunk/drivers/media/dvb/dvb-usb/vp702x.c b/trunk/drivers/media/dvb/dvb-usb/vp702x.c
index e553c139ac44..16533b31a82d 100644
--- a/trunk/drivers/media/dvb/dvb-usb/vp702x.c
+++ b/trunk/drivers/media/dvb/dvb-usb/vp702x.c
@@ -56,7 +56,7 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8
return ret;
}
-static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
u16 index, u8 *b, int blen)
{
int ret;
@@ -204,6 +204,19 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
return 0;
}
+int vp702x_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ struct vp702x_device_state *st = d->priv;
+
+ if (st->power_state == 0 && onoff)
+ vp702x_usb_out_op(d, SET_TUNER_POWER_REQ, 1, 7, NULL, 0);
+ else if (st->power_state == 1 && onoff == 0)
+ vp702x_usb_out_op(d, SET_TUNER_POWER_REQ, 0, 7, NULL, 0);
+
+ st->power_state = onoff;
+
+ return 0;
+}
static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
{
diff --git a/trunk/drivers/media/dvb/dvb-usb/vp702x.h b/trunk/drivers/media/dvb/dvb-usb/vp702x.h
index c2f97f96c21f..25a9dee4c824 100644
--- a/trunk/drivers/media/dvb/dvb-usb/vp702x.h
+++ b/trunk/drivers/media/dvb/dvb-usb/vp702x.h
@@ -102,5 +102,7 @@ extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+extern int vp702x_power_ctrl(struct dvb_usb_device *d, int onoff);
#endif
diff --git a/trunk/drivers/media/dvb/dvb-usb/vp7045.c b/trunk/drivers/media/dvb/dvb-usb/vp7045.c
index c172babf59bb..5bbd2d5192f0 100644
--- a/trunk/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/trunk/drivers/media/dvb/dvb-usb/vp7045.c
@@ -15,12 +15,9 @@
#include "vp7045.h"
/* debug */
-static int dvb_usb_vp7045_debug;
+int dvb_usb_vp7045_debug;
module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
-#define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
-#define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
-#define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args)
int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec)
{
diff --git a/trunk/drivers/media/dvb/dvb-usb/vp7045.h b/trunk/drivers/media/dvb/dvb-usb/vp7045.h
index 969688f85267..9ce21a20fa86 100644
--- a/trunk/drivers/media/dvb/dvb-usb/vp7045.h
+++ b/trunk/drivers/media/dvb/dvb-usb/vp7045.h
@@ -17,6 +17,11 @@
#define DVB_USB_LOG_PREFIX "vp7045"
#include "dvb-usb.h"
+extern int dvb_usb_vp7045_debug;
+#define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
+#define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args)
+
/* vp7045 commands */
/* Twinhan Vendor requests */
diff --git a/trunk/drivers/media/dvb/frontends/Kconfig b/trunk/drivers/media/dvb/frontends/Kconfig
index 9ad86ce4a4e5..59b9ed1f1aec 100644
--- a/trunk/drivers/media/dvb/frontends/Kconfig
+++ b/trunk/drivers/media/dvb/frontends/Kconfig
@@ -316,13 +316,6 @@ config DVB_TDA827X
help
A DVB-T silicon tuner module. Say Y when you want to support this tuner.
-config DVB_TDA18271
- tristate "NXP TDA18271 silicon tuner"
- depends on I2C
- default m if DVB_FE_CUSTOMISE
- help
- A silicon tuner module. Say Y when you want to support this tuner.
-
config DVB_TUNER_QT1010
tristate "Quantek QT1010 silicon tuner"
depends on DVB_CORE && I2C
@@ -360,15 +353,6 @@ config DVB_TUNER_DIB0070
This device is only used inside a SiP called togther with a
demodulator for now.
-config DVB_TUNER_XC5000
- tristate "Xceive XC5000 silicon tuner"
- depends on I2C
- default m if DVB_FE_CUSTOMISE
- help
- A driver for the silicon tuner XC5000 from Xceive.
- This device is only used inside a SiP called togther with a
- demodulator for now.
-
comment "Miscellaneous devices"
depends on DVB_CORE
diff --git a/trunk/drivers/media/dvb/frontends/Makefile b/trunk/drivers/media/dvb/frontends/Makefile
index 16bd107ebd32..4b8ad1f132aa 100644
--- a/trunk/drivers/media/dvb/frontends/Makefile
+++ b/trunk/drivers/media/dvb/frontends/Makefile
@@ -3,9 +3,6 @@
#
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/video/
-
-tda18271-objs := tda18271-tables.o tda18271-common.o tda18271-fe.o
obj-$(CONFIG_DVB_PLL) += dvb-pll.o
obj-$(CONFIG_DVB_STV0299) += stv0299.o
@@ -42,7 +39,6 @@ obj-$(CONFIG_DVB_ISL6421) += isl6421.o
obj-$(CONFIG_DVB_TDA10086) += tda10086.o
obj-$(CONFIG_DVB_TDA826X) += tda826x.o
obj-$(CONFIG_DVB_TDA827X) += tda827x.o
-obj-$(CONFIG_DVB_TDA18271) += tda18271.o
obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
obj-$(CONFIG_DVB_TUNER_MT2266) += mt2266.o
obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
@@ -50,4 +46,3 @@ obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o
obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
-obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o
diff --git a/trunk/drivers/media/dvb/frontends/dib0070.c b/trunk/drivers/media/dvb/frontends/dib0070.c
index fe895bf7b18f..481eaa684157 100644
--- a/trunk/drivers/media/dvb/frontends/dib0070.c
+++ b/trunk/drivers/media/dvb/frontends/dib0070.c
@@ -434,14 +434,9 @@ static u16 dib0070_p1f_defaults[] =
0,
};
-static void dib0070_wbd_calibration(struct dvb_frontend *fe)
+static void dib0070_wbd_calibration(struct dib0070_state *state)
{
u16 wbd_offs;
- struct dib0070_state *state = fe->tuner_priv;
-
- if (state->cfg->sleep)
- state->cfg->sleep(fe, 0);
-
dib0070_write_reg(state, 0x0f, 0x6d81);
dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
msleep(9);
@@ -449,10 +444,6 @@ static void dib0070_wbd_calibration(struct dvb_frontend *fe)
dib0070_write_reg(state, 0x20, 0);
state->wbd_ff_offset = ((wbd_offs * 8 * 18 / 33 + 1) / 2);
dprintk( "WBDStart = %d (Vargen) - FF = %hd", (u32) wbd_offs * 1800/1024, state->wbd_ff_offset);
-
- if (state->cfg->sleep)
- state->cfg->sleep(fe, 1);
-
}
u16 dib0070_wbd_offset(struct dvb_frontend *fe)
@@ -569,7 +560,7 @@ struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter
if (dib0070_reset(state) != 0)
goto free_mem;
- dib0070_wbd_calibration(fe);
+ dib0070_wbd_calibration(state);
printk(KERN_INFO "DiB0070: successfully identified\n");
memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
diff --git a/trunk/drivers/media/dvb/frontends/dib3000mc.c b/trunk/drivers/media/dvb/frontends/dib3000mc.c
index fa851601e7d4..edae0be063f5 100644
--- a/trunk/drivers/media/dvb/frontends/dib3000mc.c
+++ b/trunk/drivers/media/dvb/frontends/dib3000mc.c
@@ -684,9 +684,6 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
struct dib3000mc_state *state = fe->demodulator_priv;
- int ret;
-
- dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
state->current_bandwidth = fep->u.ofdm.bandwidth;
dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
@@ -703,7 +700,7 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
fep->u.ofdm.constellation == QAM_AUTO ||
fep->u.ofdm.code_rate_HP == FEC_AUTO) {
- int i = 1000, found;
+ int i = 100, found;
dib3000mc_autosearch_start(fe, fep);
do {
@@ -718,11 +715,10 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
dib3000mc_get_frontend(fe, fep);
}
- ret = dib3000mc_tune(fe, fep);
-
/* make this a config parameter */
dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
- return ret;
+
+ return dib3000mc_tune(fe, fep);
}
static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
diff --git a/trunk/drivers/media/dvb/frontends/dib7000m.c b/trunk/drivers/media/dvb/frontends/dib7000m.c
index 5f1375e30dfc..fb18441a8c57 100644
--- a/trunk/drivers/media/dvb/frontends/dib7000m.c
+++ b/trunk/drivers/media/dvb/frontends/dib7000m.c
@@ -1171,9 +1171,7 @@ static int dib7000m_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
struct dib7000m_state *state = fe->demodulator_priv;
- int time, ret;
-
- dib7000m_set_output_mode(state, OUTMODE_HIGH_Z);
+ int time;
state->current_bandwidth = fep->u.ofdm.bandwidth;
dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
@@ -1208,11 +1206,10 @@ static int dib7000m_set_frontend(struct dvb_frontend* fe,
dib7000m_get_frontend(fe, fep);
}
- ret = dib7000m_tune(fe, fep);
-
/* make this a config parameter */
dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
- return ret;
+
+ return dib7000m_tune(fe, fep);
}
static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)
diff --git a/trunk/drivers/media/dvb/frontends/dib7000p.c b/trunk/drivers/media/dvb/frontends/dib7000p.c
index 47c23e29753e..f45bcfc51cf8 100644
--- a/trunk/drivers/media/dvb/frontends/dib7000p.c
+++ b/trunk/drivers/media/dvb/frontends/dib7000p.c
@@ -35,8 +35,8 @@ struct dib7000p_state {
u16 wbd_ref;
- u8 current_band;
- u32 current_bandwidth;
+ u8 current_band;
+ fe_bandwidth_t current_bandwidth;
struct dibx000_agc_config *current_agc;
u32 timf;
@@ -1074,7 +1074,7 @@ static int dib7000p_get_frontend(struct dvb_frontend* fe,
fep->inversion = INVERSION_AUTO;
- fep->u.ofdm.bandwidth = BANDWIDTH_TO_INDEX(state->current_bandwidth);
+ fep->u.ofdm.bandwidth = state->current_bandwidth;
switch ((tps >> 8) & 0x3) {
case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
@@ -1128,11 +1128,12 @@ static int dib7000p_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
struct dib7000p_state *state = fe->demodulator_priv;
- int time, ret;
+ int time;
- dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
+ state->current_bandwidth = fep->u.ofdm.bandwidth;
+ dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
- /* maybe the parameter has been changed */
+ /* maybe the parameter has been changed */
state->sfn_workaround_active = buggy_sfn_workaround;
if (fe->ops.tuner_ops.set_params)
@@ -1165,11 +1166,10 @@ static int dib7000p_set_frontend(struct dvb_frontend* fe,
dib7000p_get_frontend(fe, fep);
}
- ret = dib7000p_tune(fe, fep);
-
/* make this a config parameter */
dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO);
- return ret;
+
+ return dib7000p_tune(fe, fep);
}
static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat)
diff --git a/trunk/drivers/media/dvb/frontends/dibx000_common.h b/trunk/drivers/media/dvb/frontends/dibx000_common.h
index 84e4d5362922..5e17275afd25 100644
--- a/trunk/drivers/media/dvb/frontends/dibx000_common.h
+++ b/trunk/drivers/media/dvb/frontends/dibx000_common.h
@@ -128,11 +128,6 @@ enum dibx000_adc_states {
(v) == BANDWIDTH_7_MHZ ? 7000 : \
(v) == BANDWIDTH_6_MHZ ? 6000 : 8000 )
-#define BANDWIDTH_TO_INDEX(v) ( \
- (v) == 8000 ? BANDWIDTH_8_MHZ : \
- (v) == 7000 ? BANDWIDTH_7_MHZ : \
- (v) == 6000 ? BANDWIDTH_6_MHZ : BANDWIDTH_8_MHZ )
-
/* Chip output mode. */
#define OUTMODE_HIGH_Z 0
#define OUTMODE_MPEG2_PAR_GATED_CLK 1
diff --git a/trunk/drivers/media/dvb/frontends/mt2266.c b/trunk/drivers/media/dvb/frontends/mt2266.c
index 54b18f94b14b..03fe8265745f 100644
--- a/trunk/drivers/media/dvb/frontends/mt2266.c
+++ b/trunk/drivers/media/dvb/frontends/mt2266.c
@@ -38,12 +38,8 @@ struct mt2266_priv {
u32 frequency;
u32 bandwidth;
- u8 band;
};
-#define MT2266_VHF 1
-#define MT2266_UHF 0
-
/* Here, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
static int debug;
@@ -94,30 +90,26 @@ static int mt2266_writeregs(struct mt2266_priv *priv,u8 *buf, u8 len)
}
// Initialisation sequences
-static u8 mt2266_init1[] = { REG_TUNE, 0x00, 0x00, 0x28,
- 0x00, 0x52, 0x99, 0x3f };
+static u8 mt2266_init1[] = {
+ REG_TUNE,
+ 0x00, 0x00, 0x28, 0x00, 0x52, 0x99, 0x3f };
static u8 mt2266_init2[] = {
- 0x17, 0x6d, 0x71, 0x61, 0xc0, 0xbf, 0xff, 0xdc, 0x00, 0x0a, 0xd4,
- 0x03, 0x64, 0x64, 0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7f, 0x5e, 0x3f, 0xff, 0xff,
- 0xff, 0x00, 0x77, 0x0f, 0x2d
-};
-
-static u8 mt2266_init_8mhz[] = { REG_BANDWIDTH, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22 };
+ 0x17, 0x6d, 0x71, 0x61, 0xc0, 0xbf, 0xff, 0xdc, 0x00, 0x0a,
+ 0xd4, 0x03, 0x64, 0x64, 0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x7f, 0x5e, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x77, 0x0f, 0x2d };
-static u8 mt2266_init_7mhz[] = { REG_BANDWIDTH, 0x32, 0x32, 0x32, 0x32,
- 0x32, 0x32, 0x32, 0x32 };
+static u8 mt2266_init_8mhz[] = {
+ REG_BANDWIDTH,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 };
-static u8 mt2266_init_6mhz[] = { REG_BANDWIDTH, 0xa7, 0xa7, 0xa7, 0xa7,
- 0xa7, 0xa7, 0xa7, 0xa7 };
+static u8 mt2266_init_7mhz[] = {
+ REG_BANDWIDTH,
+ 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32 };
-static u8 mt2266_uhf[] = { 0x1d, 0xdc, 0x00, 0x0a, 0xd4, 0x03, 0x64, 0x64,
- 0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14 };
-
-static u8 mt2266_vhf[] = { 0x1d, 0xfe, 0x00, 0x00, 0xb4, 0x03, 0xa5, 0xa5,
- 0xa5, 0xa5, 0x82, 0xaa, 0xf1, 0x17, 0x80, 0x1f };
+static u8 mt2266_init_6mhz[] = {
+ REG_BANDWIDTH,
+ 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7 };
#define FREF 30000 // Quartz oscillator 30 MHz
@@ -130,78 +122,35 @@ static int mt2266_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame
u8 lnaband;
u8 b[10];
int i;
- u8 band;
priv = fe->tuner_priv;
+ mt2266_writereg(priv,0x17,0x6d);
+ mt2266_writereg(priv,0x1c,0xff);
+
freq = params->frequency / 1000; // Hz -> kHz
- if (freq < 470000 && freq > 230000)
- return -EINVAL; /* Gap between VHF and UHF bands */
priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
priv->frequency = freq * 1000;
-
- tune = 2 * freq * (8192/16) / (FREF/16);
- band = (freq < 300000) ? MT2266_VHF : MT2266_UHF;
- if (band == MT2266_VHF)
- tune *= 2;
-
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
- mt2266_writeregs(priv, mt2266_init_6mhz,
- sizeof(mt2266_init_6mhz));
- break;
- case BANDWIDTH_7_MHZ:
- mt2266_writeregs(priv, mt2266_init_7mhz,
- sizeof(mt2266_init_7mhz));
- break;
- case BANDWIDTH_8_MHZ:
- default:
- mt2266_writeregs(priv, mt2266_init_8mhz,
- sizeof(mt2266_init_8mhz));
- break;
- }
-
- if (band == MT2266_VHF && priv->band == MT2266_UHF) {
- dprintk("Switch from UHF to VHF");
- mt2266_writereg(priv, 0x05, 0x04);
- mt2266_writereg(priv, 0x19, 0x61);
- mt2266_writeregs(priv, mt2266_vhf, sizeof(mt2266_vhf));
- } else if (band == MT2266_UHF && priv->band == MT2266_VHF) {
- dprintk("Switch from VHF to UHF");
- mt2266_writereg(priv, 0x05, 0x52);
- mt2266_writereg(priv, 0x19, 0x61);
- mt2266_writeregs(priv, mt2266_uhf, sizeof(mt2266_uhf));
- }
- msleep(10);
-
- if (freq <= 495000)
- lnaband = 0xEE;
- else if (freq <= 525000)
- lnaband = 0xDD;
- else if (freq <= 550000)
- lnaband = 0xCC;
- else if (freq <= 580000)
- lnaband = 0xBB;
- else if (freq <= 605000)
- lnaband = 0xAA;
- else if (freq <= 630000)
- lnaband = 0x99;
- else if (freq <= 655000)
- lnaband = 0x88;
- else if (freq <= 685000)
- lnaband = 0x77;
- else if (freq <= 710000)
- lnaband = 0x66;
- else if (freq <= 735000)
- lnaband = 0x55;
- else if (freq <= 765000)
- lnaband = 0x44;
- else if (freq <= 802000)
- lnaband = 0x33;
- else if (freq <= 840000)
- lnaband = 0x22;
- else
- lnaband = 0x11;
+ tune=2 * freq * (8192/16) / (FREF/16);
+
+ if (freq <= 495000) lnaband = 0xEE; else
+ if (freq <= 525000) lnaband = 0xDD; else
+ if (freq <= 550000) lnaband = 0xCC; else
+ if (freq <= 580000) lnaband = 0xBB; else
+ if (freq <= 605000) lnaband = 0xAA; else
+ if (freq <= 630000) lnaband = 0x99; else
+ if (freq <= 655000) lnaband = 0x88; else
+ if (freq <= 685000) lnaband = 0x77; else
+ if (freq <= 710000) lnaband = 0x66; else
+ if (freq <= 735000) lnaband = 0x55; else
+ if (freq <= 765000) lnaband = 0x44; else
+ if (freq <= 802000) lnaband = 0x33; else
+ if (freq <= 840000) lnaband = 0x22; else lnaband = 0x11;
+
+ msleep(100);
+ mt2266_writeregs(priv,(params->u.ofdm.bandwidth==BANDWIDTH_6_MHZ)?mt2266_init_6mhz:
+ (params->u.ofdm.bandwidth==BANDWIDTH_7_MHZ)?mt2266_init_7mhz:
+ mt2266_init_8mhz,sizeof(mt2266_init_8mhz));
b[0] = REG_TUNE;
b[1] = (tune >> 8) & 0x1F;
@@ -209,54 +158,47 @@ static int mt2266_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame
b[3] = tune >> 13;
mt2266_writeregs(priv,b,4);
- dprintk("set_parms: tune=%d band=%d %s",
- (int) tune, (int) lnaband,
- (band == MT2266_UHF) ? "UHF" : "VHF");
- dprintk("set_parms: [1..3]: %2x %2x %2x",
- (int) b[1], (int) b[2], (int)b[3]);
-
- if (band == MT2266_UHF) {
- b[0] = 0x05;
- b[1] = (priv->band == MT2266_VHF) ? 0x52 : 0x62;
- b[2] = lnaband;
- mt2266_writeregs(priv, b, 3);
- }
+ dprintk("set_parms: tune=%d band=%d",(int)tune,(int)lnaband);
+ dprintk("set_parms: [1..3]: %2x %2x %2x",(int)b[1],(int)b[2],(int)b[3]);
+
+ b[0] = 0x05;
+ b[1] = 0x62;
+ b[2] = lnaband;
+ mt2266_writeregs(priv,b,3);
- /* Wait for pll lock or timeout */
+ //Waits for pll lock or timeout
i = 0;
do {
mt2266_readreg(priv,REG_LOCK,b);
- if (b[0] & 0x40)
+ if ((b[0] & 0x40)==0x40)
break;
msleep(10);
i++;
} while (i<10);
dprintk("Lock when i=%i",(int)i);
-
- if (band == MT2266_UHF && priv->band == MT2266_VHF)
- mt2266_writereg(priv, 0x05, 0x62);
-
- priv->band = band;
-
return ret;
}
static void mt2266_calibrate(struct mt2266_priv *priv)
{
- mt2266_writereg(priv, 0x11, 0x03);
- mt2266_writereg(priv, 0x11, 0x01);
- mt2266_writeregs(priv, mt2266_init1, sizeof(mt2266_init1));
- mt2266_writeregs(priv, mt2266_init2, sizeof(mt2266_init2));
- mt2266_writereg(priv, 0x33, 0x5e);
- mt2266_writereg(priv, 0x10, 0x10);
- mt2266_writereg(priv, 0x10, 0x00);
- mt2266_writeregs(priv, mt2266_init_8mhz, sizeof(mt2266_init_8mhz));
+ mt2266_writereg(priv,0x11,0x03);
+ mt2266_writereg(priv,0x11,0x01);
+
+ mt2266_writeregs(priv,mt2266_init1,sizeof(mt2266_init1));
+ mt2266_writeregs(priv,mt2266_init2,sizeof(mt2266_init2));
+
+ mt2266_writereg(priv,0x33,0x5e);
+ mt2266_writereg(priv,0x10,0x10);
+ mt2266_writereg(priv,0x10,0x00);
+
+ mt2266_writeregs(priv,mt2266_init_8mhz,sizeof(mt2266_init_8mhz));
+
msleep(25);
- mt2266_writereg(priv, 0x17, 0x6d);
- mt2266_writereg(priv, 0x1c, 0x00);
+ mt2266_writereg(priv,0x17,0x6d);
+ mt2266_writereg(priv,0x1c,0x00);
msleep(75);
- mt2266_writereg(priv, 0x17, 0x6d);
- mt2266_writereg(priv, 0x1c, 0xff);
+ mt2266_writereg(priv,0x17,0x6d);
+ mt2266_writereg(priv,0x1c,0xff);
}
static int mt2266_get_frequency(struct dvb_frontend *fe, u32 *frequency)
@@ -275,22 +217,17 @@ static int mt2266_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
static int mt2266_init(struct dvb_frontend *fe)
{
- int ret;
struct mt2266_priv *priv = fe->tuner_priv;
- ret = mt2266_writereg(priv, 0x17, 0x6d);
- if (ret < 0)
- return ret;
- ret = mt2266_writereg(priv, 0x1c, 0xff);
- if (ret < 0)
- return ret;
+ mt2266_writereg(priv,0x17,0x6d);
+ mt2266_writereg(priv,0x1c,0xff);
return 0;
}
static int mt2266_sleep(struct dvb_frontend *fe)
{
struct mt2266_priv *priv = fe->tuner_priv;
- mt2266_writereg(priv, 0x17, 0x6d);
- mt2266_writereg(priv, 0x1c, 0x00);
+ mt2266_writereg(priv,0x17,0x6d);
+ mt2266_writereg(priv,0x1c,0x00);
return 0;
}
@@ -304,8 +241,8 @@ static int mt2266_release(struct dvb_frontend *fe)
static const struct dvb_tuner_ops mt2266_tuner_ops = {
.info = {
.name = "Microtune MT2266",
- .frequency_min = 174000000,
- .frequency_max = 862000000,
+ .frequency_min = 470000000,
+ .frequency_max = 860000000,
.frequency_step = 50000,
},
.release = mt2266_release,
@@ -327,9 +264,8 @@ struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter
priv->cfg = cfg;
priv->i2c = i2c;
- priv->band = MT2266_UHF;
- if (mt2266_readreg(priv, 0, &id)) {
+ if (mt2266_readreg(priv,0,&id) != 0) {
kfree(priv);
return NULL;
}
diff --git a/trunk/drivers/media/dvb/frontends/mt312.c b/trunk/drivers/media/dvb/frontends/mt312.c
index 1638301fbd6e..0606b9a5b616 100644
--- a/trunk/drivers/media/dvb/frontends/mt312.c
+++ b/trunk/drivers/media/dvb/frontends/mt312.c
@@ -37,9 +37,9 @@
struct mt312_state {
- struct i2c_adapter *i2c;
+ struct i2c_adapter* i2c;
/* configuration settings */
- const struct mt312_config *config;
+ const struct mt312_config* config;
struct dvb_frontend frontend;
u8 id;
@@ -49,15 +49,14 @@ struct mt312_state {
static int debug;
#define dprintk(args...) \
do { \
- if (debug) \
- printk(KERN_DEBUG "mt312: " args); \
+ if (debug) printk(KERN_DEBUG "mt312: " args); \
} while (0)
#define MT312_SYS_CLK 90000000UL /* 90 MHz */
#define MT312_LPOWER_SYS_CLK 60000000UL /* 60 MHz */
#define MT312_PLL_CLK 10000000UL /* 10 MHz */
-static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+static int mt312_read(struct mt312_state* state, const enum mt312_reg_addr reg,
void *buf, const size_t count)
{
int ret;
@@ -80,7 +79,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
return -EREMOTEIO;
}
- if (debug) {
+ if(debug) {
int i;
dprintk("R(%d):", reg & 0x7f);
for (i = 0; i < count; i++)
@@ -91,14 +90,14 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
return 0;
}
-static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
+static int mt312_write(struct mt312_state* state, const enum mt312_reg_addr reg,
const void *src, const size_t count)
{
int ret;
u8 buf[count + 1];
struct i2c_msg msg;
- if (debug) {
+ if(debug) {
int i;
dprintk("W(%d):", reg & 0x7f);
for (i = 0; i < count; i++)
@@ -124,13 +123,13 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
return 0;
}
-static inline int mt312_readreg(struct mt312_state *state,
+static inline int mt312_readreg(struct mt312_state* state,
const enum mt312_reg_addr reg, u8 *val)
{
return mt312_read(state, reg, val, 1);
}
-static inline int mt312_writereg(struct mt312_state *state,
+static inline int mt312_writereg(struct mt312_state* state,
const enum mt312_reg_addr reg, const u8 val)
{
return mt312_write(state, reg, &val, 1);
@@ -141,19 +140,18 @@ static inline u32 mt312_div(u32 a, u32 b)
return (a + (b / 2)) / b;
}
-static int mt312_reset(struct mt312_state *state, const u8 full)
+static int mt312_reset(struct mt312_state* state, const u8 full)
{
return mt312_writereg(state, RESET, full ? 0x80 : 0x40);
}
-static int mt312_get_inversion(struct mt312_state *state,
+static int mt312_get_inversion(struct mt312_state* state,
fe_spectral_inversion_t *i)
{
int ret;
u8 vit_mode;
- ret = mt312_readreg(state, VIT_MODE, &vit_mode);
- if (ret < 0)
+ if ((ret = mt312_readreg(state, VIT_MODE, &vit_mode)) < 0)
return ret;
if (vit_mode & 0x80) /* auto inversion was used */
@@ -162,7 +160,7 @@ static int mt312_get_inversion(struct mt312_state *state,
return 0;
}
-static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
+static int mt312_get_symbol_rate(struct mt312_state* state, u32 *sr)
{
int ret;
u8 sym_rate_h;
@@ -171,44 +169,37 @@ static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
u16 monitor;
u8 buf[2];
- ret = mt312_readreg(state, SYM_RATE_H, &sym_rate_h);
- if (ret < 0)
+ if ((ret = mt312_readreg(state, SYM_RATE_H, &sym_rate_h)) < 0)
return ret;
- if (sym_rate_h & 0x80) {
- /* symbol rate search was used */
- ret = mt312_writereg(state, MON_CTRL, 0x03);
- if (ret < 0)
+ if (sym_rate_h & 0x80) { /* symbol rate search was used */
+ if ((ret = mt312_writereg(state, MON_CTRL, 0x03)) < 0)
return ret;
- ret = mt312_read(state, MONITOR_H, buf, sizeof(buf));
- if (ret < 0)
+ if ((ret = mt312_read(state, MONITOR_H, buf, sizeof(buf))) < 0)
return ret;
monitor = (buf[0] << 8) | buf[1];
- dprintk("sr(auto) = %u\n",
+ dprintk(KERN_DEBUG "sr(auto) = %u\n",
mt312_div(monitor * 15625, 4));
} else {
- ret = mt312_writereg(state, MON_CTRL, 0x05);
- if (ret < 0)
+ if ((ret = mt312_writereg(state, MON_CTRL, 0x05)) < 0)
return ret;
- ret = mt312_read(state, MONITOR_H, buf, sizeof(buf));
- if (ret < 0)
+ if ((ret = mt312_read(state, MONITOR_H, buf, sizeof(buf))) < 0)
return ret;
dec_ratio = ((buf[0] >> 5) & 0x07) * 32;
- ret = mt312_read(state, SYM_RAT_OP_H, buf, sizeof(buf));
- if (ret < 0)
+ if ((ret = mt312_read(state, SYM_RAT_OP_H, buf, sizeof(buf))) < 0)
return ret;
sym_rat_op = (buf[0] << 8) | buf[1];
- dprintk("sym_rat_op=%d dec_ratio=%d\n",
+ dprintk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n",
sym_rat_op, dec_ratio);
- dprintk("*sr(manual) = %lu\n",
+ dprintk(KERN_DEBUG "*sr(manual) = %lu\n",
(((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
2) - dec_ratio);
}
@@ -216,7 +207,7 @@ static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
return 0;
}
-static int mt312_get_code_rate(struct mt312_state *state, fe_code_rate_t *cr)
+static int mt312_get_code_rate(struct mt312_state* state, fe_code_rate_t *cr)
{
const fe_code_rate_t fec_tab[8] =
{ FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_6_7, FEC_7_8,
@@ -225,8 +216,7 @@ static int mt312_get_code_rate(struct mt312_state *state, fe_code_rate_t *cr)
int ret;
u8 fec_status;
- ret = mt312_readreg(state, FEC_STATUS, &fec_status);
- if (ret < 0)
+ if ((ret = mt312_readreg(state, FEC_STATUS, &fec_status)) < 0)
return ret;
*cr = fec_tab[(fec_status >> 4) & 0x07];
@@ -234,72 +224,61 @@ static int mt312_get_code_rate(struct mt312_state *state, fe_code_rate_t *cr)
return 0;
}
-static int mt312_initfe(struct dvb_frontend *fe)
+static int mt312_initfe(struct dvb_frontend* fe)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[2];
/* wake up */
- ret = mt312_writereg(state, CONFIG,
- (state->frequency == 60 ? 0x88 : 0x8c));
- if (ret < 0)
+ if ((ret = mt312_writereg(state, CONFIG, (state->frequency == 60 ? 0x88 : 0x8c))) < 0)
return ret;
/* wait at least 150 usec */
udelay(150);
/* full reset */
- ret = mt312_reset(state, 1);
- if (ret < 0)
+ if ((ret = mt312_reset(state, 1)) < 0)
return ret;
-/* Per datasheet, write correct values. 09/28/03 ACCJr.
- * If we don't do this, we won't get FE_HAS_VITERBI in the VP310. */
+// Per datasheet, write correct values. 09/28/03 ACCJr.
+// If we don't do this, we won't get FE_HAS_VITERBI in the VP310.
{
- u8 buf_def[8] = { 0x14, 0x12, 0x03, 0x02,
- 0x01, 0x00, 0x00, 0x00 };
+ u8 buf_def[8]={0x14, 0x12, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00};
- ret = mt312_write(state, VIT_SETUP, buf_def, sizeof(buf_def));
- if (ret < 0)
+ if ((ret = mt312_write(state, VIT_SETUP, buf_def, sizeof(buf_def))) < 0)
return ret;
}
/* SYS_CLK */
- buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK :
- MT312_SYS_CLK) * 2, 1000000);
+ buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK : MT312_SYS_CLK) * 2, 1000000);
/* DISEQC_RATIO */
buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4);
- ret = mt312_write(state, SYS_CLK, buf, sizeof(buf));
- if (ret < 0)
+ if ((ret = mt312_write(state, SYS_CLK, buf, sizeof(buf))) < 0)
return ret;
- ret = mt312_writereg(state, SNR_THS_HIGH, 0x32);
- if (ret < 0)
+ if ((ret = mt312_writereg(state, SNR_THS_HIGH, 0x32)) < 0)
return ret;
- ret = mt312_writereg(state, OP_CTRL, 0x53);
- if (ret < 0)
+ if ((ret = mt312_writereg(state, OP_CTRL, 0x53)) < 0)
return ret;
/* TS_SW_LIM */
buf[0] = 0x8c;
buf[1] = 0x98;
- ret = mt312_write(state, TS_SW_LIM_L, buf, sizeof(buf));
- if (ret < 0)
+ if ((ret = mt312_write(state, TS_SW_LIM_L, buf, sizeof(buf))) < 0)
return ret;
- ret = mt312_writereg(state, CS_SW_LIM, 0x69);
- if (ret < 0)
+ if ((ret = mt312_writereg(state, CS_SW_LIM, 0x69)) < 0)
return ret;
return 0;
}
-static int mt312_send_master_cmd(struct dvb_frontend *fe,
+static int mt312_send_master_cmd(struct dvb_frontend* fe,
struct dvb_diseqc_master_cmd *c)
{
struct mt312_state *state = fe->demodulator_priv;
@@ -309,31 +288,29 @@ static int mt312_send_master_cmd(struct dvb_frontend *fe,
if ((c->msg_len == 0) || (c->msg_len > sizeof(c->msg)))
return -EINVAL;
- ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode);
- if (ret < 0)
+ if ((ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode)) < 0)
return ret;
- ret = mt312_write(state, (0x80 | DISEQC_INSTR), c->msg, c->msg_len);
- if (ret < 0)
+ if ((ret =
+ mt312_write(state, (0x80 | DISEQC_INSTR), c->msg, c->msg_len)) < 0)
return ret;
- ret = mt312_writereg(state, DISEQC_MODE,
- (diseqc_mode & 0x40) | ((c->msg_len - 1) << 3)
- | 0x04);
- if (ret < 0)
+ if ((ret =
+ mt312_writereg(state, DISEQC_MODE,
+ (diseqc_mode & 0x40) | ((c->msg_len - 1) << 3)
+ | 0x04)) < 0)
return ret;
/* set DISEQC_MODE[2:0] to zero if a return message is expected */
- if (c->msg[0] & 0x02) {
- ret = mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40));
- if (ret < 0)
+ if (c->msg[0] & 0x02)
+ if ((ret =
+ mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40))) < 0)
return ret;
- }
return 0;
}
-static int mt312_send_burst(struct dvb_frontend *fe, const fe_sec_mini_cmd_t c)
+static int mt312_send_burst(struct dvb_frontend* fe, const fe_sec_mini_cmd_t c)
{
struct mt312_state *state = fe->demodulator_priv;
const u8 mini_tab[2] = { 0x02, 0x03 };
@@ -344,19 +321,18 @@ static int mt312_send_burst(struct dvb_frontend *fe, const fe_sec_mini_cmd_t c)
if (c > SEC_MINI_B)
return -EINVAL;
- ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode);
- if (ret < 0)
+ if ((ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode)) < 0)
return ret;
- ret = mt312_writereg(state, DISEQC_MODE,
- (diseqc_mode & 0x40) | mini_tab[c]);
- if (ret < 0)
+ if ((ret =
+ mt312_writereg(state, DISEQC_MODE,
+ (diseqc_mode & 0x40) | mini_tab[c])) < 0)
return ret;
return 0;
}
-static int mt312_set_tone(struct dvb_frontend *fe, const fe_sec_tone_mode_t t)
+static int mt312_set_tone(struct dvb_frontend* fe, const fe_sec_tone_mode_t t)
{
struct mt312_state *state = fe->demodulator_priv;
const u8 tone_tab[2] = { 0x01, 0x00 };
@@ -367,19 +343,18 @@ static int mt312_set_tone(struct dvb_frontend *fe, const fe_sec_tone_mode_t t)
if (t > SEC_TONE_OFF)
return -EINVAL;
- ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode);
- if (ret < 0)
+ if ((ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode)) < 0)
return ret;
- ret = mt312_writereg(state, DISEQC_MODE,
- (diseqc_mode & 0x40) | tone_tab[t]);
- if (ret < 0)
+ if ((ret =
+ mt312_writereg(state, DISEQC_MODE,
+ (diseqc_mode & 0x40) | tone_tab[t])) < 0)
return ret;
return 0;
}
-static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v)
+static int mt312_set_voltage(struct dvb_frontend* fe, const fe_sec_voltage_t v)
{
struct mt312_state *state = fe->demodulator_priv;
const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
@@ -390,7 +365,7 @@ static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v)
return mt312_writereg(state, DISEQC_MODE, volt_tab[v]);
}
-static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s)
+static int mt312_read_status(struct dvb_frontend* fe, fe_status_t *s)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
@@ -398,12 +373,10 @@ static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s)
*s = 0;
- ret = mt312_read(state, QPSK_STAT_H, status, sizeof(status));
- if (ret < 0)
+ if ((ret = mt312_read(state, QPSK_STAT_H, status, sizeof(status))) < 0)
return ret;
- dprintk("QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x,"
- " FEC_STATUS: 0x%02x\n", status[0], status[1], status[2]);
+ dprintk(KERN_DEBUG "QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x, FEC_STATUS: 0x%02x\n", status[0], status[1], status[2]);
if (status[0] & 0xc0)
*s |= FE_HAS_SIGNAL; /* signal noise ratio */
@@ -419,14 +392,13 @@ static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s)
return 0;
}
-static int mt312_read_ber(struct dvb_frontend *fe, u32 *ber)
+static int mt312_read_ber(struct dvb_frontend* fe, u32 *ber)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[3];
- ret = mt312_read(state, RS_BERCNT_H, buf, 3);
- if (ret < 0)
+ if ((ret = mt312_read(state, RS_BERCNT_H, buf, 3)) < 0)
return ret;
*ber = ((buf[0] << 16) | (buf[1] << 8) | buf[2]) * 64;
@@ -434,8 +406,7 @@ static int mt312_read_ber(struct dvb_frontend *fe, u32 *ber)
return 0;
}
-static int mt312_read_signal_strength(struct dvb_frontend *fe,
- u16 *signal_strength)
+static int mt312_read_signal_strength(struct dvb_frontend* fe, u16 *signal_strength)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
@@ -443,8 +414,7 @@ static int mt312_read_signal_strength(struct dvb_frontend *fe,
u16 agc;
s16 err_db;
- ret = mt312_read(state, AGC_H, buf, sizeof(buf));
- if (ret < 0)
+ if ((ret = mt312_read(state, AGC_H, buf, sizeof(buf))) < 0)
return ret;
agc = (buf[0] << 6) | (buf[1] >> 2);
@@ -452,19 +422,18 @@ static int mt312_read_signal_strength(struct dvb_frontend *fe,
*signal_strength = agc;
- dprintk("agc=%08x err_db=%hd\n", agc, err_db);
+ dprintk(KERN_DEBUG "agc=%08x err_db=%hd\n", agc, err_db);
return 0;
}
-static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr)
+static int mt312_read_snr(struct dvb_frontend* fe, u16 *snr)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[2];
- ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf));
- if (ret < 0)
+ if ((ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf))) < 0)
return ret;
*snr = 0xFFFF - ((((buf[0] & 0x7f) << 8) | buf[1]) << 1);
@@ -472,14 +441,13 @@ static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr)
return 0;
}
-static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc)
+static int mt312_read_ucblocks(struct dvb_frontend* fe, u32 *ubc)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[2];
- ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf));
- if (ret < 0)
+ if ((ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf))) < 0)
return ret;
*ubc = (buf[0] << 8) | buf[1];
@@ -487,7 +455,7 @@ static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc)
return 0;
}
-static int mt312_set_frontend(struct dvb_frontend *fe,
+static int mt312_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
{
struct mt312_state *state = fe->demodulator_priv;
@@ -523,28 +491,24 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
switch (state->id) {
case ID_VP310:
- /* For now we will do this only for the VP310.
- * It should be better for the mt312 as well,
- * but tuning will be slower. ACCJr 09/29/03
- */
+ // For now we will do this only for the VP310.
+ // It should be better for the mt312 as well, but tunning will be slower. ACCJr 09/29/03
ret = mt312_readreg(state, CONFIG, &config_val);
if (ret < 0)
return ret;
- if (p->u.qpsk.symbol_rate >= 30000000) {
- /* Note that 30MS/s should use 90MHz */
- if ((config_val & 0x0c) == 0x08) {
- /* We are running 60MHz */
+ if (p->u.qpsk.symbol_rate >= 30000000) //Note that 30MS/s should use 90MHz
+ {
+ if ((config_val & 0x0c) == 0x08) { //We are running 60MHz
state->frequency = 90;
- ret = mt312_initfe(fe);
- if (ret < 0)
+ if ((ret = mt312_initfe(fe)) < 0)
return ret;
}
- } else {
- if ((config_val & 0x0c) == 0x0C) {
- /* We are running 90MHz */
+ }
+ else
+ {
+ if ((config_val & 0x0c) == 0x0C) { //We are running 90MHz
state->frequency = 60;
- ret = mt312_initfe(fe);
- if (ret < 0)
+ if ((ret = mt312_initfe(fe)) < 0)
return ret;
}
}
@@ -559,8 +523,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, p);
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
/* sr = (u16)(sr * 256.0 / 1000000.0) */
@@ -582,8 +545,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
/* GO */
buf[4] = 0x01;
- ret = mt312_write(state, SYM_RATE_H, buf, sizeof(buf));
- if (ret < 0)
+ if ((ret = mt312_write(state, SYM_RATE_H, buf, sizeof(buf))) < 0)
return ret;
mt312_reset(state, 0);
@@ -591,30 +553,27 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
return 0;
}
-static int mt312_get_frontend(struct dvb_frontend *fe,
+static int mt312_get_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
- ret = mt312_get_inversion(state, &p->inversion);
- if (ret < 0)
+ if ((ret = mt312_get_inversion(state, &p->inversion)) < 0)
return ret;
- ret = mt312_get_symbol_rate(state, &p->u.qpsk.symbol_rate);
- if (ret < 0)
+ if ((ret = mt312_get_symbol_rate(state, &p->u.qpsk.symbol_rate)) < 0)
return ret;
- ret = mt312_get_code_rate(state, &p->u.qpsk.fec_inner);
- if (ret < 0)
+ if ((ret = mt312_get_code_rate(state, &p->u.qpsk.fec_inner)) < 0)
return ret;
return 0;
}
-static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+static int mt312_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
- struct mt312_state *state = fe->demodulator_priv;
+ struct mt312_state* state = fe->demodulator_priv;
if (enable) {
return mt312_writereg(state, GPP_CTRL, 0x40);
@@ -623,31 +582,27 @@ static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
}
}
-static int mt312_sleep(struct dvb_frontend *fe)
+static int mt312_sleep(struct dvb_frontend* fe)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 config;
/* reset all registers to defaults */
- ret = mt312_reset(state, 1);
- if (ret < 0)
+ if ((ret = mt312_reset(state, 1)) < 0)
return ret;
- ret = mt312_readreg(state, CONFIG, &config);
- if (ret < 0)
+ if ((ret = mt312_readreg(state, CONFIG, &config)) < 0)
return ret;
/* enter standby */
- ret = mt312_writereg(state, CONFIG, config & 0x7f);
- if (ret < 0)
+ if ((ret = mt312_writereg(state, CONFIG, config & 0x7f)) < 0)
return ret;
return 0;
}
-static int mt312_get_tune_settings(struct dvb_frontend *fe,
- struct dvb_frontend_tune_settings *fesettings)
+static int mt312_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
{
fesettings->min_delay_ms = 50;
fesettings->step_size = 0;
@@ -655,9 +610,9 @@ static int mt312_get_tune_settings(struct dvb_frontend *fe,
return 0;
}
-static void mt312_release(struct dvb_frontend *fe)
+static void mt312_release(struct dvb_frontend* fe)
{
- struct mt312_state *state = fe->demodulator_priv;
+ struct mt312_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -700,10 +655,10 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
.set_voltage = mt312_set_voltage,
};
-struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
- struct i2c_adapter *i2c)
+struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
+ struct i2c_adapter* i2c)
{
- struct mt312_state *state = NULL;
+ struct mt312_state* state = NULL;
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
@@ -719,8 +674,7 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
goto error;
/* create dvb_frontend */
- memcpy(&state->frontend.ops, &vp310_mt312_ops,
- sizeof(struct dvb_frontend_ops));
+ memcpy(&state->frontend.ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
switch (state->id) {
@@ -733,8 +687,7 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
state->frequency = 60;
break;
default:
- printk(KERN_WARNING "Only Zarlink VP310/MT312"
- " are supported chips.\n");
+ printk (KERN_WARNING "Only Zarlink VP310/MT312 are supported chips.\n");
goto error;
}
@@ -744,7 +697,6 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
kfree(state);
return NULL;
}
-EXPORT_SYMBOL(vp310_mt312_attach);
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
@@ -753,3 +705,4 @@ MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver");
MODULE_AUTHOR("Andreas Oberritter ");
MODULE_LICENSE("GPL");
+EXPORT_SYMBOL(vp310_mt312_attach);
diff --git a/trunk/drivers/media/dvb/frontends/mt312.h b/trunk/drivers/media/dvb/frontends/mt312.h
index f17cb93ba9ba..cf9a1505ad4b 100644
--- a/trunk/drivers/media/dvb/frontends/mt312.h
+++ b/trunk/drivers/media/dvb/frontends/mt312.h
@@ -28,21 +28,22 @@
#include
-struct mt312_config {
+struct mt312_config
+{
/* the demodulator's i2c address */
u8 demod_address;
};
#if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE))
-struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
- struct i2c_adapter *i2c);
+struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
+ struct i2c_adapter* i2c);
#else
-static inline struct dvb_frontend *vp310_mt312_attach(
- const struct mt312_config *config, struct i2c_adapter *i2c)
+static inline struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
+ struct i2c_adapter* i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
return NULL;
}
-#endif /* CONFIG_DVB_MT312 */
+#endif // CONFIG_DVB_MT312
-#endif /* MT312_H */
+#endif // MT312_H
diff --git a/trunk/drivers/media/dvb/frontends/mt352.c b/trunk/drivers/media/dvb/frontends/mt352.c
index 7cd190b6f015..5dd9b731f6f2 100644
--- a/trunk/drivers/media/dvb/frontends/mt352.c
+++ b/trunk/drivers/media/dvb/frontends/mt352.c
@@ -152,13 +152,7 @@ static void mt352_calc_input_freq(struct mt352_state* state,
if (state->config.if2)
if2 = state->config.if2;
- if (adc_clock >= if2 * 2)
- ife = if2;
- else {
- ife = adc_clock - (if2 % adc_clock);
- if (ife > adc_clock / 2)
- ife = adc_clock - ife;
- }
+ ife = (2*adc_clock - if2);
value = -16374 * ife / adc_clock;
dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
__FUNCTION__, if2, ife, adc_clock, value, value & 0x3fff);
diff --git a/trunk/drivers/media/dvb/frontends/or51132.c b/trunk/drivers/media/dvb/frontends/or51132.c
index 1d2d28ce823d..b314a1f2deed 100644
--- a/trunk/drivers/media/dvb/frontends/or51132.c
+++ b/trunk/drivers/media/dvb/frontends/or51132.c
@@ -564,7 +564,7 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config,
/* Allocate memory for the internal state */
state = kmalloc(sizeof(struct or51132_state), GFP_KERNEL);
if (state == NULL)
- return NULL;
+ goto error;
/* Setup the state */
state->config = config;
@@ -576,6 +576,10 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config,
memcpy(&state->frontend.ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
}
static struct dvb_frontend_ops or51132_ops = {
diff --git a/trunk/drivers/media/dvb/frontends/or51211.c b/trunk/drivers/media/dvb/frontends/or51211.c
index 6a6b0d727c6f..f02bd9445955 100644
--- a/trunk/drivers/media/dvb/frontends/or51211.c
+++ b/trunk/drivers/media/dvb/frontends/or51211.c
@@ -529,7 +529,7 @@ struct dvb_frontend* or51211_attach(const struct or51211_config* config,
/* Allocate memory for the internal state */
state = kmalloc(sizeof(struct or51211_state), GFP_KERNEL);
if (state == NULL)
- return NULL;
+ goto error;
/* Setup the state */
state->config = config;
@@ -541,6 +541,10 @@ struct dvb_frontend* or51211_attach(const struct or51211_config* config,
memcpy(&state->frontend.ops, &or51211_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
}
static struct dvb_frontend_ops or51211_ops = {
diff --git a/trunk/drivers/media/dvb/frontends/s5h1409.c b/trunk/drivers/media/dvb/frontends/s5h1409.c
index 819433485d3b..562d9208857a 100644
--- a/trunk/drivers/media/dvb/frontends/s5h1409.c
+++ b/trunk/drivers/media/dvb/frontends/s5h1409.c
@@ -42,7 +42,6 @@ struct s5h1409_state {
fe_modulation_t current_modulation;
u32 current_frequency;
- int if_freq;
u32 is_qam_locked;
u32 qam_state;
@@ -98,7 +97,7 @@ static struct init_tab {
{ 0xac, 0x1003, },
{ 0xad, 0x103f, },
{ 0xe2, 0x0100, },
- { 0xe3, 0x1000, },
+ { 0xe3, 0x0000, },
{ 0x28, 0x1010, },
{ 0xb1, 0x000e, },
};
@@ -349,32 +348,28 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
return 0;
}
-#define S5H1409_VSB_IF_FREQ 5380
-#define S5H1409_QAM_IF_FREQ state->config->qam_if
-
static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
{
struct s5h1409_state* state = fe->demodulator_priv;
+ int ret = 0;
dprintk("%s(%d KHz)\n", __FUNCTION__, KHz);
- switch (KHz) {
- case 4000:
- s5h1409_writereg(state, 0x87, 0x014b);
- s5h1409_writereg(state, 0x88, 0x0cb5);
- s5h1409_writereg(state, 0x89, 0x03e2);
- break;
- case 5380:
- case 44000:
- default:
+ if( (KHz == 44000) || (KHz == 5380) ) {
s5h1409_writereg(state, 0x87, 0x01be);
s5h1409_writereg(state, 0x88, 0x0436);
s5h1409_writereg(state, 0x89, 0x054d);
- break;
+ } else
+ if (KHz == 4000) {
+ s5h1409_writereg(state, 0x87, 0x014b);
+ s5h1409_writereg(state, 0x88, 0x0cb5);
+ s5h1409_writereg(state, 0x89, 0x03e2);
+ } else {
+ printk("%s() Invalid arg = %d KHz\n", __FUNCTION__, KHz);
+ ret = -1;
}
- state->if_freq = KHz;
- return 0;
+ return ret;
}
static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
@@ -399,15 +394,11 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
switch(m) {
case VSB_8:
dprintk("%s() VSB_8\n", __FUNCTION__);
- if (state->if_freq != S5H1409_VSB_IF_FREQ)
- s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ);
s5h1409_writereg(state, 0xf4, 0);
break;
case QAM_64:
case QAM_256:
dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__);
- if (state->if_freq != S5H1409_QAM_IF_FREQ)
- s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ);
s5h1409_writereg(state, 0xf4, 1);
s5h1409_writereg(state, 0x85, 0x110);
break;
@@ -441,11 +432,9 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
dprintk("%s(%d)\n", __FUNCTION__, enable);
if (enable)
- return s5h1409_writereg(state, 0xe3,
- s5h1409_readreg(state, 0xe3) | 0x1100);
+ return s5h1409_writereg(state, 0xe3, 0x1100);
else
- return s5h1409_writereg(state, 0xe3,
- s5h1409_readreg(state, 0xe3) & 0xeeff);
+ return s5h1409_writereg(state, 0xe3, 0x1000);
}
static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
@@ -515,15 +504,13 @@ static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe)
s5h1409_writereg(state, 0x96, 0x20);
s5h1409_writereg(state, 0xad,
( ((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)) );
- s5h1409_writereg(state, 0xab,
- s5h1409_readreg(state, 0xab) & 0xeffe);
+ s5h1409_writereg(state, 0xab, 0x1100);
}
} else {
if (state->qam_state != 1) {
state->qam_state = 1;
s5h1409_writereg(state, 0x96, 0x08);
- s5h1409_writereg(state, 0xab,
- s5h1409_readreg(state, 0xab) | 0x1001);
+ s5h1409_writereg(state, 0xab, 0x1101);
}
}
}
@@ -560,36 +547,6 @@ static int s5h1409_set_frontend (struct dvb_frontend* fe,
return 0;
}
-static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
-{
- struct s5h1409_state *state = fe->demodulator_priv;
- u16 val;
-
- dprintk("%s(%d)\n", __FUNCTION__, mode);
-
- val = s5h1409_readreg(state, 0xac) & 0xcfff;
- switch (mode) {
- case S5H1409_MPEGTIMING_CONTINOUS_INVERTING_CLOCK:
- val |= 0x0000;
- break;
- case S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
- dprintk("%s(%d) Mode1 or Defaulting\n", __FUNCTION__, mode);
- val |= 0x1000;
- break;
- case S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
- val |= 0x2000;
- break;
- case S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK:
- val |= 0x3000;
- break;
- default:
- return -EINVAL;
- }
-
- /* Configure MPEG Signal Timing charactistics */
- return s5h1409_writereg(state, 0xac, val);
-}
-
/* Reset the demod hardware and reset all of the configuration registers
to a default state. */
static int s5h1409_init (struct dvb_frontend* fe)
@@ -609,16 +566,13 @@ static int s5h1409_init (struct dvb_frontend* fe)
state->current_modulation = VSB_8;
if (state->config->output_mode == S5H1409_SERIAL_OUTPUT)
- s5h1409_writereg(state, 0xab,
- s5h1409_readreg(state, 0xab) | 0x100); /* Serial */
+ s5h1409_writereg(state, 0xab, 0x100); /* Serial */
else
- s5h1409_writereg(state, 0xab,
- s5h1409_readreg(state, 0xab) & 0xfeff); /* Parallel */
+ s5h1409_writereg(state, 0xab, 0x0); /* Parallel */
s5h1409_set_spectralinversion(fe, state->config->inversion);
- s5h1409_set_if_freq(fe, state->if_freq);
+ s5h1409_set_if_freq(fe, state->config->if_freq);
s5h1409_set_gpio(fe, state->config->gpio);
- s5h1409_set_mpeg_timing(fe, state->config->mpeg_timing);
s5h1409_softreset(fe);
/* Note: Leaving the I2C gate closed. */
@@ -787,7 +741,6 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
struct i2c_adapter* i2c)
{
struct s5h1409_state* state = NULL;
- u16 reg;
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct s5h1409_state), GFP_KERNEL);
@@ -798,11 +751,9 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
state->config = config;
state->i2c = i2c;
state->current_modulation = 0;
- state->if_freq = S5H1409_VSB_IF_FREQ;
/* check if the demod exists */
- reg = s5h1409_readreg(state, 0x04);
- if ((reg != 0x0066) && (reg != 0x007f))
+ if (s5h1409_readreg(state, 0x04) != 0x0066)
goto error;
/* create dvb_frontend */
@@ -810,14 +761,8 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
- if (s5h1409_init(&state->frontend) != 0) {
- printk(KERN_ERR "%s: Failed to initialize correctly\n",
- __FUNCTION__);
- goto error;
- }
-
/* Note: Leaving the I2C gate open here. */
- s5h1409_i2c_gate_ctrl(&state->frontend, 1);
+ s5h1409_writereg(state, 0xf3, 1);
return &state->frontend;
diff --git a/trunk/drivers/media/dvb/frontends/s5h1409.h b/trunk/drivers/media/dvb/frontends/s5h1409.h
index f0bb13fe808b..20f9af1af445 100644
--- a/trunk/drivers/media/dvb/frontends/s5h1409.h
+++ b/trunk/drivers/media/dvb/frontends/s5h1409.h
@@ -39,8 +39,8 @@ struct s5h1409_config
#define S5H1409_GPIO_ON 1
u8 gpio;
- /* IF Freq for QAM in KHz, VSB is hardcoded to 5380 */
- u16 qam_if;
+ /* IF Freq in KHz */
+ u16 if_freq;
/* Spectral Inversion */
#define S5H1409_INVERSION_OFF 0
@@ -51,13 +51,6 @@ struct s5h1409_config
#define S5H1409_TUNERLOCKING 0
#define S5H1409_DEMODLOCKING 1
u8 status_mode;
-
- /* MPEG signal timing */
-#define S5H1409_MPEGTIMING_CONTINOUS_INVERTING_CLOCK 0
-#define S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK 1
-#define S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK 2
-#define S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
- u16 mpeg_timing;
};
#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) && defined(MODULE))
diff --git a/trunk/drivers/media/dvb/frontends/tda18271-common.c b/trunk/drivers/media/dvb/frontends/tda18271-common.c
deleted file mode 100644
index cebb6b90b7e0..000000000000
--- a/trunk/drivers/media/dvb/frontends/tda18271-common.c
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- tda18271-common.c - driver for the Philips / NXP TDA18271 silicon tuner
-
- Copyright (C) 2007, 2008 Michael Krufky
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "tda18271-priv.h"
-
-static int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- enum tda18271_i2c_gate gate;
- int ret = 0;
-
- switch (priv->gate) {
- case TDA18271_GATE_DIGITAL:
- case TDA18271_GATE_ANALOG:
- gate = priv->gate;
- break;
- case TDA18271_GATE_AUTO:
- default:
- switch (priv->mode) {
- case TDA18271_DIGITAL:
- gate = TDA18271_GATE_DIGITAL;
- break;
- case TDA18271_ANALOG:
- default:
- gate = TDA18271_GATE_ANALOG;
- break;
- }
- }
-
- switch (gate) {
- case TDA18271_GATE_ANALOG:
- if (fe->ops.analog_ops.i2c_gate_ctrl)
- ret = fe->ops.analog_ops.i2c_gate_ctrl(fe, enable);
- break;
- case TDA18271_GATE_DIGITAL:
- if (fe->ops.i2c_gate_ctrl)
- ret = fe->ops.i2c_gate_ctrl(fe, enable);
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-};
-
-/*---------------------------------------------------------------------*/
-
-static void tda18271_dump_regs(struct dvb_frontend *fe, int extended)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
-
- tda_reg("=== TDA18271 REG DUMP ===\n");
- tda_reg("ID_BYTE = 0x%02x\n", 0xff & regs[R_ID]);
- tda_reg("THERMO_BYTE = 0x%02x\n", 0xff & regs[R_TM]);
- tda_reg("POWER_LEVEL_BYTE = 0x%02x\n", 0xff & regs[R_PL]);
- tda_reg("EASY_PROG_BYTE_1 = 0x%02x\n", 0xff & regs[R_EP1]);
- tda_reg("EASY_PROG_BYTE_2 = 0x%02x\n", 0xff & regs[R_EP2]);
- tda_reg("EASY_PROG_BYTE_3 = 0x%02x\n", 0xff & regs[R_EP3]);
- tda_reg("EASY_PROG_BYTE_4 = 0x%02x\n", 0xff & regs[R_EP4]);
- tda_reg("EASY_PROG_BYTE_5 = 0x%02x\n", 0xff & regs[R_EP5]);
- tda_reg("CAL_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_CPD]);
- tda_reg("CAL_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_CD1]);
- tda_reg("CAL_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_CD2]);
- tda_reg("CAL_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_CD3]);
- tda_reg("MAIN_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_MPD]);
- tda_reg("MAIN_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_MD1]);
- tda_reg("MAIN_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_MD2]);
- tda_reg("MAIN_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_MD3]);
-
- /* only dump extended regs if DBG_ADV is set */
- if (!(tda18271_debug & DBG_ADV))
- return;
-
- /* W indicates write-only registers.
- * Register dump for write-only registers shows last value written. */
-
- tda_reg("EXTENDED_BYTE_1 = 0x%02x\n", 0xff & regs[R_EB1]);
- tda_reg("EXTENDED_BYTE_2 = 0x%02x\n", 0xff & regs[R_EB2]);
- tda_reg("EXTENDED_BYTE_3 = 0x%02x\n", 0xff & regs[R_EB3]);
- tda_reg("EXTENDED_BYTE_4 = 0x%02x\n", 0xff & regs[R_EB4]);
- tda_reg("EXTENDED_BYTE_5 = 0x%02x\n", 0xff & regs[R_EB5]);
- tda_reg("EXTENDED_BYTE_6 = 0x%02x\n", 0xff & regs[R_EB6]);
- tda_reg("EXTENDED_BYTE_7 = 0x%02x\n", 0xff & regs[R_EB7]);
- tda_reg("EXTENDED_BYTE_8 = 0x%02x\n", 0xff & regs[R_EB8]);
- tda_reg("EXTENDED_BYTE_9 W = 0x%02x\n", 0xff & regs[R_EB9]);
- tda_reg("EXTENDED_BYTE_10 = 0x%02x\n", 0xff & regs[R_EB10]);
- tda_reg("EXTENDED_BYTE_11 = 0x%02x\n", 0xff & regs[R_EB11]);
- tda_reg("EXTENDED_BYTE_12 = 0x%02x\n", 0xff & regs[R_EB12]);
- tda_reg("EXTENDED_BYTE_13 = 0x%02x\n", 0xff & regs[R_EB13]);
- tda_reg("EXTENDED_BYTE_14 = 0x%02x\n", 0xff & regs[R_EB14]);
- tda_reg("EXTENDED_BYTE_15 = 0x%02x\n", 0xff & regs[R_EB15]);
- tda_reg("EXTENDED_BYTE_16 W = 0x%02x\n", 0xff & regs[R_EB16]);
- tda_reg("EXTENDED_BYTE_17 W = 0x%02x\n", 0xff & regs[R_EB17]);
- tda_reg("EXTENDED_BYTE_18 = 0x%02x\n", 0xff & regs[R_EB18]);
- tda_reg("EXTENDED_BYTE_19 W = 0x%02x\n", 0xff & regs[R_EB19]);
- tda_reg("EXTENDED_BYTE_20 W = 0x%02x\n", 0xff & regs[R_EB20]);
- tda_reg("EXTENDED_BYTE_21 = 0x%02x\n", 0xff & regs[R_EB21]);
- tda_reg("EXTENDED_BYTE_22 = 0x%02x\n", 0xff & regs[R_EB22]);
- tda_reg("EXTENDED_BYTE_23 = 0x%02x\n", 0xff & regs[R_EB23]);
-}
-
-int tda18271_read_regs(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- unsigned char buf = 0x00;
- int ret;
- struct i2c_msg msg[] = {
- { .addr = priv->i2c_addr, .flags = 0,
- .buf = &buf, .len = 1 },
- { .addr = priv->i2c_addr, .flags = I2C_M_RD,
- .buf = regs, .len = 16 }
- };
-
- tda18271_i2c_gate_ctrl(fe, 1);
-
- /* read all registers */
- ret = i2c_transfer(priv->i2c_adap, msg, 2);
-
- tda18271_i2c_gate_ctrl(fe, 0);
-
- if (ret != 2)
- tda_err("ERROR: i2c_transfer returned: %d\n", ret);
-
- if (tda18271_debug & DBG_REG)
- tda18271_dump_regs(fe, 0);
-
- return (ret == 2 ? 0 : ret);
-}
-
-int tda18271_read_extended(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- unsigned char regdump[TDA18271_NUM_REGS];
- unsigned char buf = 0x00;
- int ret, i;
- struct i2c_msg msg[] = {
- { .addr = priv->i2c_addr, .flags = 0,
- .buf = &buf, .len = 1 },
- { .addr = priv->i2c_addr, .flags = I2C_M_RD,
- .buf = regdump, .len = TDA18271_NUM_REGS }
- };
-
- tda18271_i2c_gate_ctrl(fe, 1);
-
- /* read all registers */
- ret = i2c_transfer(priv->i2c_adap, msg, 2);
-
- tda18271_i2c_gate_ctrl(fe, 0);
-
- if (ret != 2)
- tda_err("ERROR: i2c_transfer returned: %d\n", ret);
-
- for (i = 0; i <= TDA18271_NUM_REGS; i++) {
- /* don't update write-only registers */
- if ((i != R_EB9) &&
- (i != R_EB16) &&
- (i != R_EB17) &&
- (i != R_EB19) &&
- (i != R_EB20))
- regs[i] = regdump[i];
- }
-
- if (tda18271_debug & DBG_REG)
- tda18271_dump_regs(fe, 1);
-
- return (ret == 2 ? 0 : ret);
-}
-
-int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- unsigned char buf[TDA18271_NUM_REGS + 1];
- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
- .buf = buf, .len = len + 1 };
- int i, ret;
-
- BUG_ON((len == 0) || (idx + len > sizeof(buf)));
-
- buf[0] = idx;
- for (i = 1; i <= len; i++)
- buf[i] = regs[idx - 1 + i];
-
- tda18271_i2c_gate_ctrl(fe, 1);
-
- /* write registers */
- ret = i2c_transfer(priv->i2c_adap, &msg, 1);
-
- tda18271_i2c_gate_ctrl(fe, 0);
-
- if (ret != 1)
- tda_err("ERROR: i2c_transfer returned: %d\n", ret);
-
- return (ret == 1 ? 0 : ret);
-}
-
-/*---------------------------------------------------------------------*/
-
-int tda18271_init_regs(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
-
- tda_dbg("initializing registers for device @ %d-%04x\n",
- i2c_adapter_id(priv->i2c_adap), priv->i2c_addr);
-
- /* initialize registers */
- switch (priv->id) {
- case TDA18271HDC1:
- regs[R_ID] = 0x83;
- break;
- case TDA18271HDC2:
- regs[R_ID] = 0x84;
- break;
- };
-
- regs[R_TM] = 0x08;
- regs[R_PL] = 0x80;
- regs[R_EP1] = 0xc6;
- regs[R_EP2] = 0xdf;
- regs[R_EP3] = 0x16;
- regs[R_EP4] = 0x60;
- regs[R_EP5] = 0x80;
- regs[R_CPD] = 0x80;
- regs[R_CD1] = 0x00;
- regs[R_CD2] = 0x00;
- regs[R_CD3] = 0x00;
- regs[R_MPD] = 0x00;
- regs[R_MD1] = 0x00;
- regs[R_MD2] = 0x00;
- regs[R_MD3] = 0x00;
-
- switch (priv->id) {
- case TDA18271HDC1:
- regs[R_EB1] = 0xff;
- break;
- case TDA18271HDC2:
- regs[R_EB1] = 0xfc;
- break;
- };
-
- regs[R_EB2] = 0x01;
- regs[R_EB3] = 0x84;
- regs[R_EB4] = 0x41;
- regs[R_EB5] = 0x01;
- regs[R_EB6] = 0x84;
- regs[R_EB7] = 0x40;
- regs[R_EB8] = 0x07;
- regs[R_EB9] = 0x00;
- regs[R_EB10] = 0x00;
- regs[R_EB11] = 0x96;
-
- switch (priv->id) {
- case TDA18271HDC1:
- regs[R_EB12] = 0x0f;
- break;
- case TDA18271HDC2:
- regs[R_EB12] = 0x33;
- break;
- };
-
- regs[R_EB13] = 0xc1;
- regs[R_EB14] = 0x00;
- regs[R_EB15] = 0x8f;
- regs[R_EB16] = 0x00;
- regs[R_EB17] = 0x00;
-
- switch (priv->id) {
- case TDA18271HDC1:
- regs[R_EB18] = 0x00;
- break;
- case TDA18271HDC2:
- regs[R_EB18] = 0x8c;
- break;
- };
-
- regs[R_EB19] = 0x00;
- regs[R_EB20] = 0x20;
-
- switch (priv->id) {
- case TDA18271HDC1:
- regs[R_EB21] = 0x33;
- break;
- case TDA18271HDC2:
- regs[R_EB21] = 0xb3;
- break;
- };
-
- regs[R_EB22] = 0x48;
- regs[R_EB23] = 0xb0;
-
- tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
-
- /* setup agc1 gain */
- regs[R_EB17] = 0x00;
- tda18271_write_regs(fe, R_EB17, 1);
- regs[R_EB17] = 0x03;
- tda18271_write_regs(fe, R_EB17, 1);
- regs[R_EB17] = 0x43;
- tda18271_write_regs(fe, R_EB17, 1);
- regs[R_EB17] = 0x4c;
- tda18271_write_regs(fe, R_EB17, 1);
-
- /* setup agc2 gain */
- if ((priv->id) == TDA18271HDC1) {
- regs[R_EB20] = 0xa0;
- tda18271_write_regs(fe, R_EB20, 1);
- regs[R_EB20] = 0xa7;
- tda18271_write_regs(fe, R_EB20, 1);
- regs[R_EB20] = 0xe7;
- tda18271_write_regs(fe, R_EB20, 1);
- regs[R_EB20] = 0xec;
- tda18271_write_regs(fe, R_EB20, 1);
- }
-
- /* image rejection calibration */
-
- /* low-band */
- regs[R_EP3] = 0x1f;
- regs[R_EP4] = 0x66;
- regs[R_EP5] = 0x81;
- regs[R_CPD] = 0xcc;
- regs[R_CD1] = 0x6c;
- regs[R_CD2] = 0x00;
- regs[R_CD3] = 0x00;
- regs[R_MPD] = 0xcd;
- regs[R_MD1] = 0x77;
- regs[R_MD2] = 0x08;
- regs[R_MD3] = 0x00;
-
- switch (priv->id) {
- case TDA18271HDC1:
- tda18271_write_regs(fe, R_EP3, 11);
- break;
- case TDA18271HDC2:
- tda18271_write_regs(fe, R_EP3, 12);
- break;
- };
-
- if ((priv->id) == TDA18271HDC2) {
- /* main pll cp source on */
- regs[R_EB4] = 0x61;
- tda18271_write_regs(fe, R_EB4, 1);
- msleep(1);
-
- /* main pll cp source off */
- regs[R_EB4] = 0x41;
- tda18271_write_regs(fe, R_EB4, 1);
- }
-
- msleep(5); /* pll locking */
-
- /* launch detector */
- tda18271_write_regs(fe, R_EP1, 1);
- msleep(5); /* wanted low measurement */
-
- regs[R_EP5] = 0x85;
- regs[R_CPD] = 0xcb;
- regs[R_CD1] = 0x66;
- regs[R_CD2] = 0x70;
-
- tda18271_write_regs(fe, R_EP3, 7);
- msleep(5); /* pll locking */
-
- /* launch optimization algorithm */
- tda18271_write_regs(fe, R_EP2, 1);
- msleep(30); /* image low optimization completion */
-
- /* mid-band */
- regs[R_EP5] = 0x82;
- regs[R_CPD] = 0xa8;
- regs[R_CD2] = 0x00;
- regs[R_MPD] = 0xa9;
- regs[R_MD1] = 0x73;
- regs[R_MD2] = 0x1a;
-
- tda18271_write_regs(fe, R_EP3, 11);
- msleep(5); /* pll locking */
-
- tda18271_write_regs(fe, R_EP1, 1);
- msleep(5); /* wanted mid measurement */
-
- regs[R_EP5] = 0x86;
- regs[R_CPD] = 0xa8;
- regs[R_CD1] = 0x66;
- regs[R_CD2] = 0xa0;
-
- tda18271_write_regs(fe, R_EP3, 7);
- msleep(5); /* pll locking */
-
- /* launch optimization algorithm */
- tda18271_write_regs(fe, R_EP2, 1);
- msleep(30); /* image mid optimization completion */
-
- /* high-band */
- regs[R_EP5] = 0x83;
- regs[R_CPD] = 0x98;
- regs[R_CD1] = 0x65;
- regs[R_CD2] = 0x00;
- regs[R_MPD] = 0x99;
- regs[R_MD1] = 0x71;
- regs[R_MD2] = 0xcd;
-
- tda18271_write_regs(fe, R_EP3, 11);
- msleep(5); /* pll locking */
-
- /* launch detector */
- tda18271_write_regs(fe, R_EP1, 1);
- msleep(5); /* wanted high measurement */
-
- regs[R_EP5] = 0x87;
- regs[R_CD1] = 0x65;
- regs[R_CD2] = 0x50;
-
- tda18271_write_regs(fe, R_EP3, 7);
- msleep(5); /* pll locking */
-
- /* launch optimization algorithm */
- tda18271_write_regs(fe, R_EP2, 1);
- msleep(30); /* image high optimization completion */
-
- /* return to normal mode */
- regs[R_EP4] = 0x64;
- tda18271_write_regs(fe, R_EP4, 1);
-
- /* synchronize */
- tda18271_write_regs(fe, R_EP1, 1);
-
- return 0;
-}
-
-/*---------------------------------------------------------------------*/
-
-/*
- * Standby modes, EP3 [7:5]
- *
- * | SM || SM_LT || SM_XT || mode description
- * |=====\\=======\\=======\\===================================
- * | 0 || 0 || 0 || normal mode
- * |-----||-------||-------||-----------------------------------
- * | || || || standby mode w/ slave tuner output
- * | 1 || 0 || 0 || & loop thru & xtal oscillator on
- * |-----||-------||-------||-----------------------------------
- * | 1 || 1 || 0 || standby mode w/ xtal oscillator on
- * |-----||-------||-------||-----------------------------------
- * | 1 || 1 || 1 || power off
- *
- */
-
-int tda18271_set_standby_mode(struct dvb_frontend *fe,
- int sm, int sm_lt, int sm_xt)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
-
- tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt);
-
- regs[R_EP3] &= ~0xe0; /* clear sm, sm_lt, sm_xt */
- regs[R_EP3] |= sm ? (1 << 7) : 0 |
- sm_lt ? (1 << 6) : 0 |
- sm_xt ? (1 << 5) : 0;
-
- tda18271_write_regs(fe, R_EP3, 1);
-
- return 0;
-}
-
-/*---------------------------------------------------------------------*/
-
-int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq)
-{
- /* sets main post divider & divider bytes, but does not write them */
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- u8 d, pd;
- u32 div;
-
- int ret = tda18271_lookup_pll_map(fe, MAIN_PLL, &freq, &pd, &d);
- if (ret < 0)
- goto fail;
-
- regs[R_MPD] = (0x77 & pd);
-
- switch (priv->mode) {
- case TDA18271_ANALOG:
- regs[R_MPD] &= ~0x08;
- break;
- case TDA18271_DIGITAL:
- regs[R_MPD] |= 0x08;
- break;
- }
-
- div = ((d * (freq / 1000)) << 7) / 125;
-
- regs[R_MD1] = 0x7f & (div >> 16);
- regs[R_MD2] = 0xff & (div >> 8);
- regs[R_MD3] = 0xff & div;
-fail:
- return ret;
-}
-
-int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq)
-{
- /* sets cal post divider & divider bytes, but does not write them */
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- u8 d, pd;
- u32 div;
-
- int ret = tda18271_lookup_pll_map(fe, CAL_PLL, &freq, &pd, &d);
- if (ret < 0)
- goto fail;
-
- regs[R_CPD] = pd;
-
- div = ((d * (freq / 1000)) << 7) / 125;
-
- regs[R_CD1] = 0x7f & (div >> 16);
- regs[R_CD2] = 0xff & (div >> 8);
- regs[R_CD3] = 0xff & div;
-fail:
- return ret;
-}
-
-/*---------------------------------------------------------------------*/
-
-int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq)
-{
- /* sets bp filter bits, but does not write them */
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- u8 val;
-
- int ret = tda18271_lookup_map(fe, BP_FILTER, freq, &val);
- if (ret < 0)
- goto fail;
-
- regs[R_EP1] &= ~0x07; /* clear bp filter bits */
- regs[R_EP1] |= (0x07 & val);
-fail:
- return ret;
-}
-
-int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq)
-{
- /* sets K & M bits, but does not write them */
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- u8 val;
-
- int ret = tda18271_lookup_map(fe, RF_CAL_KMCO, freq, &val);
- if (ret < 0)
- goto fail;
-
- regs[R_EB13] &= ~0x7c; /* clear k & m bits */
- regs[R_EB13] |= (0x7c & val);
-fail:
- return ret;
-}
-
-int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq)
-{
- /* sets rf band bits, but does not write them */
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- u8 val;
-
- int ret = tda18271_lookup_map(fe, RF_BAND, freq, &val);
- if (ret < 0)
- goto fail;
-
- regs[R_EP2] &= ~0xe0; /* clear rf band bits */
- regs[R_EP2] |= (0xe0 & (val << 5));
-fail:
- return ret;
-}
-
-int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq)
-{
- /* sets gain taper bits, but does not write them */
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- u8 val;
-
- int ret = tda18271_lookup_map(fe, GAIN_TAPER, freq, &val);
- if (ret < 0)
- goto fail;
-
- regs[R_EP2] &= ~0x1f; /* clear gain taper bits */
- regs[R_EP2] |= (0x1f & val);
-fail:
- return ret;
-}
-
-int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq)
-{
- /* sets IR Meas bits, but does not write them */
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- u8 val;
-
- int ret = tda18271_lookup_map(fe, IR_MEASURE, freq, &val);
- if (ret < 0)
- goto fail;
-
- regs[R_EP5] &= ~0x07;
- regs[R_EP5] |= (0x07 & val);
-fail:
- return ret;
-}
-
-int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq)
-{
- /* sets rf cal byte (RFC_Cprog), but does not write it */
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- u8 val;
-
- tda18271_lookup_map(fe, RF_CAL, freq, &val);
-
- regs[R_EB14] = val;
-
- return 0;
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/trunk/drivers/media/dvb/frontends/tda18271-fe.c b/trunk/drivers/media/dvb/frontends/tda18271-fe.c
deleted file mode 100644
index dfe72aaec380..000000000000
--- a/trunk/drivers/media/dvb/frontends/tda18271-fe.c
+++ /dev/null
@@ -1,1225 +0,0 @@
-/*
- tda18271-fe.c - driver for the Philips / NXP TDA18271 silicon tuner
-
- Copyright (C) 2007, 2008 Michael Krufky
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include
-#include
-#include "tda18271-priv.h"
-
-int tda18271_debug;
-module_param_named(debug, tda18271_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debug level "
- "(info=1, map=2, reg=4, adv=8, cal=16 (or-able))");
-
-static int tda18271_cal_on_startup;
-module_param_named(cal, tda18271_cal_on_startup, int, 0644);
-MODULE_PARM_DESC(cal, "perform RF tracking filter calibration on startup");
-
-static LIST_HEAD(tda18271_list);
-static DEFINE_MUTEX(tda18271_list_mutex);
-
-/*---------------------------------------------------------------------*/
-
-static int tda18271_ir_cal_init(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
-
- tda18271_read_regs(fe);
-
- /* test IR_CAL_OK to see if we need init */
- if ((regs[R_EP1] & 0x08) == 0)
- tda18271_init_regs(fe);
-
- return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int tda18271_channel_configuration(struct dvb_frontend *fe,
- u32 ifc, u32 freq, u32 bw, u8 std,
- int radio)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- u32 N;
-
- /* update TV broadcast parameters */
-
- /* set standard */
- regs[R_EP3] &= ~0x1f; /* clear std bits */
- regs[R_EP3] |= std;
-
- /* set cal mode to normal */
- regs[R_EP4] &= ~0x03;
-
- /* update IF output level & IF notch frequency */
- regs[R_EP4] &= ~0x1c; /* clear if level bits */
-
- switch (priv->mode) {
- case TDA18271_ANALOG:
- regs[R_MPD] &= ~0x80; /* IF notch = 0 */
- break;
- case TDA18271_DIGITAL:
- regs[R_EP4] |= 0x04; /* IF level = 1 */
- regs[R_MPD] |= 0x80; /* IF notch = 1 */
- break;
- }
-
- if (radio)
- regs[R_EP4] |= 0x80;
- else
- regs[R_EP4] &= ~0x80;
-
- /* update RF_TOP / IF_TOP */
- switch (priv->mode) {
- case TDA18271_ANALOG:
- regs[R_EB22] = 0x2c;
- break;
- case TDA18271_DIGITAL:
- regs[R_EB22] = 0x37;
- break;
- }
- tda18271_write_regs(fe, R_EB22, 1);
-
- /* --------------------------------------------------------------- */
-
- /* disable Power Level Indicator */
- regs[R_EP1] |= 0x40;
-
- /* frequency dependent parameters */
-
- tda18271_calc_ir_measure(fe, &freq);
-
- tda18271_calc_bp_filter(fe, &freq);
-
- tda18271_calc_rf_band(fe, &freq);
-
- tda18271_calc_gain_taper(fe, &freq);
-
- /* --------------------------------------------------------------- */
-
- /* dual tuner and agc1 extra configuration */
-
- /* main vco when Master, cal vco when slave */
- regs[R_EB1] |= 0x04; /* FIXME: assumes master */
-
- /* agc1 always active */
- regs[R_EB1] &= ~0x02;
-
- /* agc1 has priority on agc2 */
- regs[R_EB1] &= ~0x01;
-
- tda18271_write_regs(fe, R_EB1, 1);
-
- /* --------------------------------------------------------------- */
-
- N = freq + ifc;
-
- /* FIXME: assumes master */
- tda18271_calc_main_pll(fe, N);
- tda18271_write_regs(fe, R_MPD, 4);
-
- tda18271_write_regs(fe, R_TM, 7);
-
- /* main pll charge pump source */
- regs[R_EB4] |= 0x20;
- tda18271_write_regs(fe, R_EB4, 1);
-
- msleep(1);
-
- /* normal operation for the main pll */
- regs[R_EB4] &= ~0x20;
- tda18271_write_regs(fe, R_EB4, 1);
-
- msleep(5);
-
- return 0;
-}
-
-static int tda18271_read_thermometer(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- int tm;
-
- /* switch thermometer on */
- regs[R_TM] |= 0x10;
- tda18271_write_regs(fe, R_TM, 1);
-
- /* read thermometer info */
- tda18271_read_regs(fe);
-
- if ((((regs[R_TM] & 0x0f) == 0x00) && ((regs[R_TM] & 0x20) == 0x20)) ||
- (((regs[R_TM] & 0x0f) == 0x08) && ((regs[R_TM] & 0x20) == 0x00))) {
-
- if ((regs[R_TM] & 0x20) == 0x20)
- regs[R_TM] &= ~0x20;
- else
- regs[R_TM] |= 0x20;
-
- tda18271_write_regs(fe, R_TM, 1);
-
- msleep(10); /* temperature sensing */
-
- /* read thermometer info */
- tda18271_read_regs(fe);
- }
-
- tm = tda18271_lookup_thermometer(fe);
-
- /* switch thermometer off */
- regs[R_TM] &= ~0x10;
- tda18271_write_regs(fe, R_TM, 1);
-
- /* set CAL mode to normal */
- regs[R_EP4] &= ~0x03;
- tda18271_write_regs(fe, R_EP4, 1);
-
- return tm;
-}
-
-static int tda18271_rf_tracking_filters_correction(struct dvb_frontend *fe,
- u32 freq)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
- unsigned char *regs = priv->tda18271_regs;
- int tm_current, rfcal_comp, approx, i;
- u8 dc_over_dt, rf_tab;
-
- /* power up */
- tda18271_set_standby_mode(fe, 0, 0, 0);
-
- /* read die current temperature */
- tm_current = tda18271_read_thermometer(fe);
-
- /* frequency dependent parameters */
-
- tda18271_calc_rf_cal(fe, &freq);
- rf_tab = regs[R_EB14];
-
- i = tda18271_lookup_rf_band(fe, &freq, NULL);
- if (i < 0)
- return -EINVAL;
-
- if ((0 == map[i].rf3) || (freq / 1000 < map[i].rf2)) {
- approx = map[i].rf_a1 *
- (freq / 1000 - map[i].rf1) + map[i].rf_b1 + rf_tab;
- } else {
- approx = map[i].rf_a2 *
- (freq / 1000 - map[i].rf2) + map[i].rf_b2 + rf_tab;
- }
-
- if (approx < 0)
- approx = 0;
- if (approx > 255)
- approx = 255;
-
- tda18271_lookup_map(fe, RF_CAL_DC_OVER_DT, &freq, &dc_over_dt);
-
- /* calculate temperature compensation */
- rfcal_comp = dc_over_dt * (tm_current - priv->tm_rfcal);
-
- regs[R_EB14] = approx + rfcal_comp;
- tda18271_write_regs(fe, R_EB14, 1);
-
- return 0;
-}
-
-static int tda18271_por(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
-
- /* power up detector 1 */
- regs[R_EB12] &= ~0x20;
- tda18271_write_regs(fe, R_EB12, 1);
-
- regs[R_EB18] &= ~0x80; /* turn agc1 loop on */
- regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */
- tda18271_write_regs(fe, R_EB18, 1);
-
- regs[R_EB21] |= 0x03; /* set agc2_gain to -6 dB */
-
- /* POR mode */
- tda18271_set_standby_mode(fe, 1, 0, 0);
-
- /* disable 1.5 MHz low pass filter */
- regs[R_EB23] &= ~0x04; /* forcelp_fc2_en = 0 */
- regs[R_EB23] &= ~0x02; /* XXX: lp_fc[2] = 0 */
- tda18271_write_regs(fe, R_EB21, 3);
-
- return 0;
-}
-
-static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- u32 N;
-
- /* set CAL mode to normal */
- regs[R_EP4] &= ~0x03;
- tda18271_write_regs(fe, R_EP4, 1);
-
- /* switch off agc1 */
- regs[R_EP3] |= 0x40; /* sm_lt = 1 */
-
- regs[R_EB18] |= 0x03; /* set agc1_gain to 15 dB */
- tda18271_write_regs(fe, R_EB18, 1);
-
- /* frequency dependent parameters */
-
- tda18271_calc_bp_filter(fe, &freq);
- tda18271_calc_gain_taper(fe, &freq);
- tda18271_calc_rf_band(fe, &freq);
- tda18271_calc_km(fe, &freq);
-
- tda18271_write_regs(fe, R_EP1, 3);
- tda18271_write_regs(fe, R_EB13, 1);
-
- /* main pll charge pump source */
- regs[R_EB4] |= 0x20;
- tda18271_write_regs(fe, R_EB4, 1);
-
- /* cal pll charge pump source */
- regs[R_EB7] |= 0x20;
- tda18271_write_regs(fe, R_EB7, 1);
-
- /* force dcdc converter to 0 V */
- regs[R_EB14] = 0x00;
- tda18271_write_regs(fe, R_EB14, 1);
-
- /* disable plls lock */
- regs[R_EB20] &= ~0x20;
- tda18271_write_regs(fe, R_EB20, 1);
-
- /* set CAL mode to RF tracking filter calibration */
- regs[R_EP4] |= 0x03;
- tda18271_write_regs(fe, R_EP4, 2);
-
- /* --------------------------------------------------------------- */
-
- /* set the internal calibration signal */
- N = freq;
-
- tda18271_calc_main_pll(fe, N);
- tda18271_write_regs(fe, R_MPD, 4);
-
- /* downconvert internal calibration */
- N += 1000000;
-
- tda18271_calc_main_pll(fe, N);
- tda18271_write_regs(fe, R_MPD, 4);
-
- msleep(5);
-
- tda18271_write_regs(fe, R_EP2, 1);
- tda18271_write_regs(fe, R_EP1, 1);
- tda18271_write_regs(fe, R_EP2, 1);
- tda18271_write_regs(fe, R_EP1, 1);
-
- /* --------------------------------------------------------------- */
-
- /* normal operation for the main pll */
- regs[R_EB4] &= ~0x20;
- tda18271_write_regs(fe, R_EB4, 1);
-
- /* normal operation for the cal pll */
- regs[R_EB7] &= ~0x20;
- tda18271_write_regs(fe, R_EB7, 1);
-
- msleep(5); /* plls locking */
-
- /* launch the rf tracking filters calibration */
- regs[R_EB20] |= 0x20;
- tda18271_write_regs(fe, R_EB20, 1);
-
- msleep(60); /* calibration */
-
- /* --------------------------------------------------------------- */
-
- /* set CAL mode to normal */
- regs[R_EP4] &= ~0x03;
-
- /* switch on agc1 */
- regs[R_EP3] &= ~0x40; /* sm_lt = 0 */
-
- regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */
- tda18271_write_regs(fe, R_EB18, 1);
-
- tda18271_write_regs(fe, R_EP3, 2);
-
- /* synchronization */
- tda18271_write_regs(fe, R_EP1, 1);
-
- /* get calibration result */
- tda18271_read_extended(fe);
-
- return regs[R_EB14];
-}
-
-static int tda18271_powerscan(struct dvb_frontend *fe,
- u32 *freq_in, u32 *freq_out)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- int sgn, bcal, count, wait;
- u8 cid_target;
- u16 count_limit;
- u32 freq;
-
- freq = *freq_in;
-
- tda18271_calc_rf_band(fe, &freq);
- tda18271_calc_rf_cal(fe, &freq);
- tda18271_calc_gain_taper(fe, &freq);
- tda18271_lookup_cid_target(fe, &freq, &cid_target, &count_limit);
-
- tda18271_write_regs(fe, R_EP2, 1);
- tda18271_write_regs(fe, R_EB14, 1);
-
- /* downconvert frequency */
- freq += 1000000;
-
- tda18271_calc_main_pll(fe, freq);
- tda18271_write_regs(fe, R_MPD, 4);
-
- msleep(5); /* pll locking */
-
- /* detection mode */
- regs[R_EP4] &= ~0x03;
- regs[R_EP4] |= 0x01;
- tda18271_write_regs(fe, R_EP4, 1);
-
- /* launch power detection measurement */
- tda18271_write_regs(fe, R_EP2, 1);
-
- /* read power detection info, stored in EB10 */
- tda18271_read_extended(fe);
-
- /* algorithm initialization */
- sgn = 1;
- *freq_out = *freq_in;
- bcal = 0;
- count = 0;
- wait = false;
-
- while ((regs[R_EB10] & 0x3f) < cid_target) {
- /* downconvert updated freq to 1 MHz */
- freq = *freq_in + (sgn * count) + 1000000;
-
- tda18271_calc_main_pll(fe, freq);
- tda18271_write_regs(fe, R_MPD, 4);
-
- if (wait) {
- msleep(5); /* pll locking */
- wait = false;
- } else
- udelay(100); /* pll locking */
-
- /* launch power detection measurement */
- tda18271_write_regs(fe, R_EP2, 1);
-
- /* read power detection info, stored in EB10 */
- tda18271_read_extended(fe);
-
- count += 200;
-
- if (count < count_limit)
- continue;
-
- if (sgn <= 0)
- break;
-
- sgn = -1 * sgn;
- count = 200;
- wait = true;
- }
-
- if ((regs[R_EB10] & 0x3f) >= cid_target) {
- bcal = 1;
- *freq_out = freq - 1000000;
- } else
- bcal = 0;
-
- tda_cal("bcal = %d, freq_in = %d, freq_out = %d (freq = %d)\n",
- bcal, *freq_in, *freq_out, freq);
-
- return bcal;
-}
-
-static int tda18271_powerscan_init(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
-
- /* set standard to digital */
- regs[R_EP3] &= ~0x1f; /* clear std bits */
- regs[R_EP3] |= 0x12;
-
- /* set cal mode to normal */
- regs[R_EP4] &= ~0x03;
-
- /* update IF output level & IF notch frequency */
- regs[R_EP4] &= ~0x1c; /* clear if level bits */
-
- tda18271_write_regs(fe, R_EP3, 2);
-
- regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */
- tda18271_write_regs(fe, R_EB18, 1);
-
- regs[R_EB21] &= ~0x03; /* set agc2_gain to -15 dB */
-
- /* 1.5 MHz low pass filter */
- regs[R_EB23] |= 0x04; /* forcelp_fc2_en = 1 */
- regs[R_EB23] |= 0x02; /* lp_fc[2] = 1 */
-
- tda18271_write_regs(fe, R_EB21, 3);
-
- return 0;
-}
-
-static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
- unsigned char *regs = priv->tda18271_regs;
- int bcal, rf, i;
-#define RF1 0
-#define RF2 1
-#define RF3 2
- u32 rf_default[3];
- u32 rf_freq[3];
- u8 prog_cal[3];
- u8 prog_tab[3];
-
- i = tda18271_lookup_rf_band(fe, &freq, NULL);
-
- if (i < 0)
- return i;
-
- rf_default[RF1] = 1000 * map[i].rf1_def;
- rf_default[RF2] = 1000 * map[i].rf2_def;
- rf_default[RF3] = 1000 * map[i].rf3_def;
-
- for (rf = RF1; rf <= RF3; rf++) {
- if (0 == rf_default[rf])
- return 0;
- tda_cal("freq = %d, rf = %d\n", freq, rf);
-
- /* look for optimized calibration frequency */
- bcal = tda18271_powerscan(fe, &rf_default[rf], &rf_freq[rf]);
-
- tda18271_calc_rf_cal(fe, &rf_freq[rf]);
- prog_tab[rf] = regs[R_EB14];
-
- if (1 == bcal)
- prog_cal[rf] = tda18271_calibrate_rf(fe, rf_freq[rf]);
- else
- prog_cal[rf] = prog_tab[rf];
-
- switch (rf) {
- case RF1:
- map[i].rf_a1 = 0;
- map[i].rf_b1 = prog_cal[RF1] - prog_tab[RF1];
- map[i].rf1 = rf_freq[RF1] / 1000;
- break;
- case RF2:
- map[i].rf_a1 = (prog_cal[RF2] - prog_tab[RF2] -
- prog_cal[RF1] + prog_tab[RF1]) /
- ((rf_freq[RF2] - rf_freq[RF1]) / 1000);
- map[i].rf2 = rf_freq[RF2] / 1000;
- break;
- case RF3:
- map[i].rf_a2 = (prog_cal[RF3] - prog_tab[RF3] -
- prog_cal[RF2] + prog_tab[RF2]) /
- ((rf_freq[RF3] - rf_freq[RF2]) / 1000);
- map[i].rf_b2 = prog_cal[RF2] - prog_tab[RF2];
- map[i].rf3 = rf_freq[RF3] / 1000;
- break;
- default:
- BUG();
- }
- }
-
- return 0;
-}
-
-static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned int i;
-
- tda_info("tda18271: performing RF tracking filter calibration\n");
-
- /* wait for die temperature stabilization */
- msleep(200);
-
- tda18271_powerscan_init(fe);
-
- /* rf band calibration */
- for (i = 0; priv->rf_cal_state[i].rfmax != 0; i++)
- tda18271_rf_tracking_filters_init(fe, 1000 *
- priv->rf_cal_state[i].rfmax);
-
- priv->tm_rfcal = tda18271_read_thermometer(fe);
-
- return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int tda18271_rf_cal_init(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
-
- /* test RF_CAL_OK to see if we need init */
- if ((regs[R_EP1] & 0x10) == 0)
- priv->cal_initialized = false;
-
- if (priv->cal_initialized)
- return 0;
-
- tda18271_calc_rf_filter_curve(fe);
-
- tda18271_por(fe);
-
- tda_info("tda18271: RF tracking filter calibration complete\n");
-
- priv->cal_initialized = true;
-
- return 0;
-}
-
-static int tda18271_init(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
-
- mutex_lock(&priv->lock);
-
- /* power up */
- tda18271_set_standby_mode(fe, 0, 0, 0);
-
- /* initialization */
- tda18271_ir_cal_init(fe);
-
- if (priv->id == TDA18271HDC2)
- tda18271_rf_cal_init(fe);
-
- mutex_unlock(&priv->lock);
-
- return 0;
-}
-
-static int tda18271c2_tune(struct dvb_frontend *fe,
- u32 ifc, u32 freq, u32 bw, u8 std, int radio)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
-
- tda_dbg("freq = %d, ifc = %d\n", freq, ifc);
-
- tda18271_init(fe);
-
- mutex_lock(&priv->lock);
-
- tda18271_rf_tracking_filters_correction(fe, freq);
-
- tda18271_channel_configuration(fe, ifc, freq, bw, std, radio);
-
- mutex_unlock(&priv->lock);
-
- return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int tda18271c1_tune(struct dvb_frontend *fe,
- u32 ifc, u32 freq, u32 bw, u8 std, int radio)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- u32 N = 0;
-
- tda18271_init(fe);
-
- mutex_lock(&priv->lock);
-
- tda_dbg("freq = %d, ifc = %d\n", freq, ifc);
-
- /* RF tracking filter calibration */
-
- /* calculate bp filter */
- tda18271_calc_bp_filter(fe, &freq);
- tda18271_write_regs(fe, R_EP1, 1);
-
- regs[R_EB4] &= 0x07;
- regs[R_EB4] |= 0x60;
- tda18271_write_regs(fe, R_EB4, 1);
-
- regs[R_EB7] = 0x60;
- tda18271_write_regs(fe, R_EB7, 1);
-
- regs[R_EB14] = 0x00;
- tda18271_write_regs(fe, R_EB14, 1);
-
- regs[R_EB20] = 0xcc;
- tda18271_write_regs(fe, R_EB20, 1);
-
- /* set cal mode to RF tracking filter calibration */
- regs[R_EP4] |= 0x03;
-
- /* calculate cal pll */
-
- switch (priv->mode) {
- case TDA18271_ANALOG:
- N = freq - 1250000;
- break;
- case TDA18271_DIGITAL:
- N = freq + bw / 2;
- break;
- }
-
- tda18271_calc_cal_pll(fe, N);
-
- /* calculate main pll */
-
- switch (priv->mode) {
- case TDA18271_ANALOG:
- N = freq - 250000;
- break;
- case TDA18271_DIGITAL:
- N = freq + bw / 2 + 1000000;
- break;
- }
-
- tda18271_calc_main_pll(fe, N);
-
- tda18271_write_regs(fe, R_EP3, 11);
- msleep(5); /* RF tracking filter calibration initialization */
-
- /* search for K,M,CO for RF calibration */
- tda18271_calc_km(fe, &freq);
- tda18271_write_regs(fe, R_EB13, 1);
-
- /* search for rf band */
- tda18271_calc_rf_band(fe, &freq);
-
- /* search for gain taper */
- tda18271_calc_gain_taper(fe, &freq);
-
- tda18271_write_regs(fe, R_EP2, 1);
- tda18271_write_regs(fe, R_EP1, 1);
- tda18271_write_regs(fe, R_EP2, 1);
- tda18271_write_regs(fe, R_EP1, 1);
-
- regs[R_EB4] &= 0x07;
- regs[R_EB4] |= 0x40;
- tda18271_write_regs(fe, R_EB4, 1);
-
- regs[R_EB7] = 0x40;
- tda18271_write_regs(fe, R_EB7, 1);
- msleep(10);
-
- regs[R_EB20] = 0xec;
- tda18271_write_regs(fe, R_EB20, 1);
- msleep(60); /* RF tracking filter calibration completion */
-
- regs[R_EP4] &= ~0x03; /* set cal mode to normal */
- tda18271_write_regs(fe, R_EP4, 1);
-
- tda18271_write_regs(fe, R_EP1, 1);
-
- /* RF tracking filter correction for VHF_Low band */
- if (0 == tda18271_calc_rf_cal(fe, &freq))
- tda18271_write_regs(fe, R_EB14, 1);
-
- /* Channel Configuration */
-
- switch (priv->mode) {
- case TDA18271_ANALOG:
- regs[R_EB22] = 0x2c;
- break;
- case TDA18271_DIGITAL:
- regs[R_EB22] = 0x37;
- break;
- }
- tda18271_write_regs(fe, R_EB22, 1);
-
- regs[R_EP1] |= 0x40; /* set dis power level on */
-
- /* set standard */
- regs[R_EP3] &= ~0x1f; /* clear std bits */
-
- /* see table 22 */
- regs[R_EP3] |= std;
-
- regs[R_EP4] &= ~0x03; /* set cal mode to normal */
-
- regs[R_EP4] &= ~0x1c; /* clear if level bits */
- switch (priv->mode) {
- case TDA18271_ANALOG:
- regs[R_MPD] &= ~0x80; /* IF notch = 0 */
- break;
- case TDA18271_DIGITAL:
- regs[R_EP4] |= 0x04;
- regs[R_MPD] |= 0x80;
- break;
- }
-
- if (radio)
- regs[R_EP4] |= 0x80;
- else
- regs[R_EP4] &= ~0x80;
-
- /* image rejection validity */
- tda18271_calc_ir_measure(fe, &freq);
-
- /* calculate MAIN PLL */
- N = freq + ifc;
-
- tda18271_calc_main_pll(fe, N);
-
- tda18271_write_regs(fe, R_TM, 15);
- msleep(5);
- mutex_unlock(&priv->lock);
-
- return 0;
-}
-
-static inline int tda18271_tune(struct dvb_frontend *fe,
- u32 ifc, u32 freq, u32 bw, u8 std, int radio)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- int ret = -EINVAL;
-
- switch (priv->id) {
- case TDA18271HDC1:
- ret = tda18271c1_tune(fe, ifc, freq, bw, std, radio);
- break;
- case TDA18271HDC2:
- ret = tda18271c2_tune(fe, ifc, freq, bw, std, radio);
- break;
- }
- return ret;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int tda18271_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- struct tda18271_std_map *std_map = &priv->std;
- int ret;
- u8 std;
- u16 sgIF;
- u32 bw, freq = params->frequency;
-
- priv->mode = TDA18271_DIGITAL;
-
- if (fe->ops.info.type == FE_ATSC) {
- switch (params->u.vsb.modulation) {
- case VSB_8:
- case VSB_16:
- std = std_map->atsc_6.std_bits;
- sgIF = std_map->atsc_6.if_freq;
- break;
- case QAM_64:
- case QAM_256:
- std = std_map->qam_6.std_bits;
- sgIF = std_map->qam_6.if_freq;
- break;
- default:
- tda_warn("modulation not set!\n");
- return -EINVAL;
- }
-#if 0
- /* userspace request is already center adjusted */
- freq += 1750000; /* Adjust to center (+1.75MHZ) */
-#endif
- bw = 6000000;
- } else if (fe->ops.info.type == FE_OFDM) {
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
- bw = 6000000;
- std = std_map->dvbt_6.std_bits;
- sgIF = std_map->dvbt_6.if_freq;
- break;
- case BANDWIDTH_7_MHZ:
- bw = 7000000;
- std = std_map->dvbt_7.std_bits;
- sgIF = std_map->dvbt_7.if_freq;
- break;
- case BANDWIDTH_8_MHZ:
- bw = 8000000;
- std = std_map->dvbt_8.std_bits;
- sgIF = std_map->dvbt_8.if_freq;
- break;
- default:
- tda_warn("bandwidth not set!\n");
- return -EINVAL;
- }
- } else {
- tda_warn("modulation type not supported!\n");
- return -EINVAL;
- }
-
- /* When tuning digital, the analog demod must be tri-stated */
- if (fe->ops.analog_ops.standby)
- fe->ops.analog_ops.standby(fe);
-
- ret = tda18271_tune(fe, sgIF * 1000, freq, bw, std, 0);
-
- if (ret < 0)
- goto fail;
-
- priv->frequency = freq;
- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ?
- params->u.ofdm.bandwidth : 0;
-fail:
- return ret;
-}
-
-static int tda18271_set_analog_params(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- struct tda18271_std_map *std_map = &priv->std;
- char *mode;
- int ret, radio = 0;
- u8 std;
- u16 sgIF;
- u32 freq = params->frequency * 62500;
-
- priv->mode = TDA18271_ANALOG;
-
- if (params->mode == V4L2_TUNER_RADIO) {
- radio = 1;
- freq = freq / 1000;
- std = std_map->fm_radio.std_bits;
- sgIF = std_map->fm_radio.if_freq;
- mode = "fm";
- } else if (params->std & V4L2_STD_MN) {
- std = std_map->atv_mn.std_bits;
- sgIF = std_map->atv_mn.if_freq;
- mode = "MN";
- } else if (params->std & V4L2_STD_B) {
- std = std_map->atv_b.std_bits;
- sgIF = std_map->atv_b.if_freq;
- mode = "B";
- } else if (params->std & V4L2_STD_GH) {
- std = std_map->atv_gh.std_bits;
- sgIF = std_map->atv_gh.if_freq;
- mode = "GH";
- } else if (params->std & V4L2_STD_PAL_I) {
- std = std_map->atv_i.std_bits;
- sgIF = std_map->atv_i.if_freq;
- mode = "I";
- } else if (params->std & V4L2_STD_DK) {
- std = std_map->atv_dk.std_bits;
- sgIF = std_map->atv_dk.if_freq;
- mode = "DK";
- } else if (params->std & V4L2_STD_SECAM_L) {
- std = std_map->atv_l.std_bits;
- sgIF = std_map->atv_l.if_freq;
- mode = "L";
- } else if (params->std & V4L2_STD_SECAM_LC) {
- std = std_map->atv_lc.std_bits;
- sgIF = std_map->atv_lc.if_freq;
- mode = "L'";
- } else {
- std = std_map->atv_i.std_bits;
- sgIF = std_map->atv_i.if_freq;
- mode = "xx";
- }
-
- tda_dbg("setting tda18271 to system %s\n", mode);
-
- ret = tda18271_tune(fe, sgIF * 1000, freq, 0, std, radio);
-
- if (ret < 0)
- goto fail;
-
- priv->frequency = freq;
- priv->bandwidth = 0;
-fail:
- return ret;
-}
-
-static int tda18271_sleep(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
-
- mutex_lock(&priv->lock);
-
- /* standby mode w/ slave tuner output
- * & loop thru & xtal oscillator on */
- tda18271_set_standby_mode(fe, 1, 0, 0);
-
- mutex_unlock(&priv->lock);
-
- return 0;
-}
-
-static int tda18271_release(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
-
- mutex_lock(&tda18271_list_mutex);
-
- priv->count--;
-
- if (!priv->count) {
- tda_dbg("destroying instance @ %d-%04x\n",
- i2c_adapter_id(priv->i2c_adap),
- priv->i2c_addr);
- list_del(&priv->tda18271_list);
-
- kfree(priv);
- }
- mutex_unlock(&tda18271_list_mutex);
-
- fe->tuner_priv = NULL;
-
- return 0;
-}
-
-static int tda18271_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- *frequency = priv->frequency;
- return 0;
-}
-
-static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- *bandwidth = priv->bandwidth;
- return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-#define tda18271_update_std(std_cfg, name) do { \
- if (map->std_cfg.if_freq + map->std_cfg.std_bits > 0) { \
- tda_dbg("Using custom std config for %s\n", name); \
- memcpy(&std->std_cfg, &map->std_cfg, \
- sizeof(struct tda18271_std_map_item)); \
- } } while (0)
-
-#define tda18271_dump_std_item(std_cfg, name) do { \
- tda_dbg("(%s) if freq = %d, std bits = 0x%02x\n", \
- name, std->std_cfg.if_freq, std->std_cfg.std_bits); \
- } while (0)
-
-static int tda18271_dump_std_map(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- struct tda18271_std_map *std = &priv->std;
-
- tda_dbg("========== STANDARD MAP SETTINGS ==========\n");
- tda18271_dump_std_item(fm_radio, "fm");
- tda18271_dump_std_item(atv_b, "pal b");
- tda18271_dump_std_item(atv_dk, "pal dk");
- tda18271_dump_std_item(atv_gh, "pal gh");
- tda18271_dump_std_item(atv_i, "pal i");
- tda18271_dump_std_item(atv_l, "pal l");
- tda18271_dump_std_item(atv_lc, "pal l'");
- tda18271_dump_std_item(atv_mn, "atv mn");
- tda18271_dump_std_item(atsc_6, "atsc 6");
- tda18271_dump_std_item(dvbt_6, "dvbt 6");
- tda18271_dump_std_item(dvbt_7, "dvbt 7");
- tda18271_dump_std_item(dvbt_8, "dvbt 8");
- tda18271_dump_std_item(qam_6, "qam 6");
- tda18271_dump_std_item(qam_8, "qam 8");
-
- return 0;
-}
-
-static int tda18271_update_std_map(struct dvb_frontend *fe,
- struct tda18271_std_map *map)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- struct tda18271_std_map *std = &priv->std;
-
- if (!map)
- return -EINVAL;
-
- tda18271_update_std(fm_radio, "fm");
- tda18271_update_std(atv_b, "atv b");
- tda18271_update_std(atv_dk, "atv dk");
- tda18271_update_std(atv_gh, "atv gh");
- tda18271_update_std(atv_i, "atv i");
- tda18271_update_std(atv_l, "atv l");
- tda18271_update_std(atv_lc, "atv l'");
- tda18271_update_std(atv_mn, "atv mn");
- tda18271_update_std(atsc_6, "atsc 6");
- tda18271_update_std(dvbt_6, "dvbt 6");
- tda18271_update_std(dvbt_7, "dvbt 7");
- tda18271_update_std(dvbt_8, "dvbt 8");
- tda18271_update_std(qam_6, "qam 6");
- tda18271_update_std(qam_8, "qam 8");
-
- return 0;
-}
-
-static int tda18271_get_id(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- char *name;
- int ret = 0;
-
- mutex_lock(&priv->lock);
- tda18271_read_regs(fe);
- mutex_unlock(&priv->lock);
-
- switch (regs[R_ID] & 0x7f) {
- case 3:
- name = "TDA18271HD/C1";
- priv->id = TDA18271HDC1;
- break;
- case 4:
- name = "TDA18271HD/C2";
- priv->id = TDA18271HDC2;
- break;
- default:
- name = "Unknown device";
- ret = -EINVAL;
- break;
- }
-
- tda_info("%s detected @ %d-%04x%s\n", name,
- i2c_adapter_id(priv->i2c_adap), priv->i2c_addr,
- (0 == ret) ? "" : ", device not supported.");
-
- return ret;
-}
-
-static struct dvb_tuner_ops tda18271_tuner_ops = {
- .info = {
- .name = "NXP TDA18271HD",
- .frequency_min = 45000000,
- .frequency_max = 864000000,
- .frequency_step = 62500
- },
- .init = tda18271_init,
- .sleep = tda18271_sleep,
- .set_params = tda18271_set_params,
- .set_analog_params = tda18271_set_analog_params,
- .release = tda18271_release,
- .get_frequency = tda18271_get_frequency,
- .get_bandwidth = tda18271_get_bandwidth,
-};
-
-struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
- struct i2c_adapter *i2c,
- struct tda18271_config *cfg)
-{
- struct tda18271_priv *priv = NULL;
- int state_found = 0;
-
- mutex_lock(&tda18271_list_mutex);
-
- list_for_each_entry(priv, &tda18271_list, tda18271_list) {
- if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) &&
- (priv->i2c_addr == addr)) {
- tda_dbg("attaching existing tuner @ %d-%04x\n",
- i2c_adapter_id(priv->i2c_adap),
- priv->i2c_addr);
- priv->count++;
- fe->tuner_priv = priv;
- state_found = 1;
- /* allow dvb driver to override i2c gate setting */
- if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
- priv->gate = cfg->gate;
- break;
- }
- }
- if (state_found == 0) {
- tda_dbg("creating new tuner instance @ %d-%04x\n",
- i2c_adapter_id(i2c), addr);
-
- priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL);
- if (priv == NULL) {
- mutex_unlock(&tda18271_list_mutex);
- return NULL;
- }
-
- priv->i2c_addr = addr;
- priv->i2c_adap = i2c;
- priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
- priv->cal_initialized = false;
- mutex_init(&priv->lock);
- priv->count++;
-
- fe->tuner_priv = priv;
-
- list_add_tail(&priv->tda18271_list, &tda18271_list);
-
- if (tda18271_get_id(fe) < 0)
- goto fail;
-
- if (tda18271_assign_map_layout(fe) < 0)
- goto fail;
-
- mutex_lock(&priv->lock);
- tda18271_init_regs(fe);
-
- if ((tda18271_cal_on_startup) && (priv->id == TDA18271HDC2))
- tda18271_rf_cal_init(fe);
-
- mutex_unlock(&priv->lock);
- }
-
- /* override default std map with values in config struct */
- if ((cfg) && (cfg->std_map))
- tda18271_update_std_map(fe, cfg->std_map);
-
- mutex_unlock(&tda18271_list_mutex);
-
- memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
- sizeof(struct dvb_tuner_ops));
-
- if (tda18271_debug & DBG_MAP)
- tda18271_dump_std_map(fe);
-
- return fe;
-fail:
- mutex_unlock(&tda18271_list_mutex);
-
- tda18271_release(fe);
- return NULL;
-}
-EXPORT_SYMBOL_GPL(tda18271_attach);
-MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver");
-MODULE_AUTHOR("Michael Krufky ");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.2");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/trunk/drivers/media/dvb/frontends/tda18271-priv.h b/trunk/drivers/media/dvb/frontends/tda18271-priv.h
deleted file mode 100644
index 7b939a5325fb..000000000000
--- a/trunk/drivers/media/dvb/frontends/tda18271-priv.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- tda18271-priv.h - private header for the NXP TDA18271 silicon tuner
-
- Copyright (C) 2007, 2008 Michael Krufky
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __TDA18271_PRIV_H__
-#define __TDA18271_PRIV_H__
-
-#include
-#include
-#include
-#include "tda18271.h"
-
-#define R_ID 0x00 /* ID byte */
-#define R_TM 0x01 /* Thermo byte */
-#define R_PL 0x02 /* Power level byte */
-#define R_EP1 0x03 /* Easy Prog byte 1 */
-#define R_EP2 0x04 /* Easy Prog byte 2 */
-#define R_EP3 0x05 /* Easy Prog byte 3 */
-#define R_EP4 0x06 /* Easy Prog byte 4 */
-#define R_EP5 0x07 /* Easy Prog byte 5 */
-#define R_CPD 0x08 /* Cal Post-Divider byte */
-#define R_CD1 0x09 /* Cal Divider byte 1 */
-#define R_CD2 0x0a /* Cal Divider byte 2 */
-#define R_CD3 0x0b /* Cal Divider byte 3 */
-#define R_MPD 0x0c /* Main Post-Divider byte */
-#define R_MD1 0x0d /* Main Divider byte 1 */
-#define R_MD2 0x0e /* Main Divider byte 2 */
-#define R_MD3 0x0f /* Main Divider byte 3 */
-#define R_EB1 0x10 /* Extended byte 1 */
-#define R_EB2 0x11 /* Extended byte 2 */
-#define R_EB3 0x12 /* Extended byte 3 */
-#define R_EB4 0x13 /* Extended byte 4 */
-#define R_EB5 0x14 /* Extended byte 5 */
-#define R_EB6 0x15 /* Extended byte 6 */
-#define R_EB7 0x16 /* Extended byte 7 */
-#define R_EB8 0x17 /* Extended byte 8 */
-#define R_EB9 0x18 /* Extended byte 9 */
-#define R_EB10 0x19 /* Extended byte 10 */
-#define R_EB11 0x1a /* Extended byte 11 */
-#define R_EB12 0x1b /* Extended byte 12 */
-#define R_EB13 0x1c /* Extended byte 13 */
-#define R_EB14 0x1d /* Extended byte 14 */
-#define R_EB15 0x1e /* Extended byte 15 */
-#define R_EB16 0x1f /* Extended byte 16 */
-#define R_EB17 0x20 /* Extended byte 17 */
-#define R_EB18 0x21 /* Extended byte 18 */
-#define R_EB19 0x22 /* Extended byte 19 */
-#define R_EB20 0x23 /* Extended byte 20 */
-#define R_EB21 0x24 /* Extended byte 21 */
-#define R_EB22 0x25 /* Extended byte 22 */
-#define R_EB23 0x26 /* Extended byte 23 */
-
-#define TDA18271_NUM_REGS 39
-
-/*---------------------------------------------------------------------*/
-
-struct tda18271_rf_tracking_filter_cal {
- u32 rfmax;
- u8 rfband;
- u32 rf1_def;
- u32 rf2_def;
- u32 rf3_def;
- u32 rf1;
- u32 rf2;
- u32 rf3;
- int rf_a1;
- int rf_b1;
- int rf_a2;
- int rf_b2;
-};
-
-enum tda18271_mode {
- TDA18271_ANALOG,
- TDA18271_DIGITAL,
-};
-
-struct tda18271_map_layout;
-
-enum tda18271_ver {
- TDA18271HDC1,
- TDA18271HDC2,
-};
-
-struct tda18271_priv {
- u8 i2c_addr;
- struct i2c_adapter *i2c_adap;
- unsigned char tda18271_regs[TDA18271_NUM_REGS];
-
- struct list_head tda18271_list;
-
- enum tda18271_mode mode;
- enum tda18271_i2c_gate gate;
- enum tda18271_ver id;
-
- unsigned int count;
- unsigned int tm_rfcal;
- unsigned int cal_initialized:1;
-
- struct tda18271_map_layout *maps;
- struct tda18271_std_map std;
- struct tda18271_rf_tracking_filter_cal rf_cal_state[8];
-
- struct mutex lock;
-
- u32 frequency;
- u32 bandwidth;
-};
-
-/*---------------------------------------------------------------------*/
-
-extern int tda18271_debug;
-
-#define DBG_INFO 1
-#define DBG_MAP 2
-#define DBG_REG 4
-#define DBG_ADV 8
-#define DBG_CAL 16
-
-#define tda_printk(kern, fmt, arg...) \
- printk(kern "%s: " fmt, __FUNCTION__, ##arg)
-
-#define dprintk(kern, lvl, fmt, arg...) do {\
- if (tda18271_debug & lvl) \
- tda_printk(kern, fmt, ##arg); } while (0)
-
-#define tda_info(fmt, arg...) printk(KERN_INFO fmt, ##arg)
-#define tda_warn(fmt, arg...) tda_printk(KERN_WARNING, fmt, ##arg)
-#define tda_err(fmt, arg...) tda_printk(KERN_ERR, fmt, ##arg)
-#define tda_dbg(fmt, arg...) dprintk(KERN_DEBUG, DBG_INFO, fmt, ##arg)
-#define tda_map(fmt, arg...) dprintk(KERN_DEBUG, DBG_MAP, fmt, ##arg)
-#define tda_reg(fmt, arg...) dprintk(KERN_DEBUG, DBG_REG, fmt, ##arg)
-#define tda_cal(fmt, arg...) dprintk(KERN_DEBUG, DBG_CAL, fmt, ##arg)
-
-/*---------------------------------------------------------------------*/
-
-enum tda18271_map_type {
- /* tda18271_pll_map */
- MAIN_PLL,
- CAL_PLL,
- /* tda18271_map */
- RF_CAL,
- RF_CAL_KMCO,
- RF_CAL_DC_OVER_DT,
- BP_FILTER,
- RF_BAND,
- GAIN_TAPER,
- IR_MEASURE,
-};
-
-extern int tda18271_lookup_pll_map(struct dvb_frontend *fe,
- enum tda18271_map_type map_type,
- u32 *freq, u8 *post_div, u8 *div);
-extern int tda18271_lookup_map(struct dvb_frontend *fe,
- enum tda18271_map_type map_type,
- u32 *freq, u8 *val);
-
-extern int tda18271_lookup_thermometer(struct dvb_frontend *fe);
-
-extern int tda18271_lookup_rf_band(struct dvb_frontend *fe,
- u32 *freq, u8 *rf_band);
-
-extern int tda18271_lookup_cid_target(struct dvb_frontend *fe,
- u32 *freq, u8 *cid_target,
- u16 *count_limit);
-
-extern int tda18271_assign_map_layout(struct dvb_frontend *fe);
-
-/*---------------------------------------------------------------------*/
-
-extern int tda18271_read_regs(struct dvb_frontend *fe);
-extern int tda18271_read_extended(struct dvb_frontend *fe);
-extern int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len);
-extern int tda18271_init_regs(struct dvb_frontend *fe);
-
-extern int tda18271_set_standby_mode(struct dvb_frontend *fe,
- int sm, int sm_lt, int sm_xt);
-
-extern int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq);
-extern int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq);
-
-extern int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq);
-extern int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq);
-extern int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq);
-extern int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq);
-extern int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq);
-extern int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq);
-
-#endif /* __TDA18271_PRIV_H__ */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/trunk/drivers/media/dvb/frontends/tda18271-tables.c b/trunk/drivers/media/dvb/frontends/tda18271-tables.c
deleted file mode 100644
index e94afcfdc5bc..000000000000
--- a/trunk/drivers/media/dvb/frontends/tda18271-tables.c
+++ /dev/null
@@ -1,1285 +0,0 @@
-/*
- tda18271-tables.c - driver for the Philips / NXP TDA18271 silicon tuner
-
- Copyright (C) 2007, 2008 Michael Krufky
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "tda18271-priv.h"
-
-struct tda18271_pll_map {
- u32 lomax;
- u8 pd; /* post div */
- u8 d; /* div */
-};
-
-struct tda18271_map {
- u32 rfmax;
- u8 val;
-};
-
-/*---------------------------------------------------------------------*/
-
-static struct tda18271_pll_map tda18271c1_main_pll[] = {
- { .lomax = 32000, .pd = 0x5f, .d = 0xf0 },
- { .lomax = 35000, .pd = 0x5e, .d = 0xe0 },
- { .lomax = 37000, .pd = 0x5d, .d = 0xd0 },
- { .lomax = 41000, .pd = 0x5c, .d = 0xc0 },
- { .lomax = 44000, .pd = 0x5b, .d = 0xb0 },
- { .lomax = 49000, .pd = 0x5a, .d = 0xa0 },
- { .lomax = 54000, .pd = 0x59, .d = 0x90 },
- { .lomax = 61000, .pd = 0x58, .d = 0x80 },
- { .lomax = 65000, .pd = 0x4f, .d = 0x78 },
- { .lomax = 70000, .pd = 0x4e, .d = 0x70 },
- { .lomax = 75000, .pd = 0x4d, .d = 0x68 },
- { .lomax = 82000, .pd = 0x4c, .d = 0x60 },
- { .lomax = 89000, .pd = 0x4b, .d = 0x58 },
- { .lomax = 98000, .pd = 0x4a, .d = 0x50 },
- { .lomax = 109000, .pd = 0x49, .d = 0x48 },
- { .lomax = 123000, .pd = 0x48, .d = 0x40 },
- { .lomax = 131000, .pd = 0x3f, .d = 0x3c },
- { .lomax = 141000, .pd = 0x3e, .d = 0x38 },
- { .lomax = 151000, .pd = 0x3d, .d = 0x34 },
- { .lomax = 164000, .pd = 0x3c, .d = 0x30 },
- { .lomax = 179000, .pd = 0x3b, .d = 0x2c },
- { .lomax = 197000, .pd = 0x3a, .d = 0x28 },
- { .lomax = 219000, .pd = 0x39, .d = 0x24 },
- { .lomax = 246000, .pd = 0x38, .d = 0x20 },
- { .lomax = 263000, .pd = 0x2f, .d = 0x1e },
- { .lomax = 282000, .pd = 0x2e, .d = 0x1c },
- { .lomax = 303000, .pd = 0x2d, .d = 0x1a },
- { .lomax = 329000, .pd = 0x2c, .d = 0x18 },
- { .lomax = 359000, .pd = 0x2b, .d = 0x16 },
- { .lomax = 395000, .pd = 0x2a, .d = 0x14 },
- { .lomax = 438000, .pd = 0x29, .d = 0x12 },
- { .lomax = 493000, .pd = 0x28, .d = 0x10 },
- { .lomax = 526000, .pd = 0x1f, .d = 0x0f },
- { .lomax = 564000, .pd = 0x1e, .d = 0x0e },
- { .lomax = 607000, .pd = 0x1d, .d = 0x0d },
- { .lomax = 658000, .pd = 0x1c, .d = 0x0c },
- { .lomax = 718000, .pd = 0x1b, .d = 0x0b },
- { .lomax = 790000, .pd = 0x1a, .d = 0x0a },
- { .lomax = 877000, .pd = 0x19, .d = 0x09 },
- { .lomax = 987000, .pd = 0x18, .d = 0x08 },
- { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */
-};
-
-static struct tda18271_pll_map tda18271c2_main_pll[] = {
- { .lomax = 33125, .pd = 0x57, .d = 0xf0 },
- { .lomax = 35500, .pd = 0x56, .d = 0xe0 },
- { .lomax = 38188, .pd = 0x55, .d = 0xd0 },
- { .lomax = 41375, .pd = 0x54, .d = 0xc0 },
- { .lomax = 45125, .pd = 0x53, .d = 0xb0 },
- { .lomax = 49688, .pd = 0x52, .d = 0xa0 },
- { .lomax = 55188, .pd = 0x51, .d = 0x90 },
- { .lomax = 62125, .pd = 0x50, .d = 0x80 },
- { .lomax = 66250, .pd = 0x47, .d = 0x78 },
- { .lomax = 71000, .pd = 0x46, .d = 0x70 },
- { .lomax = 76375, .pd = 0x45, .d = 0x68 },
- { .lomax = 82750, .pd = 0x44, .d = 0x60 },
- { .lomax = 90250, .pd = 0x43, .d = 0x58 },
- { .lomax = 99375, .pd = 0x42, .d = 0x50 },
- { .lomax = 110375, .pd = 0x41, .d = 0x48 },
- { .lomax = 124250, .pd = 0x40, .d = 0x40 },
- { .lomax = 132500, .pd = 0x37, .d = 0x3c },
- { .lomax = 142000, .pd = 0x36, .d = 0x38 },
- { .lomax = 152750, .pd = 0x35, .d = 0x34 },
- { .lomax = 165500, .pd = 0x34, .d = 0x30 },
- { .lomax = 180500, .pd = 0x33, .d = 0x2c },
- { .lomax = 198750, .pd = 0x32, .d = 0x28 },
- { .lomax = 220750, .pd = 0x31, .d = 0x24 },
- { .lomax = 248500, .pd = 0x30, .d = 0x20 },
- { .lomax = 265000, .pd = 0x27, .d = 0x1e },
- { .lomax = 284000, .pd = 0x26, .d = 0x1c },
- { .lomax = 305500, .pd = 0x25, .d = 0x1a },
- { .lomax = 331000, .pd = 0x24, .d = 0x18 },
- { .lomax = 361000, .pd = 0x23, .d = 0x16 },
- { .lomax = 397500, .pd = 0x22, .d = 0x14 },
- { .lomax = 441500, .pd = 0x21, .d = 0x12 },
- { .lomax = 497000, .pd = 0x20, .d = 0x10 },
- { .lomax = 530000, .pd = 0x17, .d = 0x0f },
- { .lomax = 568000, .pd = 0x16, .d = 0x0e },
- { .lomax = 611000, .pd = 0x15, .d = 0x0d },
- { .lomax = 662000, .pd = 0x14, .d = 0x0c },
- { .lomax = 722000, .pd = 0x13, .d = 0x0b },
- { .lomax = 795000, .pd = 0x12, .d = 0x0a },
- { .lomax = 883000, .pd = 0x11, .d = 0x09 },
- { .lomax = 994000, .pd = 0x10, .d = 0x08 },
- { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */
-};
-
-static struct tda18271_pll_map tda18271c1_cal_pll[] = {
- { .lomax = 33000, .pd = 0xdd, .d = 0xd0 },
- { .lomax = 36000, .pd = 0xdc, .d = 0xc0 },
- { .lomax = 40000, .pd = 0xdb, .d = 0xb0 },
- { .lomax = 44000, .pd = 0xda, .d = 0xa0 },
- { .lomax = 49000, .pd = 0xd9, .d = 0x90 },
- { .lomax = 55000, .pd = 0xd8, .d = 0x80 },
- { .lomax = 63000, .pd = 0xd3, .d = 0x70 },
- { .lomax = 67000, .pd = 0xcd, .d = 0x68 },
- { .lomax = 73000, .pd = 0xcc, .d = 0x60 },
- { .lomax = 80000, .pd = 0xcb, .d = 0x58 },
- { .lomax = 88000, .pd = 0xca, .d = 0x50 },
- { .lomax = 98000, .pd = 0xc9, .d = 0x48 },
- { .lomax = 110000, .pd = 0xc8, .d = 0x40 },
- { .lomax = 126000, .pd = 0xc3, .d = 0x38 },
- { .lomax = 135000, .pd = 0xbd, .d = 0x34 },
- { .lomax = 147000, .pd = 0xbc, .d = 0x30 },
- { .lomax = 160000, .pd = 0xbb, .d = 0x2c },
- { .lomax = 176000, .pd = 0xba, .d = 0x28 },
- { .lomax = 196000, .pd = 0xb9, .d = 0x24 },
- { .lomax = 220000, .pd = 0xb8, .d = 0x20 },
- { .lomax = 252000, .pd = 0xb3, .d = 0x1c },
- { .lomax = 271000, .pd = 0xad, .d = 0x1a },
- { .lomax = 294000, .pd = 0xac, .d = 0x18 },
- { .lomax = 321000, .pd = 0xab, .d = 0x16 },
- { .lomax = 353000, .pd = 0xaa, .d = 0x14 },
- { .lomax = 392000, .pd = 0xa9, .d = 0x12 },
- { .lomax = 441000, .pd = 0xa8, .d = 0x10 },
- { .lomax = 505000, .pd = 0xa3, .d = 0x0e },
- { .lomax = 543000, .pd = 0x9d, .d = 0x0d },
- { .lomax = 589000, .pd = 0x9c, .d = 0x0c },
- { .lomax = 642000, .pd = 0x9b, .d = 0x0b },
- { .lomax = 707000, .pd = 0x9a, .d = 0x0a },
- { .lomax = 785000, .pd = 0x99, .d = 0x09 },
- { .lomax = 883000, .pd = 0x98, .d = 0x08 },
- { .lomax = 1010000, .pd = 0x93, .d = 0x07 },
- { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */
-};
-
-static struct tda18271_pll_map tda18271c2_cal_pll[] = {
- { .lomax = 33813, .pd = 0xdd, .d = 0xd0 },
- { .lomax = 36625, .pd = 0xdc, .d = 0xc0 },
- { .lomax = 39938, .pd = 0xdb, .d = 0xb0 },
- { .lomax = 43938, .pd = 0xda, .d = 0xa0 },
- { .lomax = 48813, .pd = 0xd9, .d = 0x90 },
- { .lomax = 54938, .pd = 0xd8, .d = 0x80 },
- { .lomax = 62813, .pd = 0xd3, .d = 0x70 },
- { .lomax = 67625, .pd = 0xcd, .d = 0x68 },
- { .lomax = 73250, .pd = 0xcc, .d = 0x60 },
- { .lomax = 79875, .pd = 0xcb, .d = 0x58 },
- { .lomax = 87875, .pd = 0xca, .d = 0x50 },
- { .lomax = 97625, .pd = 0xc9, .d = 0x48 },
- { .lomax = 109875, .pd = 0xc8, .d = 0x40 },
- { .lomax = 125625, .pd = 0xc3, .d = 0x38 },
- { .lomax = 135250, .pd = 0xbd, .d = 0x34 },
- { .lomax = 146500, .pd = 0xbc, .d = 0x30 },
- { .lomax = 159750, .pd = 0xbb, .d = 0x2c },
- { .lomax = 175750, .pd = 0xba, .d = 0x28 },
- { .lomax = 195250, .pd = 0xb9, .d = 0x24 },
- { .lomax = 219750, .pd = 0xb8, .d = 0x20 },
- { .lomax = 251250, .pd = 0xb3, .d = 0x1c },
- { .lomax = 270500, .pd = 0xad, .d = 0x1a },
- { .lomax = 293000, .pd = 0xac, .d = 0x18 },
- { .lomax = 319500, .pd = 0xab, .d = 0x16 },
- { .lomax = 351500, .pd = 0xaa, .d = 0x14 },
- { .lomax = 390500, .pd = 0xa9, .d = 0x12 },
- { .lomax = 439500, .pd = 0xa8, .d = 0x10 },
- { .lomax = 502500, .pd = 0xa3, .d = 0x0e },
- { .lomax = 541000, .pd = 0x9d, .d = 0x0d },
- { .lomax = 586000, .pd = 0x9c, .d = 0x0c },
- { .lomax = 639000, .pd = 0x9b, .d = 0x0b },
- { .lomax = 703000, .pd = 0x9a, .d = 0x0a },
- { .lomax = 781000, .pd = 0x99, .d = 0x09 },
- { .lomax = 879000, .pd = 0x98, .d = 0x08 },
- { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271_bp_filter[] = {
- { .rfmax = 62000, .val = 0x00 },
- { .rfmax = 84000, .val = 0x01 },
- { .rfmax = 100000, .val = 0x02 },
- { .rfmax = 140000, .val = 0x03 },
- { .rfmax = 170000, .val = 0x04 },
- { .rfmax = 180000, .val = 0x05 },
- { .rfmax = 865000, .val = 0x06 },
- { .rfmax = 0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271c1_km[] = {
- { .rfmax = 61100, .val = 0x74 },
- { .rfmax = 350000, .val = 0x40 },
- { .rfmax = 720000, .val = 0x30 },
- { .rfmax = 865000, .val = 0x40 },
- { .rfmax = 0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271c2_km[] = {
- { .rfmax = 47900, .val = 0x38 },
- { .rfmax = 61100, .val = 0x44 },
- { .rfmax = 350000, .val = 0x30 },
- { .rfmax = 720000, .val = 0x24 },
- { .rfmax = 865000, .val = 0x3c },
- { .rfmax = 0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271_rf_band[] = {
- { .rfmax = 47900, .val = 0x00 },
- { .rfmax = 61100, .val = 0x01 },
-/* { .rfmax = 152600, .val = 0x02 }, */
- { .rfmax = 121200, .val = 0x02 },
- { .rfmax = 164700, .val = 0x03 },
- { .rfmax = 203500, .val = 0x04 },
- { .rfmax = 457800, .val = 0x05 },
- { .rfmax = 865000, .val = 0x06 },
- { .rfmax = 0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271_gain_taper[] = {
- { .rfmax = 45400, .val = 0x1f },
- { .rfmax = 45800, .val = 0x1e },
- { .rfmax = 46200, .val = 0x1d },
- { .rfmax = 46700, .val = 0x1c },
- { .rfmax = 47100, .val = 0x1b },
- { .rfmax = 47500, .val = 0x1a },
- { .rfmax = 47900, .val = 0x19 },
- { .rfmax = 49600, .val = 0x17 },
- { .rfmax = 51200, .val = 0x16 },
- { .rfmax = 52900, .val = 0x15 },
- { .rfmax = 54500, .val = 0x14 },
- { .rfmax = 56200, .val = 0x13 },
- { .rfmax = 57800, .val = 0x12 },
- { .rfmax = 59500, .val = 0x11 },
- { .rfmax = 61100, .val = 0x10 },
- { .rfmax = 67600, .val = 0x0d },
- { .rfmax = 74200, .val = 0x0c },
- { .rfmax = 80700, .val = 0x0b },
- { .rfmax = 87200, .val = 0x0a },
- { .rfmax = 93800, .val = 0x09 },
- { .rfmax = 100300, .val = 0x08 },
- { .rfmax = 106900, .val = 0x07 },
- { .rfmax = 113400, .val = 0x06 },
- { .rfmax = 119900, .val = 0x05 },
- { .rfmax = 126500, .val = 0x04 },
- { .rfmax = 133000, .val = 0x03 },
- { .rfmax = 139500, .val = 0x02 },
- { .rfmax = 146100, .val = 0x01 },
- { .rfmax = 152600, .val = 0x00 },
- { .rfmax = 154300, .val = 0x1f },
- { .rfmax = 156100, .val = 0x1e },
- { .rfmax = 157800, .val = 0x1d },
- { .rfmax = 159500, .val = 0x1c },
- { .rfmax = 161200, .val = 0x1b },
- { .rfmax = 163000, .val = 0x1a },
- { .rfmax = 164700, .val = 0x19 },
- { .rfmax = 170200, .val = 0x17 },
- { .rfmax = 175800, .val = 0x16 },
- { .rfmax = 181300, .val = 0x15 },
- { .rfmax = 186900, .val = 0x14 },
- { .rfmax = 192400, .val = 0x13 },
- { .rfmax = 198000, .val = 0x12 },
- { .rfmax = 203500, .val = 0x11 },
- { .rfmax = 216200, .val = 0x14 },
- { .rfmax = 228900, .val = 0x13 },
- { .rfmax = 241600, .val = 0x12 },
- { .rfmax = 254400, .val = 0x11 },
- { .rfmax = 267100, .val = 0x10 },
- { .rfmax = 279800, .val = 0x0f },
- { .rfmax = 292500, .val = 0x0e },
- { .rfmax = 305200, .val = 0x0d },
- { .rfmax = 317900, .val = 0x0c },
- { .rfmax = 330700, .val = 0x0b },
- { .rfmax = 343400, .val = 0x0a },
- { .rfmax = 356100, .val = 0x09 },
- { .rfmax = 368800, .val = 0x08 },
- { .rfmax = 381500, .val = 0x07 },
- { .rfmax = 394200, .val = 0x06 },
- { .rfmax = 406900, .val = 0x05 },
- { .rfmax = 419700, .val = 0x04 },
- { .rfmax = 432400, .val = 0x03 },
- { .rfmax = 445100, .val = 0x02 },
- { .rfmax = 457800, .val = 0x01 },
- { .rfmax = 476300, .val = 0x19 },
- { .rfmax = 494800, .val = 0x18 },
- { .rfmax = 513300, .val = 0x17 },
- { .rfmax = 531800, .val = 0x16 },
- { .rfmax = 550300, .val = 0x15 },
- { .rfmax = 568900, .val = 0x14 },
- { .rfmax = 587400, .val = 0x13 },
- { .rfmax = 605900, .val = 0x12 },
- { .rfmax = 624400, .val = 0x11 },
- { .rfmax = 642900, .val = 0x10 },
- { .rfmax = 661400, .val = 0x0f },
- { .rfmax = 679900, .val = 0x0e },
- { .rfmax = 698400, .val = 0x0d },
- { .rfmax = 716900, .val = 0x0c },
- { .rfmax = 735400, .val = 0x0b },
- { .rfmax = 753900, .val = 0x0a },
- { .rfmax = 772500, .val = 0x09 },
- { .rfmax = 791000, .val = 0x08 },
- { .rfmax = 809500, .val = 0x07 },
- { .rfmax = 828000, .val = 0x06 },
- { .rfmax = 846500, .val = 0x05 },
- { .rfmax = 865000, .val = 0x04 },
- { .rfmax = 0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271c1_rf_cal[] = {
- { .rfmax = 41000, .val = 0x1e },
- { .rfmax = 43000, .val = 0x30 },
- { .rfmax = 45000, .val = 0x43 },
- { .rfmax = 46000, .val = 0x4d },
- { .rfmax = 47000, .val = 0x54 },
- { .rfmax = 47900, .val = 0x64 },
- { .rfmax = 49100, .val = 0x20 },
- { .rfmax = 50000, .val = 0x22 },
- { .rfmax = 51000, .val = 0x2a },
- { .rfmax = 53000, .val = 0x32 },
- { .rfmax = 55000, .val = 0x35 },
- { .rfmax = 56000, .val = 0x3c },
- { .rfmax = 57000, .val = 0x3f },
- { .rfmax = 58000, .val = 0x48 },
- { .rfmax = 59000, .val = 0x4d },
- { .rfmax = 60000, .val = 0x58 },
- { .rfmax = 61100, .val = 0x5f },
- { .rfmax = 0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271c2_rf_cal[] = {
- { .rfmax = 41000, .val = 0x0f },
- { .rfmax = 43000, .val = 0x1c },
- { .rfmax = 45000, .val = 0x2f },
- { .rfmax = 46000, .val = 0x39 },
- { .rfmax = 47000, .val = 0x40 },
- { .rfmax = 47900, .val = 0x50 },
- { .rfmax = 49100, .val = 0x16 },
- { .rfmax = 50000, .val = 0x18 },
- { .rfmax = 51000, .val = 0x20 },
- { .rfmax = 53000, .val = 0x28 },
- { .rfmax = 55000, .val = 0x2b },
- { .rfmax = 56000, .val = 0x32 },
- { .rfmax = 57000, .val = 0x35 },
- { .rfmax = 58000, .val = 0x3e },
- { .rfmax = 59000, .val = 0x43 },
- { .rfmax = 60000, .val = 0x4e },
- { .rfmax = 61100, .val = 0x55 },
- { .rfmax = 63000, .val = 0x0f },
- { .rfmax = 64000, .val = 0x11 },
- { .rfmax = 65000, .val = 0x12 },
- { .rfmax = 66000, .val = 0x15 },
- { .rfmax = 67000, .val = 0x16 },
- { .rfmax = 68000, .val = 0x17 },
- { .rfmax = 70000, .val = 0x19 },
- { .rfmax = 71000, .val = 0x1c },
- { .rfmax = 72000, .val = 0x1d },
- { .rfmax = 73000, .val = 0x1f },
- { .rfmax = 74000, .val = 0x20 },
- { .rfmax = 75000, .val = 0x21 },
- { .rfmax = 76000, .val = 0x24 },
- { .rfmax = 77000, .val = 0x25 },
- { .rfmax = 78000, .val = 0x27 },
- { .rfmax = 80000, .val = 0x28 },
- { .rfmax = 81000, .val = 0x29 },
- { .rfmax = 82000, .val = 0x2d },
- { .rfmax = 83000, .val = 0x2e },
- { .rfmax = 84000, .val = 0x2f },
- { .rfmax = 85000, .val = 0x31 },
- { .rfmax = 86000, .val = 0x33 },
- { .rfmax = 87000, .val = 0x34 },
- { .rfmax = 88000, .val = 0x35 },
- { .rfmax = 89000, .val = 0x37 },
- { .rfmax = 90000, .val = 0x38 },
- { .rfmax = 91000, .val = 0x39 },
- { .rfmax = 93000, .val = 0x3c },
- { .rfmax = 94000, .val = 0x3e },
- { .rfmax = 95000, .val = 0x3f },
- { .rfmax = 96000, .val = 0x40 },
- { .rfmax = 97000, .val = 0x42 },
- { .rfmax = 99000, .val = 0x45 },
- { .rfmax = 100000, .val = 0x46 },
- { .rfmax = 102000, .val = 0x48 },
- { .rfmax = 103000, .val = 0x4a },
- { .rfmax = 105000, .val = 0x4d },
- { .rfmax = 106000, .val = 0x4e },
- { .rfmax = 107000, .val = 0x50 },
- { .rfmax = 108000, .val = 0x51 },
- { .rfmax = 110000, .val = 0x54 },
- { .rfmax = 111000, .val = 0x56 },
- { .rfmax = 112000, .val = 0x57 },
- { .rfmax = 113000, .val = 0x58 },
- { .rfmax = 114000, .val = 0x59 },
- { .rfmax = 115000, .val = 0x5c },
- { .rfmax = 116000, .val = 0x5d },
- { .rfmax = 117000, .val = 0x5f },
- { .rfmax = 119000, .val = 0x60 },
- { .rfmax = 120000, .val = 0x64 },
- { .rfmax = 121000, .val = 0x65 },
- { .rfmax = 122000, .val = 0x66 },
- { .rfmax = 123000, .val = 0x68 },
- { .rfmax = 124000, .val = 0x69 },
- { .rfmax = 125000, .val = 0x6c },
- { .rfmax = 126000, .val = 0x6d },
- { .rfmax = 127000, .val = 0x6e },
- { .rfmax = 128000, .val = 0x70 },
- { .rfmax = 129000, .val = 0x71 },
- { .rfmax = 130000, .val = 0x75 },
- { .rfmax = 131000, .val = 0x77 },
- { .rfmax = 132000, .val = 0x78 },
- { .rfmax = 133000, .val = 0x7b },
- { .rfmax = 134000, .val = 0x7e },
- { .rfmax = 135000, .val = 0x81 },
- { .rfmax = 136000, .val = 0x82 },
- { .rfmax = 137000, .val = 0x87 },
- { .rfmax = 138000, .val = 0x88 },
- { .rfmax = 139000, .val = 0x8d },
- { .rfmax = 140000, .val = 0x8e },
- { .rfmax = 141000, .val = 0x91 },
- { .rfmax = 142000, .val = 0x95 },
- { .rfmax = 143000, .val = 0x9a },
- { .rfmax = 144000, .val = 0x9d },
- { .rfmax = 145000, .val = 0xa1 },
- { .rfmax = 146000, .val = 0xa2 },
- { .rfmax = 147000, .val = 0xa4 },
- { .rfmax = 148000, .val = 0xa9 },
- { .rfmax = 149000, .val = 0xae },
- { .rfmax = 150000, .val = 0xb0 },
- { .rfmax = 151000, .val = 0xb1 },
- { .rfmax = 152000, .val = 0xb7 },
- { .rfmax = 153000, .val = 0xbd },
- { .rfmax = 154000, .val = 0x20 },
- { .rfmax = 155000, .val = 0x22 },
- { .rfmax = 156000, .val = 0x24 },
- { .rfmax = 157000, .val = 0x25 },
- { .rfmax = 158000, .val = 0x27 },
- { .rfmax = 159000, .val = 0x29 },
- { .rfmax = 160000, .val = 0x2c },
- { .rfmax = 161000, .val = 0x2d },
- { .rfmax = 163000, .val = 0x2e },
- { .rfmax = 164000, .val = 0x2f },
- { .rfmax = 165000, .val = 0x30 },
- { .rfmax = 166000, .val = 0x11 },
- { .rfmax = 167000, .val = 0x12 },
- { .rfmax = 168000, .val = 0x13 },
- { .rfmax = 169000, .val = 0x14 },
- { .rfmax = 170000, .val = 0x15 },
- { .rfmax = 172000, .val = 0x16 },
- { .rfmax = 173000, .val = 0x17 },
- { .rfmax = 174000, .val = 0x18 },
- { .rfmax = 175000, .val = 0x1a },
- { .rfmax = 176000, .val = 0x1b },
- { .rfmax = 178000, .val = 0x1d },
- { .rfmax = 179000, .val = 0x1e },
- { .rfmax = 180000, .val = 0x1f },
- { .rfmax = 181000, .val = 0x20 },
- { .rfmax = 182000, .val = 0x21 },
- { .rfmax = 183000, .val = 0x22 },
- { .rfmax = 184000, .val = 0x24 },
- { .rfmax = 185000, .val = 0x25 },
- { .rfmax = 186000, .val = 0x26 },
- { .rfmax = 187000, .val = 0x27 },
- { .rfmax = 188000, .val = 0x29 },
- { .rfmax = 189000, .val = 0x2a },
- { .rfmax = 190000, .val = 0x2c },
- { .rfmax = 191000, .val = 0x2d },
- { .rfmax = 192000, .val = 0x2e },
- { .rfmax = 193000, .val = 0x2f },
- { .rfmax = 194000, .val = 0x30 },
- { .rfmax = 195000, .val = 0x33 },
- { .rfmax = 196000, .val = 0x35 },
- { .rfmax = 198000, .val = 0x36 },
- { .rfmax = 200000, .val = 0x38 },
- { .rfmax = 201000, .val = 0x3c },
- { .rfmax = 202000, .val = 0x3d },
- { .rfmax = 203500, .val = 0x3e },
- { .rfmax = 206000, .val = 0x0e },
- { .rfmax = 208000, .val = 0x0f },
- { .rfmax = 212000, .val = 0x10 },
- { .rfmax = 216000, .val = 0x11 },
- { .rfmax = 217000, .val = 0x12 },
- { .rfmax = 218000, .val = 0x13 },
- { .rfmax = 220000, .val = 0x14 },
- { .rfmax = 222000, .val = 0x15 },
- { .rfmax = 225000, .val = 0x16 },
- { .rfmax = 228000, .val = 0x17 },
- { .rfmax = 231000, .val = 0x18 },
- { .rfmax = 234000, .val = 0x19 },
- { .rfmax = 235000, .val = 0x1a },
- { .rfmax = 236000, .val = 0x1b },
- { .rfmax = 237000, .val = 0x1c },
- { .rfmax = 240000, .val = 0x1d },
- { .rfmax = 242000, .val = 0x1f },
- { .rfmax = 247000, .val = 0x20 },
- { .rfmax = 249000, .val = 0x21 },
- { .rfmax = 252000, .val = 0x22 },
- { .rfmax = 253000, .val = 0x23 },
- { .rfmax = 254000, .val = 0x24 },
- { .rfmax = 256000, .val = 0x25 },
- { .rfmax = 259000, .val = 0x26 },
- { .rfmax = 262000, .val = 0x27 },
- { .rfmax = 264000, .val = 0x28 },
- { .rfmax = 267000, .val = 0x29 },
- { .rfmax = 269000, .val = 0x2a },
- { .rfmax = 271000, .val = 0x2b },
- { .rfmax = 273000, .val = 0x2c },
- { .rfmax = 275000, .val = 0x2d },
- { .rfmax = 277000, .val = 0x2e },
- { .rfmax = 279000, .val = 0x2f },
- { .rfmax = 282000, .val = 0x30 },
- { .rfmax = 284000, .val = 0x31 },
- { .rfmax = 286000, .val = 0x32 },
- { .rfmax = 287000, .val = 0x33 },
- { .rfmax = 290000, .val = 0x34 },
- { .rfmax = 293000, .val = 0x35 },
- { .rfmax = 295000, .val = 0x36 },
- { .rfmax = 297000, .val = 0x37 },
- { .rfmax = 300000, .val = 0x38 },
- { .rfmax = 303000, .val = 0x39 },
- { .rfmax = 305000, .val = 0x3a },
- { .rfmax = 306000, .val = 0x3b },
- { .rfmax = 307000, .val = 0x3c },
- { .rfmax = 310000, .val = 0x3d },
- { .rfmax = 312000, .val = 0x3e },
- { .rfmax = 315000, .val = 0x3f },
- { .rfmax = 318000, .val = 0x40 },
- { .rfmax = 320000, .val = 0x41 },
- { .rfmax = 323000, .val = 0x42 },
- { .rfmax = 324000, .val = 0x43 },
- { .rfmax = 325000, .val = 0x44 },
- { .rfmax = 327000, .val = 0x45 },
- { .rfmax = 331000, .val = 0x46 },
- { .rfmax = 334000, .val = 0x47 },
- { .rfmax = 337000, .val = 0x48 },
- { .rfmax = 339000, .val = 0x49 },
- { .rfmax = 340000, .val = 0x4a },
- { .rfmax = 341000, .val = 0x4b },
- { .rfmax = 343000, .val = 0x4c },
- { .rfmax = 345000, .val = 0x4d },
- { .rfmax = 349000, .val = 0x4e },
- { .rfmax = 352000, .val = 0x4f },
- { .rfmax = 353000, .val = 0x50 },
- { .rfmax = 355000, .val = 0x51 },
- { .rfmax = 357000, .val = 0x52 },
- { .rfmax = 359000, .val = 0x53 },
- { .rfmax = 361000, .val = 0x54 },
- { .rfmax = 362000, .val = 0x55 },
- { .rfmax = 364000, .val = 0x56 },
- { .rfmax = 368000, .val = 0x57 },
- { .rfmax = 370000, .val = 0x58 },
- { .rfmax = 372000, .val = 0x59 },
- { .rfmax = 375000, .val = 0x5a },
- { .rfmax = 376000, .val = 0x5b },
- { .rfmax = 377000, .val = 0x5c },
- { .rfmax = 379000, .val = 0x5d },
- { .rfmax = 382000, .val = 0x5e },
- { .rfmax = 384000, .val = 0x5f },
- { .rfmax = 385000, .val = 0x60 },
- { .rfmax = 386000, .val = 0x61 },
- { .rfmax = 388000, .val = 0x62 },
- { .rfmax = 390000, .val = 0x63 },
- { .rfmax = 393000, .val = 0x64 },
- { .rfmax = 394000, .val = 0x65 },
- { .rfmax = 396000, .val = 0x66 },
- { .rfmax = 397000, .val = 0x67 },
- { .rfmax = 398000, .val = 0x68 },
- { .rfmax = 400000, .val = 0x69 },
- { .rfmax = 402000, .val = 0x6a },
- { .rfmax = 403000, .val = 0x6b },
- { .rfmax = 407000, .val = 0x6c },
- { .rfmax = 408000, .val = 0x6d },
- { .rfmax = 409000, .val = 0x6e },
- { .rfmax = 410000, .val = 0x6f },
- { .rfmax = 411000, .val = 0x70 },
- { .rfmax = 412000, .val = 0x71 },
- { .rfmax = 413000, .val = 0x72 },
- { .rfmax = 414000, .val = 0x73 },
- { .rfmax = 417000, .val = 0x74 },
- { .rfmax = 418000, .val = 0x75 },
- { .rfmax = 420000, .val = 0x76 },
- { .rfmax = 422000, .val = 0x77 },
- { .rfmax = 423000, .val = 0x78 },
- { .rfmax = 424000, .val = 0x79 },
- { .rfmax = 427000, .val = 0x7a },
- { .rfmax = 428000, .val = 0x7b },
- { .rfmax = 429000, .val = 0x7d },
- { .rfmax = 432000, .val = 0x7f },
- { .rfmax = 434000, .val = 0x80 },
- { .rfmax = 435000, .val = 0x81 },
- { .rfmax = 436000, .val = 0x83 },
- { .rfmax = 437000, .val = 0x84 },
- { .rfmax = 438000, .val = 0x85 },
- { .rfmax = 439000, .val = 0x86 },
- { .rfmax = 440000, .val = 0x87 },
- { .rfmax = 441000, .val = 0x88 },
- { .rfmax = 442000, .val = 0x89 },
- { .rfmax = 445000, .val = 0x8a },
- { .rfmax = 446000, .val = 0x8b },
- { .rfmax = 447000, .val = 0x8c },
- { .rfmax = 448000, .val = 0x8e },
- { .rfmax = 449000, .val = 0x8f },
- { .rfmax = 450000, .val = 0x90 },
- { .rfmax = 452000, .val = 0x91 },
- { .rfmax = 453000, .val = 0x93 },
- { .rfmax = 454000, .val = 0x94 },
- { .rfmax = 456000, .val = 0x96 },
- { .rfmax = 457000, .val = 0x98 },
- { .rfmax = 461000, .val = 0x11 },
- { .rfmax = 468000, .val = 0x12 },
- { .rfmax = 472000, .val = 0x13 },
- { .rfmax = 473000, .val = 0x14 },
- { .rfmax = 474000, .val = 0x15 },
- { .rfmax = 481000, .val = 0x16 },
- { .rfmax = 486000, .val = 0x17 },
- { .rfmax = 491000, .val = 0x18 },
- { .rfmax = 498000, .val = 0x19 },
- { .rfmax = 499000, .val = 0x1a },
- { .rfmax = 501000, .val = 0x1b },
- { .rfmax = 506000, .val = 0x1c },
- { .rfmax = 511000, .val = 0x1d },
- { .rfmax = 516000, .val = 0x1e },
- { .rfmax = 520000, .val = 0x1f },
- { .rfmax = 521000, .val = 0x20 },
- { .rfmax = 525000, .val = 0x21 },
- { .rfmax = 529000, .val = 0x22 },
- { .rfmax = 533000, .val = 0x23 },
- { .rfmax = 539000, .val = 0x24 },
- { .rfmax = 541000, .val = 0x25 },
- { .rfmax = 547000, .val = 0x26 },
- { .rfmax = 549000, .val = 0x27 },
- { .rfmax = 551000, .val = 0x28 },
- { .rfmax = 556000, .val = 0x29 },
- { .rfmax = 561000, .val = 0x2a },
- { .rfmax = 563000, .val = 0x2b },
- { .rfmax = 565000, .val = 0x2c },
- { .rfmax = 569000, .val = 0x2d },
- { .rfmax = 571000, .val = 0x2e },
- { .rfmax = 577000, .val = 0x2f },
- { .rfmax = 580000, .val = 0x30 },
- { .rfmax = 582000, .val = 0x31 },
- { .rfmax = 584000, .val = 0x32 },
- { .rfmax = 588000, .val = 0x33 },
- { .rfmax = 591000, .val = 0x34 },
- { .rfmax = 596000, .val = 0x35 },
- { .rfmax = 598000, .val = 0x36 },
- { .rfmax = 603000, .val = 0x37 },
- { .rfmax = 604000, .val = 0x38 },
- { .rfmax = 606000, .val = 0x39 },
- { .rfmax = 612000, .val = 0x3a },
- { .rfmax = 615000, .val = 0x3b },
- { .rfmax = 617000, .val = 0x3c },
- { .rfmax = 621000, .val = 0x3d },
- { .rfmax = 622000, .val = 0x3e },
- { .rfmax = 625000, .val = 0x3f },
- { .rfmax = 632000, .val = 0x40 },
- { .rfmax = 633000, .val = 0x41 },
- { .rfmax = 634000, .val = 0x42 },
- { .rfmax = 642000, .val = 0x43 },
- { .rfmax = 643000, .val = 0x44 },
- { .rfmax = 647000, .val = 0x45 },
- { .rfmax = 650000, .val = 0x46 },
- { .rfmax = 652000, .val = 0x47 },
- { .rfmax = 657000, .val = 0x48 },
- { .rfmax = 661000, .val = 0x49 },
- { .rfmax = 662000, .val = 0x4a },
- { .rfmax = 665000, .val = 0x4b },
- { .rfmax = 667000, .val = 0x4c },
- { .rfmax = 670000, .val = 0x4d },
- { .rfmax = 673000, .val = 0x4e },
- { .rfmax = 676000, .val = 0x4f },
- { .rfmax = 677000, .val = 0x50 },
- { .rfmax = 681000, .val = 0x51 },
- { .rfmax = 683000, .val = 0x52 },
- { .rfmax = 686000, .val = 0x53 },
- { .rfmax = 688000, .val = 0x54 },
- { .rfmax = 689000, .val = 0x55 },
- { .rfmax = 691000, .val = 0x56 },
- { .rfmax = 695000, .val = 0x57 },
- { .rfmax = 698000, .val = 0x58 },
- { .rfmax = 703000, .val = 0x59 },
- { .rfmax = 704000, .val = 0x5a },
- { .rfmax = 705000, .val = 0x5b },
- { .rfmax = 707000, .val = 0x5c },
- { .rfmax = 710000, .val = 0x5d },
- { .rfmax = 712000, .val = 0x5e },
- { .rfmax = 717000, .val = 0x5f },
- { .rfmax = 718000, .val = 0x60 },
- { .rfmax = 721000, .val = 0x61 },
- { .rfmax = 722000, .val = 0x62 },
- { .rfmax = 723000, .val = 0x63 },
- { .rfmax = 725000, .val = 0x64 },
- { .rfmax = 727000, .val = 0x65 },
- { .rfmax = 730000, .val = 0x66 },
- { .rfmax = 732000, .val = 0x67 },
- { .rfmax = 735000, .val = 0x68 },
- { .rfmax = 740000, .val = 0x69 },
- { .rfmax = 741000, .val = 0x6a },
- { .rfmax = 742000, .val = 0x6b },
- { .rfmax = 743000, .val = 0x6c },
- { .rfmax = 745000, .val = 0x6d },
- { .rfmax = 747000, .val = 0x6e },
- { .rfmax = 748000, .val = 0x6f },
- { .rfmax = 750000, .val = 0x70 },
- { .rfmax = 752000, .val = 0x71 },
- { .rfmax = 754000, .val = 0x72 },
- { .rfmax = 757000, .val = 0x73 },
- { .rfmax = 758000, .val = 0x74 },
- { .rfmax = 760000, .val = 0x75 },
- { .rfmax = 763000, .val = 0x76 },
- { .rfmax = 764000, .val = 0x77 },
- { .rfmax = 766000, .val = 0x78 },
- { .rfmax = 767000, .val = 0x79 },
- { .rfmax = 768000, .val = 0x7a },
- { .rfmax = 773000, .val = 0x7b },
- { .rfmax = 774000, .val = 0x7c },
- { .rfmax = 776000, .val = 0x7d },
- { .rfmax = 777000, .val = 0x7e },
- { .rfmax = 778000, .val = 0x7f },
- { .rfmax = 779000, .val = 0x80 },
- { .rfmax = 781000, .val = 0x81 },
- { .rfmax = 783000, .val = 0x82 },
- { .rfmax = 784000, .val = 0x83 },
- { .rfmax = 785000, .val = 0x84 },
- { .rfmax = 786000, .val = 0x85 },
- { .rfmax = 793000, .val = 0x86 },
- { .rfmax = 794000, .val = 0x87 },
- { .rfmax = 795000, .val = 0x88 },
- { .rfmax = 797000, .val = 0x89 },
- { .rfmax = 799000, .val = 0x8a },
- { .rfmax = 801000, .val = 0x8b },
- { .rfmax = 802000, .val = 0x8c },
- { .rfmax = 803000, .val = 0x8d },
- { .rfmax = 804000, .val = 0x8e },
- { .rfmax = 810000, .val = 0x90 },
- { .rfmax = 811000, .val = 0x91 },
- { .rfmax = 812000, .val = 0x92 },
- { .rfmax = 814000, .val = 0x93 },
- { .rfmax = 816000, .val = 0x94 },
- { .rfmax = 817000, .val = 0x96 },
- { .rfmax = 818000, .val = 0x97 },
- { .rfmax = 820000, .val = 0x98 },
- { .rfmax = 821000, .val = 0x99 },
- { .rfmax = 822000, .val = 0x9a },
- { .rfmax = 828000, .val = 0x9b },
- { .rfmax = 829000, .val = 0x9d },
- { .rfmax = 830000, .val = 0x9f },
- { .rfmax = 831000, .val = 0xa0 },
- { .rfmax = 833000, .val = 0xa1 },
- { .rfmax = 835000, .val = 0xa2 },
- { .rfmax = 836000, .val = 0xa3 },
- { .rfmax = 837000, .val = 0xa4 },
- { .rfmax = 838000, .val = 0xa6 },
- { .rfmax = 840000, .val = 0xa8 },
- { .rfmax = 842000, .val = 0xa9 },
- { .rfmax = 845000, .val = 0xaa },
- { .rfmax = 846000, .val = 0xab },
- { .rfmax = 847000, .val = 0xad },
- { .rfmax = 848000, .val = 0xae },
- { .rfmax = 852000, .val = 0xaf },
- { .rfmax = 853000, .val = 0xb0 },
- { .rfmax = 858000, .val = 0xb1 },
- { .rfmax = 860000, .val = 0xb2 },
- { .rfmax = 861000, .val = 0xb3 },
- { .rfmax = 862000, .val = 0xb4 },
- { .rfmax = 863000, .val = 0xb6 },
- { .rfmax = 864000, .val = 0xb8 },
- { .rfmax = 865000, .val = 0xb9 },
- { .rfmax = 0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271_ir_measure[] = {
- { .rfmax = 30000, .val = 4 },
- { .rfmax = 200000, .val = 5 },
- { .rfmax = 600000, .val = 6 },
- { .rfmax = 865000, .val = 7 },
- { .rfmax = 0, .val = 0 }, /* end */
-};
-
-static struct tda18271_map tda18271_rf_cal_dc_over_dt[] = {
- { .rfmax = 47900, .val = 0x00 },
- { .rfmax = 55000, .val = 0x00 },
- { .rfmax = 61100, .val = 0x0a },
- { .rfmax = 64000, .val = 0x0a },
- { .rfmax = 82000, .val = 0x14 },
- { .rfmax = 84000, .val = 0x19 },
- { .rfmax = 119000, .val = 0x1c },
- { .rfmax = 124000, .val = 0x20 },
- { .rfmax = 129000, .val = 0x2a },
- { .rfmax = 134000, .val = 0x32 },
- { .rfmax = 139000, .val = 0x39 },
- { .rfmax = 144000, .val = 0x3e },
- { .rfmax = 149000, .val = 0x3f },
- { .rfmax = 152600, .val = 0x40 },
- { .rfmax = 154000, .val = 0x40 },
- { .rfmax = 164700, .val = 0x41 },
- { .rfmax = 203500, .val = 0x32 },
- { .rfmax = 353000, .val = 0x19 },
- { .rfmax = 356000, .val = 0x1a },
- { .rfmax = 359000, .val = 0x1b },
- { .rfmax = 363000, .val = 0x1c },
- { .rfmax = 366000, .val = 0x1d },
- { .rfmax = 369000, .val = 0x1e },
- { .rfmax = 373000, .val = 0x1f },
- { .rfmax = 376000, .val = 0x20 },
- { .rfmax = 379000, .val = 0x21 },
- { .rfmax = 383000, .val = 0x22 },
- { .rfmax = 386000, .val = 0x23 },
- { .rfmax = 389000, .val = 0x24 },
- { .rfmax = 393000, .val = 0x25 },
- { .rfmax = 396000, .val = 0x26 },
- { .rfmax = 399000, .val = 0x27 },
- { .rfmax = 402000, .val = 0x28 },
- { .rfmax = 404000, .val = 0x29 },
- { .rfmax = 407000, .val = 0x2a },
- { .rfmax = 409000, .val = 0x2b },
- { .rfmax = 412000, .val = 0x2c },
- { .rfmax = 414000, .val = 0x2d },
- { .rfmax = 417000, .val = 0x2e },
- { .rfmax = 419000, .val = 0x2f },
- { .rfmax = 422000, .val = 0x30 },
- { .rfmax = 424000, .val = 0x31 },
- { .rfmax = 427000, .val = 0x32 },
- { .rfmax = 429000, .val = 0x33 },
- { .rfmax = 432000, .val = 0x34 },
- { .rfmax = 434000, .val = 0x35 },
- { .rfmax = 437000, .val = 0x36 },
- { .rfmax = 439000, .val = 0x37 },
- { .rfmax = 442000, .val = 0x38 },
- { .rfmax = 444000, .val = 0x39 },
- { .rfmax = 447000, .val = 0x3a },
- { .rfmax = 449000, .val = 0x3b },
- { .rfmax = 457800, .val = 0x3c },
- { .rfmax = 465000, .val = 0x0f },
- { .rfmax = 477000, .val = 0x12 },
- { .rfmax = 483000, .val = 0x14 },
- { .rfmax = 502000, .val = 0x19 },
- { .rfmax = 508000, .val = 0x1b },
- { .rfmax = 519000, .val = 0x1c },
- { .rfmax = 522000, .val = 0x1d },
- { .rfmax = 524000, .val = 0x1e },
- { .rfmax = 534000, .val = 0x1f },
- { .rfmax = 549000, .val = 0x20 },
- { .rfmax = 554000, .val = 0x22 },
- { .rfmax = 584000, .val = 0x24 },
- { .rfmax = 589000, .val = 0x26 },
- { .rfmax = 658000, .val = 0x27 },
- { .rfmax = 664000, .val = 0x2c },
- { .rfmax = 669000, .val = 0x2d },
- { .rfmax = 699000, .val = 0x2e },
- { .rfmax = 704000, .val = 0x30 },
- { .rfmax = 709000, .val = 0x31 },
- { .rfmax = 714000, .val = 0x32 },
- { .rfmax = 724000, .val = 0x33 },
- { .rfmax = 729000, .val = 0x36 },
- { .rfmax = 739000, .val = 0x38 },
- { .rfmax = 744000, .val = 0x39 },
- { .rfmax = 749000, .val = 0x3b },
- { .rfmax = 754000, .val = 0x3c },
- { .rfmax = 759000, .val = 0x3d },
- { .rfmax = 764000, .val = 0x3e },
- { .rfmax = 769000, .val = 0x3f },
- { .rfmax = 774000, .val = 0x40 },
- { .rfmax = 779000, .val = 0x41 },
- { .rfmax = 784000, .val = 0x43 },
- { .rfmax = 789000, .val = 0x46 },
- { .rfmax = 794000, .val = 0x48 },
- { .rfmax = 799000, .val = 0x4b },
- { .rfmax = 804000, .val = 0x4f },
- { .rfmax = 809000, .val = 0x54 },
- { .rfmax = 814000, .val = 0x59 },
- { .rfmax = 819000, .val = 0x5d },
- { .rfmax = 824000, .val = 0x61 },
- { .rfmax = 829000, .val = 0x68 },
- { .rfmax = 834000, .val = 0x6e },
- { .rfmax = 839000, .val = 0x75 },
- { .rfmax = 844000, .val = 0x7e },
- { .rfmax = 849000, .val = 0x82 },
- { .rfmax = 854000, .val = 0x84 },
- { .rfmax = 859000, .val = 0x8f },
- { .rfmax = 865000, .val = 0x9a },
- { .rfmax = 0, .val = 0x00 }, /* end */
-};
-
-/*---------------------------------------------------------------------*/
-
-struct tda18271_thermo_map {
- u8 d;
- u8 r0;
- u8 r1;
-};
-
-static struct tda18271_thermo_map tda18271_thermometer[] = {
- { .d = 0x00, .r0 = 60, .r1 = 92 },
- { .d = 0x01, .r0 = 62, .r1 = 94 },
- { .d = 0x02, .r0 = 66, .r1 = 98 },
- { .d = 0x03, .r0 = 64, .r1 = 96 },
- { .d = 0x04, .r0 = 74, .r1 = 106 },
- { .d = 0x05, .r0 = 72, .r1 = 104 },
- { .d = 0x06, .r0 = 68, .r1 = 100 },
- { .d = 0x07, .r0 = 70, .r1 = 102 },
- { .d = 0x08, .r0 = 90, .r1 = 122 },
- { .d = 0x09, .r0 = 88, .r1 = 120 },
- { .d = 0x0a, .r0 = 84, .r1 = 116 },
- { .d = 0x0b, .r0 = 86, .r1 = 118 },
- { .d = 0x0c, .r0 = 76, .r1 = 108 },
- { .d = 0x0d, .r0 = 78, .r1 = 110 },
- { .d = 0x0e, .r0 = 82, .r1 = 114 },
- { .d = 0x0f, .r0 = 80, .r1 = 112 },
- { .d = 0x00, .r0 = 0, .r1 = 0 }, /* end */
-};
-
-int tda18271_lookup_thermometer(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- unsigned char *regs = priv->tda18271_regs;
- int val, i = 0;
-
- while (tda18271_thermometer[i].d < (regs[R_TM] & 0x0f)) {
- if (tda18271_thermometer[i + 1].d == 0)
- break;
- i++;
- }
-
- if ((regs[R_TM] & 0x20) == 0x20)
- val = tda18271_thermometer[i].r1;
- else
- val = tda18271_thermometer[i].r0;
-
- tda_map("(%d) tm = %d\n", i, val);
-
- return val;
-}
-
-/*---------------------------------------------------------------------*/
-
-struct tda18271_cid_target_map {
- u32 rfmax;
- u8 target;
- u16 limit;
-};
-
-static struct tda18271_cid_target_map tda18271_cid_target[] = {
- { .rfmax = 46000, .target = 0x04, .limit = 1800 },
- { .rfmax = 52200, .target = 0x0a, .limit = 1500 },
- { .rfmax = 79100, .target = 0x01, .limit = 4000 },
- { .rfmax = 136800, .target = 0x18, .limit = 4000 },
- { .rfmax = 156700, .target = 0x18, .limit = 4000 },
- { .rfmax = 156700, .target = 0x18, .limit = 4000 },
- { .rfmax = 186250, .target = 0x0a, .limit = 4000 },
- { .rfmax = 230000, .target = 0x0a, .limit = 4000 },
- { .rfmax = 345000, .target = 0x18, .limit = 4000 },
- { .rfmax = 426000, .target = 0x0e, .limit = 4000 },
- { .rfmax = 489500, .target = 0x1e, .limit = 4000 },
- { .rfmax = 697500, .target = 0x32, .limit = 4000 },
- { .rfmax = 842000, .target = 0x3a, .limit = 4000 },
- { .rfmax = 0, .target = 0x00, .limit = 0 }, /* end */
-};
-
-int tda18271_lookup_cid_target(struct dvb_frontend *fe,
- u32 *freq, u8 *cid_target, u16 *count_limit)
-{
- int i = 0;
-
- while ((tda18271_cid_target[i].rfmax * 1000) < *freq) {
- if (tda18271_cid_target[i + 1].rfmax == 0)
- break;
- i++;
- }
- *cid_target = tda18271_cid_target[i].target;
- *count_limit = tda18271_cid_target[i].limit;
-
- tda_map("(%d) cid_target = %02x, count_limit = %d\n", i,
- tda18271_cid_target[i].target, tda18271_cid_target[i].limit);
-
- return 0;
-}
-
-/*---------------------------------------------------------------------*/
-
-static struct tda18271_rf_tracking_filter_cal tda18271_rf_band_template[] = {
- { .rfmax = 47900, .rfband = 0x00,
- .rf1_def = 46000, .rf2_def = 0, .rf3_def = 0 },
- { .rfmax = 61100, .rfband = 0x01,
- .rf1_def = 52200, .rf2_def = 0, .rf3_def = 0 },
- { .rfmax = 152600, .rfband = 0x02,
- .rf1_def = 70100, .rf2_def = 136800, .rf3_def = 0 },
- { .rfmax = 164700, .rfband = 0x03,
- .rf1_def = 156700, .rf2_def = 0, .rf3_def = 0 },
- { .rfmax = 203500, .rfband = 0x04,
- .rf1_def = 186250, .rf2_def = 0, .rf3_def = 0 },
- { .rfmax = 457800, .rfband = 0x05,
- .rf1_def = 230000, .rf2_def = 345000, .rf3_def = 426000 },
- { .rfmax = 865000, .rfband = 0x06,
- .rf1_def = 489500, .rf2_def = 697500, .rf3_def = 842000 },
- { .rfmax = 0, .rfband = 0x00,
- .rf1_def = 0, .rf2_def = 0, .rf3_def = 0 }, /* end */
-};
-
-int tda18271_lookup_rf_band(struct dvb_frontend *fe, u32 *freq, u8 *rf_band)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
- int i = 0;
-
- while ((map[i].rfmax * 1000) < *freq) {
- if (tda18271_debug & DBG_ADV)
- tda_map("(%d) rfmax = %d < freq = %d, "
- "rf1_def = %d, rf2_def = %d, rf3_def = %d, "
- "rf1 = %d, rf2 = %d, rf3 = %d, "
- "rf_a1 = %d, rf_a2 = %d, "
- "rf_b1 = %d, rf_b2 = %d\n",
- i, map[i].rfmax * 1000, *freq,
- map[i].rf1_def, map[i].rf2_def, map[i].rf3_def,
- map[i].rf1, map[i].rf2, map[i].rf3,
- map[i].rf_a1, map[i].rf_a2,
- map[i].rf_b1, map[i].rf_b2);
- if (map[i].rfmax == 0)
- return -EINVAL;
- i++;
- }
- if (rf_band)
- *rf_band = map[i].rfband;
-
- tda_map("(%d) rf_band = %02x\n", i, map[i].rfband);
-
- return i;
-}
-
-/*---------------------------------------------------------------------*/
-
-struct tda18271_map_layout {
- struct tda18271_pll_map *main_pll;
- struct tda18271_pll_map *cal_pll;
-
- struct tda18271_map *rf_cal;
- struct tda18271_map *rf_cal_kmco;
- struct tda18271_map *rf_cal_dc_over_dt;
-
- struct tda18271_map *bp_filter;
- struct tda18271_map *rf_band;
- struct tda18271_map *gain_taper;
- struct tda18271_map *ir_measure;
-};
-
-/*---------------------------------------------------------------------*/
-
-int tda18271_lookup_pll_map(struct dvb_frontend *fe,
- enum tda18271_map_type map_type,
- u32 *freq, u8 *post_div, u8 *div)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- struct tda18271_pll_map *map = NULL;
- unsigned int i = 0;
- char *map_name;
- int ret = 0;
-
- BUG_ON(!priv->maps);
-
- switch (map_type) {
- case MAIN_PLL:
- map = priv->maps->main_pll;
- map_name = "main_pll";
- break;
- case CAL_PLL:
- map = priv->maps->cal_pll;
- map_name = "cal_pll";
- break;
- default:
- /* we should never get here */
- map_name = "undefined";
- break;
- }
-
- if (!map) {
- tda_warn("%s map is not set!\n", map_name);
- ret = -EINVAL;
- goto fail;
- }
-
- while ((map[i].lomax * 1000) < *freq) {
- if (map[i + 1].lomax == 0) {
- tda_map("%s: frequency (%d) out of range\n",
- map_name, *freq);
- ret = -ERANGE;
- break;
- }
- i++;
- }
- *post_div = map[i].pd;
- *div = map[i].d;
-
- tda_map("(%d) %s: post div = 0x%02x, div = 0x%02x\n",
- i, map_name, *post_div, *div);
-fail:
- return ret;
-}
-
-int tda18271_lookup_map(struct dvb_frontend *fe,
- enum tda18271_map_type map_type,
- u32 *freq, u8 *val)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- struct tda18271_map *map = NULL;
- unsigned int i = 0;
- char *map_name;
- int ret = 0;
-
- BUG_ON(!priv->maps);
-
- switch (map_type) {
- case BP_FILTER:
- map = priv->maps->bp_filter;
- map_name = "bp_filter";
- break;
- case RF_CAL_KMCO:
- map = priv->maps->rf_cal_kmco;
- map_name = "km";
- break;
- case RF_BAND:
- map = priv->maps->rf_band;
- map_name = "rf_band";
- break;
- case GAIN_TAPER:
- map = priv->maps->gain_taper;
- map_name = "gain_taper";
- break;
- case RF_CAL:
- map = priv->maps->rf_cal;
- map_name = "rf_cal";
- break;
- case IR_MEASURE:
- map = priv->maps->ir_measure;
- map_name = "ir_measure";
- break;
- case RF_CAL_DC_OVER_DT:
- map = priv->maps->rf_cal_dc_over_dt;
- map_name = "rf_cal_dc_over_dt";
- break;
- default:
- /* we should never get here */
- map_name = "undefined";
- break;
- }
-
- if (!map) {
- tda_warn("%s map is not set!\n", map_name);
- ret = -EINVAL;
- goto fail;
- }
-
- while ((map[i].rfmax * 1000) < *freq) {
- if (map[i + 1].rfmax == 0) {
- tda_map("%s: frequency (%d) out of range\n",
- map_name, *freq);
- ret = -ERANGE;
- break;
- }
- i++;
- }
- *val = map[i].val;
-
- tda_map("(%d) %s: 0x%02x\n", i, map_name, *val);
-fail:
- return ret;
-}
-
-/*---------------------------------------------------------------------*/
-
-static struct tda18271_std_map tda18271c1_std_map = {
- .fm_radio = { .if_freq = 1250, .std_bits = 0x18 },
- .atv_b = { .if_freq = 6750, .std_bits = 0x0e },
- .atv_dk = { .if_freq = 7750, .std_bits = 0x0f },
- .atv_gh = { .if_freq = 7750, .std_bits = 0x0f },
- .atv_i = { .if_freq = 7750, .std_bits = 0x0f },
- .atv_l = { .if_freq = 7750, .std_bits = 0x0f },
- .atv_lc = { .if_freq = 1250, .std_bits = 0x0f },
- .atv_mn = { .if_freq = 5750, .std_bits = 0x0d },
- .atsc_6 = { .if_freq = 3250, .std_bits = 0x1c },
- .dvbt_6 = { .if_freq = 3300, .std_bits = 0x1c },
- .dvbt_7 = { .if_freq = 3800, .std_bits = 0x1d },
- .dvbt_8 = { .if_freq = 4300, .std_bits = 0x1e },
- .qam_6 = { .if_freq = 4000, .std_bits = 0x1d },
- .qam_8 = { .if_freq = 5000, .std_bits = 0x1f },
-};
-
-static struct tda18271_std_map tda18271c2_std_map = {
- .fm_radio = { .if_freq = 1250, .std_bits = 0x18 },
- .atv_b = { .if_freq = 6000, .std_bits = 0x0d },
- .atv_dk = { .if_freq = 6900, .std_bits = 0x0e },
- .atv_gh = { .if_freq = 7100, .std_bits = 0x0e },
- .atv_i = { .if_freq = 7250, .std_bits = 0x0e },
- .atv_l = { .if_freq = 6900, .std_bits = 0x0e },
- .atv_lc = { .if_freq = 1250, .std_bits = 0x0e },
- .atv_mn = { .if_freq = 5400, .std_bits = 0x0c },
- .atsc_6 = { .if_freq = 3250, .std_bits = 0x1c },
- .dvbt_6 = { .if_freq = 3300, .std_bits = 0x1c },
- .dvbt_7 = { .if_freq = 3500, .std_bits = 0x1c },
- .dvbt_8 = { .if_freq = 4000, .std_bits = 0x1d },
- .qam_6 = { .if_freq = 4000, .std_bits = 0x1d },
- .qam_8 = { .if_freq = 5000, .std_bits = 0x1f },
-};
-
-/*---------------------------------------------------------------------*/
-
-static struct tda18271_map_layout tda18271c1_map_layout = {
- .main_pll = tda18271c1_main_pll,
- .cal_pll = tda18271c1_cal_pll,
-
- .rf_cal = tda18271c1_rf_cal,
- .rf_cal_kmco = tda18271c1_km,
-
- .bp_filter = tda18271_bp_filter,
- .rf_band = tda18271_rf_band,
- .gain_taper = tda18271_gain_taper,
- .ir_measure = tda18271_ir_measure,
-};
-
-static struct tda18271_map_layout tda18271c2_map_layout = {
- .main_pll = tda18271c2_main_pll,
- .cal_pll = tda18271c2_cal_pll,
-
- .rf_cal = tda18271c2_rf_cal,
- .rf_cal_kmco = tda18271c2_km,
-
- .rf_cal_dc_over_dt = tda18271_rf_cal_dc_over_dt,
-
- .bp_filter = tda18271_bp_filter,
- .rf_band = tda18271_rf_band,
- .gain_taper = tda18271_gain_taper,
- .ir_measure = tda18271_ir_measure,
-};
-
-int tda18271_assign_map_layout(struct dvb_frontend *fe)
-{
- struct tda18271_priv *priv = fe->tuner_priv;
- int ret = 0;
-
- switch (priv->id) {
- case TDA18271HDC1:
- priv->maps = &tda18271c1_map_layout;
- memcpy(&priv->std, &tda18271c1_std_map,
- sizeof(struct tda18271_std_map));
- break;
- case TDA18271HDC2:
- priv->maps = &tda18271c2_map_layout;
- memcpy(&priv->std, &tda18271c2_std_map,
- sizeof(struct tda18271_std_map));
- break;
- default:
- ret = -EINVAL;
- break;
- }
- memcpy(priv->rf_cal_state, &tda18271_rf_band_template,
- sizeof(tda18271_rf_band_template));
-
- return ret;
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/trunk/drivers/media/dvb/frontends/tda18271.h b/trunk/drivers/media/dvb/frontends/tda18271.h
deleted file mode 100644
index 24b0e35a2ab3..000000000000
--- a/trunk/drivers/media/dvb/frontends/tda18271.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- tda18271.h - header for the Philips / NXP TDA18271 silicon tuner
-
- Copyright (C) 2007, 2008 Michael Krufky
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __TDA18271_H__
-#define __TDA18271_H__
-
-#include
-#include "dvb_frontend.h"
-
-struct tda18271_std_map_item {
- u16 if_freq;
- u8 std_bits;
-};
-
-struct tda18271_std_map {
- struct tda18271_std_map_item fm_radio;
- struct tda18271_std_map_item atv_b;
- struct tda18271_std_map_item atv_dk;
- struct tda18271_std_map_item atv_gh;
- struct tda18271_std_map_item atv_i;
- struct tda18271_std_map_item atv_l;
- struct tda18271_std_map_item atv_lc;
- struct tda18271_std_map_item atv_mn;
- struct tda18271_std_map_item atsc_6;
- struct tda18271_std_map_item dvbt_6;
- struct tda18271_std_map_item dvbt_7;
- struct tda18271_std_map_item dvbt_8;
- struct tda18271_std_map_item qam_6;
- struct tda18271_std_map_item qam_8;
-};
-
-enum tda18271_i2c_gate {
- TDA18271_GATE_AUTO = 0,
- TDA18271_GATE_ANALOG,
- TDA18271_GATE_DIGITAL,
-};
-
-struct tda18271_config {
- /* override default if freq / std settings (optional) */
- struct tda18271_std_map *std_map;
-
- /* use i2c gate provided by analog or digital demod */
- enum tda18271_i2c_gate gate;
-};
-
-#if defined(CONFIG_DVB_TDA18271) || (defined(CONFIG_DVB_TDA18271_MODULE) && defined(MODULE))
-extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
- struct i2c_adapter *i2c,
- struct tda18271_config *cfg);
-#else
-static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe,
- u8 addr,
- struct i2c_adapter *i2c,
- struct tda18271_config *cfg)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
- return NULL;
-}
-#endif
-
-#endif /* __TDA18271_H__ */
diff --git a/trunk/drivers/media/dvb/frontends/tda827x.c b/trunk/drivers/media/dvb/frontends/tda827x.c
index 229b11987a58..256fc4bf500b 100644
--- a/trunk/drivers/media/dvb/frontends/tda827x.c
+++ b/trunk/drivers/media/dvb/frontends/tda827x.c
@@ -19,16 +19,12 @@
*/
#include
-#include
#include
-#include
+#include
#include "tda827x.h"
static int debug = 0;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
#define dprintk(args...) \
do { \
if (debug) printk(KERN_DEBUG "tda827x: " args); \
@@ -38,57 +34,10 @@ struct tda827x_priv {
int i2c_addr;
struct i2c_adapter *i2c_adap;
struct tda827x_config *cfg;
-
- unsigned int sgIF;
- unsigned char lpsel;
-
u32 frequency;
u32 bandwidth;
};
-static void tda827x_set_std(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct tda827x_priv *priv = fe->tuner_priv;
- char *mode;
-
- priv->lpsel = 0;
- if (params->std & V4L2_STD_MN) {
- priv->sgIF = 92;
- priv->lpsel = 1;
- mode = "MN";
- } else if (params->std & V4L2_STD_B) {
- priv->sgIF = 108;
- mode = "B";
- } else if (params->std & V4L2_STD_GH) {
- priv->sgIF = 124;
- mode = "GH";
- } else if (params->std & V4L2_STD_PAL_I) {
- priv->sgIF = 124;
- mode = "I";
- } else if (params->std & V4L2_STD_DK) {
- priv->sgIF = 124;
- mode = "DK";
- } else if (params->std & V4L2_STD_SECAM_L) {
- priv->sgIF = 124;
- mode = "L";
- } else if (params->std & V4L2_STD_SECAM_LC) {
- priv->sgIF = 20;
- mode = "LC";
- } else {
- priv->sgIF = 124;
- mode = "xx";
- }
-
- if (params->mode == V4L2_TUNER_RADIO)
- priv->sgIF = 88; /* if frequency is 5.5 MHz */
-
- dprintk("setting tda827x to system %s\n", mode);
-}
-
-
-/* ------------------------------------------------------------------ */
-
struct tda827x_data {
u32 lomax;
u8 spd;
@@ -99,7 +48,7 @@ struct tda827x_data {
u8 div1p5;
};
-static const struct tda827x_data tda827x_table[] = {
+static const struct tda827x_data tda827x_dvbt[] = {
{ .lomax = 62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
{ .lomax = 66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
{ .lomax = 76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
@@ -157,22 +106,21 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
tuner_freq = params->frequency + if_freq;
i = 0;
- while (tda827x_table[i].lomax < tuner_freq) {
- if (tda827x_table[i + 1].lomax == 0)
+ while (tda827x_dvbt[i].lomax < tuner_freq) {
+ if(tda827x_dvbt[i + 1].lomax == 0)
break;
i++;
}
- N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
+ N = ((tuner_freq + 125000) / 250000) << (tda827x_dvbt[i].spd + 2);
buf[0] = 0;
buf[1] = (N>>8) | 0x40;
buf[2] = N & 0xff;
buf[3] = 0;
buf[4] = 0x52;
- buf[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) +
- (tda827x_table[i].bs << 3) +
- tda827x_table[i].bp;
- buf[6] = (tda827x_table[i].gc3 << 4) + 0x8f;
+ buf[5] = (tda827x_dvbt[i].spd << 6) + (tda827x_dvbt[i].div1p5 << 5) +
+ (tda827x_dvbt[i].bs << 3) + tda827x_dvbt[i].bp;
+ buf[6] = (tda827x_dvbt[i].gc3 << 4) + 0x8f;
buf[7] = 0xbf;
buf[8] = 0x2a;
buf[9] = 0x05;
@@ -192,7 +140,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
msleep(500);
/* correct CP value */
buf[0] = 0x30;
- buf[1] = 0x50 + tda827x_table[i].cp;
+ buf[1] = 0x50 + tda827x_dvbt[i].cp;
msg.len = 2;
if (fe->ops.i2c_gate_ctrl)
@@ -225,102 +173,6 @@ static int tda827xo_sleep(struct dvb_frontend *fe)
/* ------------------------------------------------------------------ */
-static int tda827xo_set_analog_params(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- unsigned char tuner_reg[8];
- unsigned char reg2[2];
- u32 N;
- int i;
- struct tda827x_priv *priv = fe->tuner_priv;
- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 };
- unsigned int freq = params->frequency;
-
- tda827x_set_std(fe, params);
-
- if (params->mode == V4L2_TUNER_RADIO)
- freq = freq / 1000;
-
- N = freq + priv->sgIF;
-
- i = 0;
- while (tda827x_table[i].lomax < N * 62500) {
- if (tda827x_table[i + 1].lomax == 0)
- break;
- i++;
- }
-
- N = N << tda827x_table[i].spd;
-
- tuner_reg[0] = 0;
- tuner_reg[1] = (unsigned char)(N>>8);
- tuner_reg[2] = (unsigned char) N;
- tuner_reg[3] = 0x40;
- tuner_reg[4] = 0x52 + (priv->lpsel << 5);
- tuner_reg[5] = (tda827x_table[i].spd << 6) +
- (tda827x_table[i].div1p5 << 5) +
- (tda827x_table[i].bs << 3) + tda827x_table[i].bp;
- tuner_reg[6] = 0x8f + (tda827x_table[i].gc3 << 4);
- tuner_reg[7] = 0x8f;
-
- msg.buf = tuner_reg;
- msg.len = 8;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- msg.buf = reg2;
- msg.len = 2;
- reg2[0] = 0x80;
- reg2[1] = 0;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- reg2[0] = 0x60;
- reg2[1] = 0xbf;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- reg2[0] = 0x30;
- reg2[1] = tuner_reg[4] + 0x80;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- msleep(1);
- reg2[0] = 0x30;
- reg2[1] = tuner_reg[4] + 4;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- msleep(1);
- reg2[0] = 0x30;
- reg2[1] = tuner_reg[4];
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- msleep(550);
- reg2[0] = 0x30;
- reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- reg2[0] = 0x60;
- reg2[1] = 0x3f;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- reg2[0] = 0x80;
- reg2[1] = 0x08; /* Vsync en */
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- priv->frequency = freq * 62500;
-
- return 0;
-}
-
-static void tda827xo_agcf(struct dvb_frontend *fe)
-{
- struct tda827x_priv *priv = fe->tuner_priv;
- unsigned char data[] = { 0x80, 0x0c };
- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
- .buf = data, .len = 2};
-
- i2c_transfer(priv->i2c_adap, &msg, 1);
-}
-
-/* ------------------------------------------------------------------ */
-
struct tda827xa_data {
u32 lomax;
u8 svco;
@@ -360,35 +212,6 @@ static const struct tda827xa_data tda827xa_dvbt[] = {
{ .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
};
-static struct tda827xa_data tda827xa_analog[] = {
- { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3},
- { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
- { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
- { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
- { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
- { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
- { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
- { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
- { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
- { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
- { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3},
- { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3},
- { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
- { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
- { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
- { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
- { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
- { .lomax = 554000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
- { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
- { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
- { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
- { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
- { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
- { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
- { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
- { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
-};
-
static int tda827xa_set_params(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
{
@@ -545,163 +368,6 @@ static int tda827xa_sleep(struct dvb_frontend *fe)
return 0;
}
-/* ------------------------------------------------------------------ */
-
-static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
- struct analog_parameters *params)
-{
- struct tda827x_priv *priv = fe->tuner_priv;
- unsigned char buf[] = {0x22, 0x01};
- int arg;
- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
- .buf = buf, .len = sizeof(buf) };
-
- if (NULL == priv->cfg) {
- dprintk("tda827x_config not defined, cannot set LNA gain!\n");
- return;
- }
-
- if (priv->cfg->config) {
- if (high)
- dprintk("setting LNA to high gain\n");
- else
- dprintk("setting LNA to low gain\n");
- }
- switch (*priv->cfg->config) {
- case 0: /* no LNA */
- break;
- case 1: /* switch is GPIO 0 of tda8290 */
- case 2:
- /* turn Vsync on */
- if (params->std & V4L2_STD_MN)
- arg = 1;
- else
- arg = 0;
- if (priv->cfg->tuner_callback)
- priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
- 1, arg);
- buf[1] = high ? 0 : 1;
- if (*priv->cfg->config == 2)
- buf[1] = high ? 1 : 0;
- i2c_transfer(priv->i2c_adap, &msg, 1);
- break;
- case 3: /* switch with GPIO of saa713x */
- if (priv->cfg->tuner_callback)
- priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
- 0, high);
- break;
- }
-}
-
-static int tda827xa_set_analog_params(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- unsigned char tuner_reg[11];
- u32 N;
- int i;
- struct tda827x_priv *priv = fe->tuner_priv;
- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
- .buf = tuner_reg, .len = sizeof(tuner_reg) };
- unsigned int freq = params->frequency;
-
- tda827x_set_std(fe, params);
-
- tda827xa_lna_gain(fe, 1, params);
- msleep(10);
-
- if (params->mode == V4L2_TUNER_RADIO)
- freq = freq / 1000;
-
- N = freq + priv->sgIF;
-
- i = 0;
- while (tda827xa_analog[i].lomax < N * 62500) {
- if (tda827xa_analog[i + 1].lomax == 0)
- break;
- i++;
- }
-
- N = N << tda827xa_analog[i].spd;
-
- tuner_reg[0] = 0;
- tuner_reg[1] = (unsigned char)(N>>8);
- tuner_reg[2] = (unsigned char) N;
- tuner_reg[3] = 0;
- tuner_reg[4] = 0x16;
- tuner_reg[5] = (tda827xa_analog[i].spd << 5) +
- (tda827xa_analog[i].svco << 3) +
- tda827xa_analog[i].sbs;
- tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4);
- tuner_reg[7] = 0x1c;
- tuner_reg[8] = 4;
- tuner_reg[9] = 0x20;
- tuner_reg[10] = 0x00;
- msg.len = 11;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- tuner_reg[0] = 0x90;
- tuner_reg[1] = 0xff;
- tuner_reg[2] = 0xe0;
- tuner_reg[3] = 0;
- tuner_reg[4] = 0x99 + (priv->lpsel << 1);
- msg.len = 5;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- tuner_reg[0] = 0xa0;
- tuner_reg[1] = 0xc0;
- msg.len = 2;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- tuner_reg[0] = 0x30;
- tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- msg.flags = I2C_M_RD;
- i2c_transfer(priv->i2c_adap, &msg, 1);
- msg.flags = 0;
- tuner_reg[1] >>= 4;
- dprintk("AGC2 gain is: %d\n", tuner_reg[1]);
- if (tuner_reg[1] < 1)
- tda827xa_lna_gain(fe, 0, params);
-
- msleep(100);
- tuner_reg[0] = 0x60;
- tuner_reg[1] = 0x3c;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- msleep(163);
- tuner_reg[0] = 0x50;
- tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- tuner_reg[0] = 0x80;
- tuner_reg[1] = 0x28;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- tuner_reg[0] = 0xb0;
- tuner_reg[1] = 0x01;
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- tuner_reg[0] = 0xc0;
- tuner_reg[1] = 0x19 + (priv->lpsel << 1);
- i2c_transfer(priv->i2c_adap, &msg, 1);
-
- priv->frequency = freq * 62500;
-
- return 0;
-}
-
-static void tda827xa_agcf(struct dvb_frontend *fe)
-{
- struct tda827x_priv *priv = fe->tuner_priv;
- unsigned char data[] = {0x80, 0x2c};
- struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
- .buf = data, .len = 2};
- i2c_transfer(priv->i2c_adap, &msg, 1);
-}
-
-/* ------------------------------------------------------------------ */
-
static int tda827x_release(struct dvb_frontend *fe)
{
kfree(fe->tuner_priv);
@@ -764,7 +430,6 @@ static struct dvb_tuner_ops tda827xo_tuner_ops = {
.init = tda827x_initial_init,
.sleep = tda827x_initial_sleep,
.set_params = tda827xo_set_params,
- .set_analog_params = tda827xo_set_analog_params,
.get_frequency = tda827x_get_frequency,
.get_bandwidth = tda827x_get_bandwidth,
};
@@ -780,7 +445,6 @@ static struct dvb_tuner_ops tda827xa_tuner_ops = {
.init = tda827x_init,
.sleep = tda827xa_sleep,
.set_params = tda827xa_set_params,
- .set_analog_params = tda827xa_set_analog_params,
.get_frequency = tda827x_get_frequency,
.get_bandwidth = tda827x_get_bandwidth,
};
@@ -801,13 +465,9 @@ static int tda827x_probe_version(struct dvb_frontend *fe)
dprintk("tda827x tuner found\n");
fe->ops.tuner_ops.init = tda827x_init;
fe->ops.tuner_ops.sleep = tda827xo_sleep;
- if (priv->cfg)
- priv->cfg->agcf = tda827xo_agcf;
} else {
dprintk("tda827xa tuner found\n");
memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops));
- if (priv->cfg)
- priv->cfg->agcf = tda827xa_agcf;
}
return 0;
}
@@ -827,13 +487,16 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
priv->i2c_adap = i2c;
priv->cfg = cfg;
memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops));
- fe->tuner_priv = priv;
- dprintk("type set to %s\n", fe->ops.tuner_ops.info.name);
+ fe->tuner_priv = priv;
return fe;
}
-EXPORT_SYMBOL_GPL(tda827x_attach);
+
+EXPORT_SYMBOL(tda827x_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
MODULE_DESCRIPTION("DVB TDA827x driver");
MODULE_AUTHOR("Hartmut Hackmann ");
diff --git a/trunk/drivers/media/dvb/frontends/tda827x.h b/trunk/drivers/media/dvb/frontends/tda827x.h
index 92eb65b4012b..69e8263d6d59 100644
--- a/trunk/drivers/media/dvb/frontends/tda827x.h
+++ b/trunk/drivers/media/dvb/frontends/tda827x.h
@@ -29,16 +29,9 @@
struct tda827x_config
{
- /* saa7134 - provided callbacks */
void (*lna_gain) (struct dvb_frontend *fe, int high);
int (*init) (struct dvb_frontend *fe);
int (*sleep) (struct dvb_frontend *fe);
-
- /* interface to tda829x driver */
- unsigned int *config;
- int (*tuner_callback) (void *dev, int command, int arg);
-
- void (*agcf)(struct dvb_frontend *fe);
};
diff --git a/trunk/drivers/media/dvb/frontends/ves1820.c b/trunk/drivers/media/dvb/frontends/ves1820.c
index 8791701c8f25..60433b5011fd 100644
--- a/trunk/drivers/media/dvb/frontends/ves1820.c
+++ b/trunk/drivers/media/dvb/frontends/ves1820.c
@@ -65,7 +65,7 @@ static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1)
- printk("ves1820: %s(): writereg error (reg == 0x%02x, "
+ printk("ves1820: %s(): writereg error (reg == 0x%02x,"
"val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret);
return (ret != 1) ? -EREMOTEIO : 0;
@@ -84,7 +84,7 @@ static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2)
- printk("ves1820: %s(): readreg error (reg == 0x%02x, "
+ printk("ves1820: %s(): readreg error (reg == 0x%02x,"
"ret == %i)\n", __FUNCTION__, reg, ret);
return b1[0];
diff --git a/trunk/drivers/media/dvb/frontends/xc5000.c b/trunk/drivers/media/dvb/frontends/xc5000.c
deleted file mode 100644
index f642ca200b59..000000000000
--- a/trunk/drivers/media/dvb/frontends/xc5000.c
+++ /dev/null
@@ -1,964 +0,0 @@
-/*
- * Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
- *
- * Copyright (c) 2007 Xceive Corporation
- * Copyright (c) 2007 Steven Toth
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "dvb_frontend.h"
-
-#include "xc5000.h"
-#include "xc5000_priv.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-#define dprintk(level,fmt, arg...) if (debug >= level) \
- printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
-
-#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw"
-#define XC5000_DEFAULT_FIRMWARE_SIZE 12332
-
-/* Misc Defines */
-#define MAX_TV_STANDARD 23
-#define XC_MAX_I2C_WRITE_LENGTH 64
-
-/* Signal Types */
-#define XC_RF_MODE_AIR 0
-#define XC_RF_MODE_CABLE 1
-
-/* Result codes */
-#define XC_RESULT_SUCCESS 0
-#define XC_RESULT_RESET_FAILURE 1
-#define XC_RESULT_I2C_WRITE_FAILURE 2
-#define XC_RESULT_I2C_READ_FAILURE 3
-#define XC_RESULT_OUT_OF_RANGE 5
-
-/* Product id */
-#define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000
-#define XC_PRODUCT_ID_FW_LOADED 0x1388
-
-/* Registers */
-#define XREG_INIT 0x00
-#define XREG_VIDEO_MODE 0x01
-#define XREG_AUDIO_MODE 0x02
-#define XREG_RF_FREQ 0x03
-#define XREG_D_CODE 0x04
-#define XREG_IF_OUT 0x05
-#define XREG_SEEK_MODE 0x07
-#define XREG_POWER_DOWN 0x0A
-#define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */
-#define XREG_SMOOTHEDCVBS 0x0E
-#define XREG_XTALFREQ 0x0F
-#define XREG_FINERFFREQ 0x10
-#define XREG_DDIMODE 0x11
-
-#define XREG_ADC_ENV 0x00
-#define XREG_QUALITY 0x01
-#define XREG_FRAME_LINES 0x02
-#define XREG_HSYNC_FREQ 0x03
-#define XREG_LOCK 0x04
-#define XREG_FREQ_ERROR 0x05
-#define XREG_SNR 0x06
-#define XREG_VERSION 0x07
-#define XREG_PRODUCT_ID 0x08
-#define XREG_BUSY 0x09
-
-/*
- Basic firmware description. This will remain with
- the driver for documentation purposes.
-
- This represents an I2C firmware file encoded as a
- string of unsigned char. Format is as follows:
-
- char[0 ]=len0_MSB -> len = len_MSB * 256 + len_LSB
- char[1 ]=len0_LSB -> length of first write transaction
- char[2 ]=data0 -> first byte to be sent
- char[3 ]=data1
- char[4 ]=data2
- char[ ]=...
- char[M ]=dataN -> last byte to be sent
- char[M+1]=len1_MSB -> len = len_MSB * 256 + len_LSB
- char[M+2]=len1_LSB -> length of second write transaction
- char[M+3]=data0
- char[M+4]=data1
- ...
- etc.
-
- The [len] value should be interpreted as follows:
-
- len= len_MSB _ len_LSB
- len=1111_1111_1111_1111 : End of I2C_SEQUENCE
- len=0000_0000_0000_0000 : Reset command: Do hardware reset
- len=0NNN_NNNN_NNNN_NNNN : Normal transaction: number of bytes = {1:32767)
- len=1WWW_WWWW_WWWW_WWWW : Wait command: wait for {1:32767} ms
-
- For the RESET and WAIT commands, the two following bytes will contain
- immediately the length of the following transaction.
-
-*/
-typedef struct {
- char *Name;
- u16 AudioMode;
- u16 VideoMode;
-} XC_TV_STANDARD;
-
-/* Tuner standards */
-#define MN_NTSC_PAL_BTSC 0
-#define MN_NTSC_PAL_A2 1
-#define MN_NTSC_PAL_EIAJ 2
-#define MN_NTSC_PAL_Mono 3
-#define BG_PAL_A2 4
-#define BG_PAL_NICAM 5
-#define BG_PAL_MONO 6
-#define I_PAL_NICAM 7
-#define I_PAL_NICAM_MONO 8
-#define DK_PAL_A2 9
-#define DK_PAL_NICAM 10
-#define DK_PAL_MONO 11
-#define DK_SECAM_A2DK1 12
-#define DK_SECAM_A2LDK3 13
-#define DK_SECAM_A2MONO 14
-#define L_SECAM_NICAM 15
-#define LC_SECAM_NICAM 16
-#define DTV6 17
-#define DTV8 18
-#define DTV7_8 19
-#define DTV7 20
-#define FM_Radio_INPUT2 21
-#define FM_Radio_INPUT1 22
-
-XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
- {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
- {"M/N-NTSC/PAL-A2", 0x0600, 0x8020},
- {"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020},
- {"M/N-NTSC/PAL-Mono", 0x0478, 0x8020},
- {"B/G-PAL-A2", 0x0A00, 0x8049},
- {"B/G-PAL-NICAM", 0x0C04, 0x8049},
- {"B/G-PAL-MONO", 0x0878, 0x8059},
- {"I-PAL-NICAM", 0x1080, 0x8009},
- {"I-PAL-NICAM-MONO", 0x0E78, 0x8009},
- {"D/K-PAL-A2", 0x1600, 0x8009},
- {"D/K-PAL-NICAM", 0x0E80, 0x8009},
- {"D/K-PAL-MONO", 0x1478, 0x8009},
- {"D/K-SECAM-A2 DK1", 0x1200, 0x8009},
- {"D/K-SECAM-A2 L/DK3",0x0E00, 0x8009},
- {"D/K-SECAM-A2 MONO", 0x1478, 0x8009},
- {"L-SECAM-NICAM", 0x8E82, 0x0009},
- {"L'-SECAM-NICAM", 0x8E82, 0x4009},
- {"DTV6", 0x00C0, 0x8002},
- {"DTV8", 0x00C0, 0x800B},
- {"DTV7/8", 0x00C0, 0x801B},
- {"DTV7", 0x00C0, 0x8007},
- {"FM Radio-INPUT2", 0x9802, 0x9002},
- {"FM Radio-INPUT1", 0x0208, 0x9002}
-};
-
-static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len);
-static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len);
-static void xc5000_TunerReset(struct dvb_frontend *fe);
-
-static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
-{
- return xc5000_writeregs(priv, buf, len)
- ? XC_RESULT_I2C_WRITE_FAILURE : XC_RESULT_SUCCESS;
-}
-
-static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
-{
- return xc5000_readregs(priv, buf, len)
- ? XC_RESULT_I2C_READ_FAILURE : XC_RESULT_SUCCESS;
-}
-
-static int xc_reset(struct dvb_frontend *fe)
-{
- xc5000_TunerReset(fe);
- return XC_RESULT_SUCCESS;
-}
-
-static void xc_wait(int wait_ms)
-{
- msleep(wait_ms);
-}
-
-static void xc5000_TunerReset(struct dvb_frontend *fe)
-{
- struct xc5000_priv *priv = fe->tuner_priv;
- int ret;
-
- dprintk(1, "%s()\n", __FUNCTION__);
-
- if (priv->cfg->tuner_callback) {
- ret = priv->cfg->tuner_callback(priv->cfg->priv,
- XC5000_TUNER_RESET, 0);
- if (ret)
- printk(KERN_ERR "xc5000: reset failed\n");
- } else
- printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n");
-}
-
-static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
-{
- u8 buf[4];
- int WatchDogTimer = 5;
- int result;
-
- buf[0] = (regAddr >> 8) & 0xFF;
- buf[1] = regAddr & 0xFF;
- buf[2] = (i2cData >> 8) & 0xFF;
- buf[3] = i2cData & 0xFF;
- result = xc_send_i2c_data(priv, buf, 4);
- if (result == XC_RESULT_SUCCESS) {
- /* wait for busy flag to clear */
- while ((WatchDogTimer > 0) && (result == XC_RESULT_SUCCESS)) {
- buf[0] = 0;
- buf[1] = XREG_BUSY;
-
- result = xc_send_i2c_data(priv, buf, 2);
- if (result == XC_RESULT_SUCCESS) {
- result = xc_read_i2c_data(priv, buf, 2);
- if (result == XC_RESULT_SUCCESS) {
- if ((buf[0] == 0) && (buf[1] == 0)) {
- /* busy flag cleared */
- break;
- } else {
- xc_wait(100); /* wait 5 ms */
- WatchDogTimer--;
- }
- }
- }
- }
- }
- if (WatchDogTimer < 0)
- result = XC_RESULT_I2C_WRITE_FAILURE;
-
- return result;
-}
-
-static int xc_read_reg(struct xc5000_priv *priv, u16 regAddr, u16 *i2cData)
-{
- u8 buf[2];
- int result;
-
- buf[0] = (regAddr >> 8) & 0xFF;
- buf[1] = regAddr & 0xFF;
- result = xc_send_i2c_data(priv, buf, 2);
- if (result != XC_RESULT_SUCCESS)
- return result;
-
- result = xc_read_i2c_data(priv, buf, 2);
- if (result != XC_RESULT_SUCCESS)
- return result;
-
- *i2cData = buf[0] * 256 + buf[1];
- return result;
-}
-
-static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[])
-{
- struct xc5000_priv *priv = fe->tuner_priv;
-
- int i, nbytes_to_send, result;
- unsigned int len, pos, index;
- u8 buf[XC_MAX_I2C_WRITE_LENGTH];
-
- index=0;
- while ((i2c_sequence[index]!=0xFF) || (i2c_sequence[index+1]!=0xFF)) {
- len = i2c_sequence[index]* 256 + i2c_sequence[index+1];
- if (len == 0x0000) {
- /* RESET command */
- result = xc_reset(fe);
- index += 2;
- if (result != XC_RESULT_SUCCESS)
- return result;
- } else if (len & 0x8000) {
- /* WAIT command */
- xc_wait(len & 0x7FFF);
- index += 2;
- } else {
- /* Send i2c data whilst ensuring individual transactions
- * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes.
- */
- index += 2;
- buf[0] = i2c_sequence[index];
- buf[1] = i2c_sequence[index + 1];
- pos = 2;
- while (pos < len) {
- if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2) {
- nbytes_to_send = XC_MAX_I2C_WRITE_LENGTH;
- } else {
- nbytes_to_send = (len - pos + 2);
- }
- for (i=2; ivideo_standard].Name);
-
- ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
- if (ret == XC_RESULT_SUCCESS)
- ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode);
-
- return ret;
-}
-
-static int xc_shutdown(struct xc5000_priv *priv)
-{
- return 0;
- /* Fixme: cannot bring tuner back alive once shutdown
- * without reloading the driver modules.
- * return xc_write_reg(priv, XREG_POWER_DOWN, 0);
- */
-}
-
-static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
-{
- dprintk(1, "%s(%d) Source = %s\n", __FUNCTION__, rf_mode,
- rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
-
- if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE))
- {
- rf_mode = XC_RF_MODE_CABLE;
- printk(KERN_ERR
- "%s(), Invalid mode, defaulting to CABLE",
- __FUNCTION__);
- }
- return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
-}
-
-static const struct dvb_tuner_ops xc5000_tuner_ops;
-
-static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
-{
- u16 freq_code;
-
- dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
-
- if ((freq_hz > xc5000_tuner_ops.info.frequency_max) ||
- (freq_hz < xc5000_tuner_ops.info.frequency_min))
- return XC_RESULT_OUT_OF_RANGE;
-
- freq_code = (u16)(freq_hz / 15625);
-
- return xc_write_reg(priv, XREG_RF_FREQ, freq_code);
-}
-
-
-static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
-{
- u32 freq_code = (freq_khz * 1024)/1000;
- dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
- __FUNCTION__, freq_khz, freq_code);
-
- return xc_write_reg(priv, XREG_IF_OUT, freq_code);
-}
-
-
-static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope)
-{
- return xc_read_reg(priv, XREG_ADC_ENV, adc_envelope);
-}
-
-static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
-{
- int result;
- u16 regData;
- u32 tmp;
-
- result = xc_read_reg(priv, XREG_FREQ_ERROR, ®Data);
- if (result)
- return result;
-
- tmp = (u32)regData;
- (*freq_error_hz) = (tmp * 15625) / 1000;
- return result;
-}
-
-static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status)
-{
- return xc_read_reg(priv, XREG_LOCK, lock_status);
-}
-
-static int xc_get_version(struct xc5000_priv *priv,
- u8 *hw_majorversion, u8 *hw_minorversion,
- u8 *fw_majorversion, u8 *fw_minorversion)
-{
- u16 data;
- int result;
-
- result = xc_read_reg(priv, XREG_VERSION, &data);
- if (result)
- return result;
-
- (*hw_majorversion) = (data >> 12) & 0x0F;
- (*hw_minorversion) = (data >> 8) & 0x0F;
- (*fw_majorversion) = (data >> 4) & 0x0F;
- (*fw_minorversion) = data & 0x0F;
-
- return 0;
-}
-
-static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz)
-{
- u16 regData;
- int result;
-
- result = xc_read_reg(priv, XREG_HSYNC_FREQ, ®Data);
- if (result)
- return result;
-
- (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
- return result;
-}
-
-static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines)
-{
- return xc_read_reg(priv, XREG_FRAME_LINES, frame_lines);
-}
-
-static int xc_get_quality(struct xc5000_priv *priv, u16 *quality)
-{
- return xc_read_reg(priv, XREG_QUALITY, quality);
-}
-
-static u16 WaitForLock(struct xc5000_priv *priv)
-{
- u16 lockState = 0;
- int watchDogCount = 40;
-
- while ((lockState == 0) && (watchDogCount > 0)) {
- xc_get_lock_status(priv, &lockState);
- if (lockState != 1) {
- xc_wait(5);
- watchDogCount--;
- }
- }
- return lockState;
-}
-
-static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz)
-{
- int found = 0;
-
- dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
-
- if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
- return 0;
-
- if (WaitForLock(priv) == 1)
- found = 1;
-
- return found;
-}
-
-static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
-{
- u8 buf[2] = { reg >> 8, reg & 0xff };
- u8 bval[2] = { 0, 0 };
- struct i2c_msg msg[2] = {
- { .addr = priv->cfg->i2c_address,
- .flags = 0, .buf = &buf[0], .len = 2 },
- { .addr = priv->cfg->i2c_address,
- .flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
- };
-
- if (i2c_transfer(priv->i2c, msg, 2) != 2) {
- printk(KERN_WARNING "xc5000: I2C read failed\n");
- return -EREMOTEIO;
- }
-
- *val = (bval[0] << 8) | bval[1];
- return 0;
-}
-
-static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len)
-{
- struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
- .flags = 0, .buf = buf, .len = len };
-
- if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
- printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n",
- (int)len);
- return -EREMOTEIO;
- }
- return 0;
-}
-
-static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len)
-{
- struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
- .flags = I2C_M_RD, .buf = buf, .len = len };
-
- if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
- printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len);
- return -EREMOTEIO;
- }
- return 0;
-}
-
-static int xc5000_fwupload(struct dvb_frontend* fe)
-{
- struct xc5000_priv *priv = fe->tuner_priv;
- const struct firmware *fw;
- int ret;
-
- /* request the firmware, this will block and timeout */
- printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
- XC5000_DEFAULT_FIRMWARE);
-
- ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c->dev);
- if (ret) {
- printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
- ret = XC_RESULT_RESET_FAILURE;
- goto out;
- } else {
- printk(KERN_INFO "xc5000: firmware read %Zu bytes.\n",
- fw->size);
- ret = XC_RESULT_SUCCESS;
- }
-
- if (fw->size != XC5000_DEFAULT_FIRMWARE_SIZE) {
- printk(KERN_ERR "xc5000: firmware incorrect size\n");
- ret = XC_RESULT_RESET_FAILURE;
- } else {
- printk(KERN_INFO "xc5000: firmware upload\n");
- ret = xc_load_i2c_sequence(fe, fw->data );
- }
-
-out:
- release_firmware(fw);
- return ret;
-}
-
-static void xc_debug_dump(struct xc5000_priv *priv)
-{
- u16 adc_envelope;
- u32 freq_error_hz = 0;
- u16 lock_status;
- u32 hsync_freq_hz = 0;
- u16 frame_lines;
- u16 quality;
- u8 hw_majorversion = 0, hw_minorversion = 0;
- u8 fw_majorversion = 0, fw_minorversion = 0;
-
- /* Wait for stats to stabilize.
- * Frame Lines needs two frame times after initial lock
- * before it is valid.
- */
- xc_wait(100);
-
- xc_get_ADC_Envelope(priv, &adc_envelope);
- dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
-
- xc_get_frequency_error(priv, &freq_error_hz);
- dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
-
- xc_get_lock_status(priv, &lock_status);
- dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
- lock_status);
-
- xc_get_version(priv, &hw_majorversion, &hw_minorversion,
- &fw_majorversion, &fw_minorversion);
- dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n",
- hw_majorversion, hw_minorversion,
- fw_majorversion, fw_minorversion);
-
- xc_get_hsync_freq(priv, &hsync_freq_hz);
- dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz);
-
- xc_get_frame_lines(priv, &frame_lines);
- dprintk(1, "*** Frame lines = %d\n", frame_lines);
-
- xc_get_quality(priv, &quality);
- dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
-}
-
-static int xc5000_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
-{
- struct xc5000_priv *priv = fe->tuner_priv;
- int ret;
-
- dprintk(1, "%s() frequency=%d (Hz)\n", __FUNCTION__, params->frequency);
-
- switch(params->u.vsb.modulation) {
- case VSB_8:
- case VSB_16:
- dprintk(1, "%s() VSB modulation\n", __FUNCTION__);
- priv->rf_mode = XC_RF_MODE_AIR;
- priv->freq_hz = params->frequency - 1750000;
- priv->bandwidth = BANDWIDTH_6_MHZ;
- priv->video_standard = DTV6;
- break;
- case QAM_64:
- case QAM_256:
- case QAM_AUTO:
- dprintk(1, "%s() QAM modulation\n", __FUNCTION__);
- priv->rf_mode = XC_RF_MODE_CABLE;
- priv->freq_hz = params->frequency - 1750000;
- priv->bandwidth = BANDWIDTH_6_MHZ;
- priv->video_standard = DTV6;
- break;
- default:
- return -EINVAL;
- }
-
- dprintk(1, "%s() frequency=%d (compensated)\n",
- __FUNCTION__, priv->freq_hz);
-
- ret = xc_SetSignalSource(priv, priv->rf_mode);
- if (ret != XC_RESULT_SUCCESS) {
- printk(KERN_ERR
- "xc5000: xc_SetSignalSource(%d) failed\n",
- priv->rf_mode);
- return -EREMOTEIO;
- }
-
- ret = xc_SetTVStandard(priv,
- XC5000_Standard[priv->video_standard].VideoMode,
- XC5000_Standard[priv->video_standard].AudioMode);
- if (ret != XC_RESULT_SUCCESS) {
- printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
- return -EREMOTEIO;
- }
-
- ret = xc_set_IF_frequency(priv, priv->cfg->if_khz);
- if (ret != XC_RESULT_SUCCESS) {
- printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
- priv->cfg->if_khz);
- return -EIO;
- }
-
- xc_tune_channel(priv, priv->freq_hz);
-
- if (debug)
- xc_debug_dump(priv);
-
- return 0;
-}
-
-static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
-
-static int xc5000_set_analog_params(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct xc5000_priv *priv = fe->tuner_priv;
- int ret;
-
- if(priv->fwloaded == 0)
- xc_load_fw_and_init_tuner(fe);
-
- dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
- __FUNCTION__, params->frequency);
-
- priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */
-
- /* params->frequency is in units of 62.5khz */
- priv->freq_hz = params->frequency * 62500;
-
- /* FIX ME: Some video standards may have several possible audio
- standards. We simply default to one of them here.
- */
- if(params->std & V4L2_STD_MN) {
- /* default to BTSC audio standard */
- priv->video_standard = MN_NTSC_PAL_BTSC;
- goto tune_channel;
- }
-
- if(params->std & V4L2_STD_PAL_BG) {
- /* default to NICAM audio standard */
- priv->video_standard = BG_PAL_NICAM;
- goto tune_channel;
- }
-
- if(params->std & V4L2_STD_PAL_I) {
- /* default to NICAM audio standard */
- priv->video_standard = I_PAL_NICAM;
- goto tune_channel;
- }
-
- if(params->std & V4L2_STD_PAL_DK) {
- /* default to NICAM audio standard */
- priv->video_standard = DK_PAL_NICAM;
- goto tune_channel;
- }
-
- if(params->std & V4L2_STD_SECAM_DK) {
- /* default to A2 DK1 audio standard */
- priv->video_standard = DK_SECAM_A2DK1;
- goto tune_channel;
- }
-
- if(params->std & V4L2_STD_SECAM_L) {
- priv->video_standard = L_SECAM_NICAM;
- goto tune_channel;
- }
-
- if(params->std & V4L2_STD_SECAM_LC) {
- priv->video_standard = LC_SECAM_NICAM;
- goto tune_channel;
- }
-
-tune_channel:
- ret = xc_SetSignalSource(priv, priv->rf_mode);
- if (ret != XC_RESULT_SUCCESS) {
- printk(KERN_ERR
- "xc5000: xc_SetSignalSource(%d) failed\n",
- priv->rf_mode);
- return -EREMOTEIO;
- }
-
- ret = xc_SetTVStandard(priv,
- XC5000_Standard[priv->video_standard].VideoMode,
- XC5000_Standard[priv->video_standard].AudioMode);
- if (ret != XC_RESULT_SUCCESS) {
- printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
- return -EREMOTEIO;
- }
-
- xc_tune_channel(priv, priv->freq_hz);
-
- if (debug)
- xc_debug_dump(priv);
-
- return 0;
-}
-
-static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
-{
- struct xc5000_priv *priv = fe->tuner_priv;
- dprintk(1, "%s()\n", __FUNCTION__);
- *freq = priv->freq_hz;
- return 0;
-}
-
-static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
-{
- struct xc5000_priv *priv = fe->tuner_priv;
- dprintk(1, "%s()\n", __FUNCTION__);
-
- *bw = priv->bandwidth;
- return 0;
-}
-
-static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
-{
- struct xc5000_priv *priv = fe->tuner_priv;
- u16 lock_status = 0;
-
- xc_get_lock_status(priv, &lock_status);
-
- dprintk(1, "%s() lock_status = 0x%08x\n", __FUNCTION__, lock_status);
-
- *status = lock_status;
-
- return 0;
-}
-
-static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
-{
- struct xc5000_priv *priv = fe->tuner_priv;
- int ret = 0;
-
- if (priv->fwloaded == 0) {
- ret = xc5000_fwupload(fe);
- if (ret != XC_RESULT_SUCCESS)
- return ret;
- priv->fwloaded = 1;
- }
-
- /* Start the tuner self-calibration process */
- ret |= xc_initialize(priv);
-
- /* Wait for calibration to complete.
- * We could continue but XC5000 will clock stretch subsequent
- * I2C transactions until calibration is complete. This way we
- * don't have to rely on clock stretching working.
- */
- xc_wait( 100 );
-
- /* Default to "CABLE" mode */
- ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
-
- return ret;
-}
-
-static int xc5000_sleep(struct dvb_frontend *fe)
-{
- struct xc5000_priv *priv = fe->tuner_priv;
- int ret;
-
- dprintk(1, "%s()\n", __FUNCTION__);
-
- /* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized
- * once shutdown without reloading the driver. Maybe I am not
- * doing something right.
- *
- */
-
- ret = xc_shutdown(priv);
- if(ret != XC_RESULT_SUCCESS) {
- printk(KERN_ERR
- "xc5000: %s() unable to shutdown tuner\n",
- __FUNCTION__);
- return -EREMOTEIO;
- }
- else {
- /* priv->fwloaded = 0; */
- return XC_RESULT_SUCCESS;
- }
-}
-
-static int xc5000_init(struct dvb_frontend *fe)
-{
- struct xc5000_priv *priv = fe->tuner_priv;
- dprintk(1, "%s()\n", __FUNCTION__);
-
- if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
- printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
- return -EREMOTEIO;
- }
-
- if (debug)
- xc_debug_dump(priv);
-
- return 0;
-}
-
-static int xc5000_release(struct dvb_frontend *fe)
-{
- dprintk(1, "%s()\n", __FUNCTION__);
- kfree(fe->tuner_priv);
- fe->tuner_priv = NULL;
- return 0;
-}
-
-static const struct dvb_tuner_ops xc5000_tuner_ops = {
- .info = {
- .name = "Xceive XC5000",
- .frequency_min = 1000000,
- .frequency_max = 1023000000,
- .frequency_step = 50000,
- },
-
- .release = xc5000_release,
- .init = xc5000_init,
- .sleep = xc5000_sleep,
-
- .set_params = xc5000_set_params,
- .set_analog_params = xc5000_set_analog_params,
- .get_frequency = xc5000_get_frequency,
- .get_bandwidth = xc5000_get_bandwidth,
- .get_status = xc5000_get_status
-};
-
-struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c,
- struct xc5000_config *cfg)
-{
- struct xc5000_priv *priv = NULL;
- u16 id = 0;
-
- dprintk(1, "%s()\n", __FUNCTION__);
-
- priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL);
- if (priv == NULL)
- return NULL;
-
- priv->cfg = cfg;
- priv->bandwidth = BANDWIDTH_6_MHZ;
- priv->i2c = i2c;
-
- /* Check if firmware has been loaded. It is possible that another
- instance of the driver has loaded the firmware.
- */
- if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) {
- kfree(priv);
- return NULL;
- }
-
- switch(id) {
- case XC_PRODUCT_ID_FW_LOADED:
- printk(KERN_INFO
- "xc5000: Successfully identified at address 0x%02x\n",
- cfg->i2c_address);
- printk(KERN_INFO
- "xc5000: Firmware has been loaded previously\n");
- priv->fwloaded = 1;
- break;
- case XC_PRODUCT_ID_FW_NOT_LOADED:
- printk(KERN_INFO
- "xc5000: Successfully identified at address 0x%02x\n",
- cfg->i2c_address);
- printk(KERN_INFO
- "xc5000: Firmware has not been loaded previously\n");
- priv->fwloaded = 0;
- break;
- default:
- printk(KERN_ERR
- "xc5000: Device not found at addr 0x%02x (0x%x)\n",
- cfg->i2c_address, id);
- kfree(priv);
- return NULL;
- }
-
- memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
- sizeof(struct dvb_tuner_ops));
-
- fe->tuner_priv = priv;
-
- return fe;
-}
-EXPORT_SYMBOL(xc5000_attach);
-
-MODULE_AUTHOR("Steven Toth");
-MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver");
-MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/media/dvb/frontends/xc5000.h b/trunk/drivers/media/dvb/frontends/xc5000.h
deleted file mode 100644
index e0e84562aed1..000000000000
--- a/trunk/drivers/media/dvb/frontends/xc5000.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
- *
- * Copyright (c) 2007 Steven Toth
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __XC5000_H__
-#define __XC5000_H__
-
-#include
-
-struct dvb_frontend;
-struct i2c_adapter;
-
-struct xc5000_config {
- u8 i2c_address;
- u32 if_khz;
-
- /* For each bridge framework, when it attaches either analog or digital,
- * it has to store a reference back to its _core equivalent structure,
- * so that it can service the hardware by steering gpio's etc.
- * Each bridge implementation is different so cast priv accordingly.
- * The xc5000 driver cares not for this value, other than ensuring
- * it's passed back to a bridge during tuner_callback().
- */
- void *priv;
- int (*tuner_callback) (void *priv, int command, int arg);
-};
-
-/* xc5000 callback command */
-#define XC5000_TUNER_RESET 0
-
-#if defined(CONFIG_DVB_TUNER_XC5000) || defined(CONFIG_DVB_TUNER_XC5000_MODULE)
-extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c,
- struct xc5000_config *cfg);
-#else
-static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c,
- struct xc5000_config *cfg)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
- return NULL;
-}
-#endif // CONFIG_DVB_TUNER_XC5000
-
-#endif // __XC5000_H__
diff --git a/trunk/drivers/media/dvb/frontends/xc5000_priv.h b/trunk/drivers/media/dvb/frontends/xc5000_priv.h
deleted file mode 100644
index 13b2d19341da..000000000000
--- a/trunk/drivers/media/dvb/frontends/xc5000_priv.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
- *
- * Copyright (c) 2007 Steven Toth
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef XC5000_PRIV_H
-#define XC5000_PRIV_H
-
-struct xc5000_priv {
- struct xc5000_config *cfg;
- struct i2c_adapter *i2c;
-
- u32 freq_hz;
- u32 bandwidth;
- u8 video_standard;
- u8 rf_mode;
- u8 fwloaded;
-};
-
-#endif
diff --git a/trunk/drivers/media/dvb/frontends/zl10353.c b/trunk/drivers/media/dvb/frontends/zl10353.c
index 276e3b631dc2..0106df4c55e8 100644
--- a/trunk/drivers/media/dvb/frontends/zl10353.c
+++ b/trunk/drivers/media/dvb/frontends/zl10353.c
@@ -1,7 +1,7 @@
/*
* Driver for Zarlink DVB-T ZL10353 demodulator
*
- * Copyright (C) 2006, 2007 Christopher Pascoe
+ * Copyright (C) 2006 Christopher Pascoe
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
*/
#include
@@ -25,7 +25,6 @@
#include
#include
#include
-#include
#include "dvb_frontend.h"
#include "zl10353_priv.h"
@@ -36,8 +35,6 @@ struct zl10353_state {
struct dvb_frontend frontend;
struct zl10353_config config;
-
- enum fe_bandwidth bandwidth;
};
static int debug;
@@ -125,10 +122,9 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
enum fe_bandwidth bandwidth,
u16 *nominal_rate)
{
- struct zl10353_state *state = fe->demodulator_priv;
- u32 adc_clock = 450560; /* 45.056 MHz */
- u64 value;
+ u32 adc_clock = 45056; /* 45.056 MHz */
u8 bw;
+ struct zl10353_state *state = fe->demodulator_priv;
if (state->config.adc_clock)
adc_clock = state->config.adc_clock;
@@ -146,44 +142,12 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
break;
}
- value = (u64)10 * (1 << 23) / 7 * 125;
- value = (bw * value) + adc_clock / 2;
- do_div(value, adc_clock);
- *nominal_rate = value;
+ *nominal_rate = (bw * (1 << 23) / 7 * 125 + adc_clock / 2) / adc_clock;
dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
__FUNCTION__, bw, adc_clock, *nominal_rate);
}
-static void zl10353_calc_input_freq(struct dvb_frontend *fe,
- u16 *input_freq)
-{
- struct zl10353_state *state = fe->demodulator_priv;
- u32 adc_clock = 450560; /* 45.056 MHz */
- int if2 = 361667; /* 36.1667 MHz */
- int ife;
- u64 value;
-
- if (state->config.adc_clock)
- adc_clock = state->config.adc_clock;
- if (state->config.if2)
- if2 = state->config.if2;
-
- if (adc_clock >= if2 * 2)
- ife = if2;
- else {
- ife = adc_clock - (if2 % adc_clock);
- if (ife > adc_clock / 2)
- ife = adc_clock - ife;
- }
- value = (u64)65536 * ife + adc_clock / 2;
- do_div(value, adc_clock);
- *input_freq = -value;
-
- dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
- __FUNCTION__, if2, ife, adc_clock, -(int)value, *input_freq);
-}
-
static int zl10353_sleep(struct dvb_frontend *fe)
{
static u8 zl10353_softdown[] = { 0x50, 0x0C, 0x44 };
@@ -196,276 +160,64 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
struct dvb_frontend_parameters *param)
{
struct zl10353_state *state = fe->demodulator_priv;
- u16 nominal_rate, input_freq;
- u8 pllbuf[6] = { 0x67 }, acq_ctl = 0;
- u16 tps = 0;
- struct dvb_ofdm_parameters *op = ¶m->u.ofdm;
+ u16 nominal_rate;
+ u8 pllbuf[6] = { 0x67 };
- zl10353_single_write(fe, RESET, 0x80);
+ /* These settings set "auto-everything" and start the FSM. */
+ zl10353_single_write(fe, 0x55, 0x80);
udelay(200);
zl10353_single_write(fe, 0xEA, 0x01);
udelay(200);
zl10353_single_write(fe, 0xEA, 0x00);
- zl10353_single_write(fe, AGC_TARGET, 0x28);
-
- if (op->transmission_mode != TRANSMISSION_MODE_AUTO)
- acq_ctl |= (1 << 0);
- if (op->guard_interval != GUARD_INTERVAL_AUTO)
- acq_ctl |= (1 << 1);
- zl10353_single_write(fe, ACQ_CTL, acq_ctl);
+ zl10353_single_write(fe, 0x56, 0x28);
+ zl10353_single_write(fe, 0x89, 0x20);
+ zl10353_single_write(fe, 0x5E, 0x00);
- switch (op->bandwidth) {
- case BANDWIDTH_6_MHZ:
- /* These are extrapolated from the 7 and 8MHz values */
- zl10353_single_write(fe, MCLK_RATIO, 0x97);
- zl10353_single_write(fe, 0x64, 0x34);
- break;
- case BANDWIDTH_7_MHZ:
- zl10353_single_write(fe, MCLK_RATIO, 0x86);
- zl10353_single_write(fe, 0x64, 0x35);
- break;
- case BANDWIDTH_8_MHZ:
- default:
- zl10353_single_write(fe, MCLK_RATIO, 0x75);
- zl10353_single_write(fe, 0x64, 0x36);
- }
-
- zl10353_calc_nominal_rate(fe, op->bandwidth, &nominal_rate);
+ zl10353_calc_nominal_rate(fe, param->u.ofdm.bandwidth, &nominal_rate);
zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate));
zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate));
- state->bandwidth = op->bandwidth;
-
- zl10353_calc_input_freq(fe, &input_freq);
- zl10353_single_write(fe, INPUT_FREQ_1, msb(input_freq));
- zl10353_single_write(fe, INPUT_FREQ_0, lsb(input_freq));
-
- /* Hint at TPS settings */
- switch (op->code_rate_HP) {
- case FEC_2_3:
- tps |= (1 << 7);
- break;
- case FEC_3_4:
- tps |= (2 << 7);
- break;
- case FEC_5_6:
- tps |= (3 << 7);
- break;
- case FEC_7_8:
- tps |= (4 << 7);
- break;
- case FEC_1_2:
- case FEC_AUTO:
- break;
- default:
- return -EINVAL;
- }
-
- switch (op->code_rate_LP) {
- case FEC_2_3:
- tps |= (1 << 4);
- break;
- case FEC_3_4:
- tps |= (2 << 4);
- break;
- case FEC_5_6:
- tps |= (3 << 4);
- break;
- case FEC_7_8:
- tps |= (4 << 4);
- break;
- case FEC_1_2:
- case FEC_AUTO:
- break;
- case FEC_NONE:
- if (op->hierarchy_information == HIERARCHY_AUTO ||
- op->hierarchy_information == HIERARCHY_NONE)
- break;
- default:
- return -EINVAL;
- }
-
- switch (op->constellation) {
- case QPSK:
- break;
- case QAM_AUTO:
- case QAM_16:
- tps |= (1 << 13);
- break;
- case QAM_64:
- tps |= (2 << 13);
- break;
- default:
- return -EINVAL;
- }
-
- switch (op->transmission_mode) {
- case TRANSMISSION_MODE_2K:
- case TRANSMISSION_MODE_AUTO:
- break;
- case TRANSMISSION_MODE_8K:
- tps |= (1 << 0);
- break;
- default:
- return -EINVAL;
- }
-
- switch (op->guard_interval) {
- case GUARD_INTERVAL_1_32:
- case GUARD_INTERVAL_AUTO:
- break;
- case GUARD_INTERVAL_1_16:
- tps |= (1 << 2);
- break;
- case GUARD_INTERVAL_1_8:
- tps |= (2 << 2);
- break;
- case GUARD_INTERVAL_1_4:
- tps |= (3 << 2);
- break;
- default:
- return -EINVAL;
- }
-
- switch (op->hierarchy_information) {
- case HIERARCHY_AUTO:
- case HIERARCHY_NONE:
- break;
- case HIERARCHY_1:
- tps |= (1 << 10);
- break;
- case HIERARCHY_2:
- tps |= (2 << 10);
- break;
- case HIERARCHY_4:
- tps |= (3 << 10);
- break;
- default:
- return -EINVAL;
- }
-
- zl10353_single_write(fe, TPS_GIVEN_1, msb(tps));
- zl10353_single_write(fe, TPS_GIVEN_0, lsb(tps));
+ zl10353_single_write(fe, 0x6C, 0xCD);
+ zl10353_single_write(fe, 0x6D, 0x7E);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
- /*
- * If there is no tuner attached to the secondary I2C bus, we call
- * set_params to program a potential tuner attached somewhere else.
- * Otherwise, we update the PLL registers via calc_regs.
- */
+ // if there is no attached secondary tuner, we call set_params to program
+ // a potential tuner attached somewhere else
if (state->config.no_tuner) {
if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, param);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
- } else if (fe->ops.tuner_ops.calc_regs) {
- fe->ops.tuner_ops.calc_regs(fe, param, pllbuf + 1, 5);
- pllbuf[1] <<= 1;
- zl10353_write(fe, pllbuf, sizeof(pllbuf));
}
- zl10353_single_write(fe, 0x5F, 0x13);
-
- /* If no attached tuner or invalid PLL registers, just start the FSM. */
- if (state->config.no_tuner || fe->ops.tuner_ops.calc_regs == NULL)
- zl10353_single_write(fe, FSM_GO, 0x01);
- else
- zl10353_single_write(fe, TUNER_GO, 0x01);
-
- return 0;
-}
-
-static int zl10353_get_parameters(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
-{
- struct zl10353_state *state = fe->demodulator_priv;
- struct dvb_ofdm_parameters *op = ¶m->u.ofdm;
- int s6, s9;
- u16 tps;
- static const u8 tps_fec_to_api[8] = {
- FEC_1_2,
- FEC_2_3,
- FEC_3_4,
- FEC_5_6,
- FEC_7_8,
- FEC_AUTO,
- FEC_AUTO,
- FEC_AUTO
- };
-
- s6 = zl10353_read_register(state, STATUS_6);
- s9 = zl10353_read_register(state, STATUS_9);
- if (s6 < 0 || s9 < 0)
- return -EREMOTEIO;
- if ((s6 & (1 << 5)) == 0 || (s9 & (1 << 4)) == 0)
- return -EINVAL; /* no FE or TPS lock */
-
- tps = zl10353_read_register(state, TPS_RECEIVED_1) << 8 |
- zl10353_read_register(state, TPS_RECEIVED_0);
-
- op->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7];
- op->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7];
-
- switch ((tps >> 13) & 3) {
- case 0:
- op->constellation = QPSK;
- break;
- case 1:
- op->constellation = QAM_16;
- break;
- case 2:
- op->constellation = QAM_64;
- break;
- default:
- op->constellation = QAM_AUTO;
- break;
- }
-
- op->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K :
- TRANSMISSION_MODE_2K;
-
- switch ((tps >> 2) & 3) {
- case 0:
- op->guard_interval = GUARD_INTERVAL_1_32;
- break;
- case 1:
- op->guard_interval = GUARD_INTERVAL_1_16;
- break;
- case 2:
- op->guard_interval = GUARD_INTERVAL_1_8;
- break;
- case 3:
- op->guard_interval = GUARD_INTERVAL_1_4;
- break;
- default:
- op->guard_interval = GUARD_INTERVAL_AUTO;
- break;
+ // if pllbuf is defined, retrieve the settings
+ if (fe->ops.tuner_ops.calc_regs) {
+ fe->ops.tuner_ops.calc_regs(fe, param, pllbuf+1, 5);
+ pllbuf[1] <<= 1;
+ } else {
+ // fake pllbuf settings
+ pllbuf[1] = 0x61 << 1;
+ pllbuf[2] = 0;
+ pllbuf[3] = 0;
+ pllbuf[3] = 0;
+ pllbuf[4] = 0;
}
- switch ((tps >> 10) & 7) {
- case 0:
- op->hierarchy_information = HIERARCHY_NONE;
- break;
- case 1:
- op->hierarchy_information = HIERARCHY_1;
- break;
- case 2:
- op->hierarchy_information = HIERARCHY_2;
- break;
- case 3:
- op->hierarchy_information = HIERARCHY_4;
- break;
- default:
- op->hierarchy_information = HIERARCHY_AUTO;
- break;
- }
+ // there is no call to _just_ start decoding, so we send the pllbuf anyway
+ // even if there isn't a PLL attached to the secondary bus
+ zl10353_write(fe, pllbuf, sizeof(pllbuf));
- param->frequency = 0;
- op->bandwidth = state->bandwidth;
- param->inversion = INVERSION_AUTO;
+ zl10353_single_write(fe, 0x5F, 0x13);
+ zl10353_single_write(fe, 0x70, 0x01);
+ udelay(250);
+ zl10353_single_write(fe, 0xE4, 0x00);
+ zl10353_single_write(fe, 0xE5, 0x2A);
+ zl10353_single_write(fe, 0xE9, 0x02);
+ zl10353_single_write(fe, 0xE7, 0x40);
+ zl10353_single_write(fe, 0xE8, 0x10);
return 0;
}
@@ -654,7 +406,6 @@ static struct dvb_frontend_ops zl10353_ops = {
.write = zl10353_write,
.set_frontend = zl10353_set_parameters,
- .get_frontend = zl10353_get_parameters,
.get_tune_settings = zl10353_get_tune_settings,
.read_status = zl10353_read_status,
diff --git a/trunk/drivers/media/dvb/frontends/zl10353.h b/trunk/drivers/media/dvb/frontends/zl10353.h
index fc734c22b5fa..1c3d494a6da9 100644
--- a/trunk/drivers/media/dvb/frontends/zl10353.h
+++ b/trunk/drivers/media/dvb/frontends/zl10353.h
@@ -1,7 +1,7 @@
/*
* Driver for Zarlink DVB-T ZL10353 demodulator
*
- * Copyright (C) 2006, 2007 Christopher Pascoe
+ * Copyright (C) 2006 Christopher Pascoe
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,9 +29,8 @@ struct zl10353_config
/* demodulator's I2C address */
u8 demod_address;
- /* frequencies in units of 0.1kHz */
- int adc_clock; /* default: 450560 (45.056 MHz) */
- int if2; /* default: 361667 (36.1667 MHz) */
+ /* frequencies in kHz */
+ int adc_clock; /* default: 45056 */
/* set if no pll is connected to the secondary i2c bus */
int no_tuner;
@@ -50,6 +49,6 @@ static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *c
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
return NULL;
}
-#endif /* CONFIG_DVB_ZL10353 */
+#endif // CONFIG_DVB_ZL10353
#endif /* ZL10353_H */
diff --git a/trunk/drivers/media/dvb/frontends/zl10353_priv.h b/trunk/drivers/media/dvb/frontends/zl10353_priv.h
index 055ff1f7e349..4962434b35e7 100644
--- a/trunk/drivers/media/dvb/frontends/zl10353_priv.h
+++ b/trunk/drivers/media/dvb/frontends/zl10353_priv.h
@@ -1,7 +1,7 @@
/*
* Driver for Zarlink DVB-T ZL10353 demodulator
*
- * Copyright (C) 2006, 2007 Christopher Pascoe
+ * Copyright (C) 2006 Christopher Pascoe
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
*/
#ifndef _ZL10353_PRIV_
@@ -46,28 +46,9 @@ enum zl10353_reg_addr {
RS_ERR_CNT_0 = 0x13,
RS_UBC_1 = 0x14,
RS_UBC_0 = 0x15,
- TPS_RECEIVED_1 = 0x1D,
- TPS_RECEIVED_0 = 0x1E,
- TPS_CURRENT_1 = 0x1F,
- TPS_CURRENT_0 = 0x20,
- RESET = 0x55,
- AGC_TARGET = 0x56,
- MCLK_RATIO = 0x5C,
- ACQ_CTL = 0x5E,
TRL_NOMINAL_RATE_1 = 0x65,
TRL_NOMINAL_RATE_0 = 0x66,
- INPUT_FREQ_1 = 0x6C,
- INPUT_FREQ_0 = 0x6D,
- TPS_GIVEN_1 = 0x6E,
- TPS_GIVEN_0 = 0x6F,
- TUNER_GO = 0x70,
- FSM_GO = 0x71,
CHIP_ID = 0x7F,
- CHAN_STEP_1 = 0xE4,
- CHAN_STEP_0 = 0xE5,
- OFDM_LOCK_TIME = 0xE7,
- FEC_LOCK_TIME = 0xE8,
- ACQ_DELAY = 0xE9,
};
#endif /* _ZL10353_PRIV_ */
diff --git a/trunk/drivers/media/dvb/ttpci/Kconfig b/trunk/drivers/media/dvb/ttpci/Kconfig
index ae882432dd3d..54b91f26ca63 100644
--- a/trunk/drivers/media/dvb/ttpci/Kconfig
+++ b/trunk/drivers/media/dvb/ttpci/Kconfig
@@ -1,14 +1,8 @@
-config TTPCI_EEPROM
- tristate
- default n
-
config DVB_AV7110
tristate "AV7110 cards"
- depends on DVB_CORE && PCI && I2C
+ depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
select FW_LOADER if !DVB_AV7110_FIRMWARE
- select TTPCI_EEPROM
select VIDEO_SAA7146_VV
- depends on VIDEO_DEV # dependencies of VIDEO_SAA7146_VV
select DVB_VES1820 if !DVB_FE_CUSTOMISE
select DVB_VES1X93 if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
@@ -63,19 +57,10 @@ config DVB_AV7110_OSD
All other people say N.
-config DVB_BUDGET_CORE
- tristate "SAA7146 DVB cards (aka Budget, Nova-PCI)"
- depends on DVB_CORE && PCI && I2C
- select VIDEO_SAA7146
- select TTPCI_EEPROM
- help
- Support for simple SAA7146 based DVB cards
- (so called Budget- or Nova-PCI cards) without onboard
- MPEG2 decoder.
-
config DVB_BUDGET
tristate "Budget cards"
- depends on DVB_BUDGET_CORE && I2C
+ depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
+ select VIDEO_SAA7146
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_VES1X93 if !DVB_FE_CUSTOMISE
select DVB_VES1820 if !DVB_FE_CUSTOMISE
@@ -88,9 +73,9 @@ config DVB_BUDGET
select DVB_TDA826X if !DVB_FE_CUSTOMISE
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
help
- Support for simple SAA7146 based DVB cards (so called Budget-
- or Nova-PCI cards) without onboard MPEG2 decoder, and without
- analog inputs or an onboard Common Interface connector.
+ Support for simple SAA7146 based DVB cards
+ (so called Budget- or Nova-PCI cards) without onboard
+ MPEG2 decoder.
Say Y if you own such a card and want to use it.
@@ -99,7 +84,8 @@ config DVB_BUDGET
config DVB_BUDGET_CI
tristate "Budget cards with onboard CI connector"
- depends on DVB_BUDGET_CORE && I2C
+ depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 && INPUT
+ select VIDEO_SAA7146
select DVB_STV0297 if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
@@ -120,9 +106,8 @@ config DVB_BUDGET_CI
config DVB_BUDGET_AV
tristate "Budget cards with analog video inputs"
- depends on DVB_BUDGET_CORE && I2C
+ depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
select VIDEO_SAA7146_VV
- depends on VIDEO_DEV # dependencies of VIDEO_SAA7146_VV
select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
@@ -142,8 +127,8 @@ config DVB_BUDGET_AV
config DVB_BUDGET_PATCH
tristate "AV7110 cards with Budget Patch"
- depends on DVB_BUDGET_CORE && I2C
- depends on DVB_AV7110
+ depends on DVB_CORE && DVB_BUDGET && VIDEO_V4L1
+ select DVB_AV7110
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_VES1X93 if !DVB_FE_CUSTOMISE
select DVB_TDA8083 if !DVB_FE_CUSTOMISE
diff --git a/trunk/drivers/media/dvb/ttpci/Makefile b/trunk/drivers/media/dvb/ttpci/Makefile
index d7483f1a9b3f..2c1145236ee6 100644
--- a/trunk/drivers/media/dvb/ttpci/Makefile
+++ b/trunk/drivers/media/dvb/ttpci/Makefile
@@ -5,13 +5,11 @@
dvb-ttpci-objs := av7110_hw.o av7110_v4l.o av7110_av.o av7110_ca.o av7110.o av7110_ipack.o av7110_ir.o
-obj-$(CONFIG_TTPCI_EEPROM) += ttpci-eeprom.o
-obj-$(CONFIG_DVB_BUDGET_CORE) += budget-core.o
-obj-$(CONFIG_DVB_BUDGET) += budget.o
-obj-$(CONFIG_DVB_BUDGET_AV) += budget-av.o
-obj-$(CONFIG_DVB_BUDGET_CI) += budget-ci.o
-obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o
-obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
+obj-$(CONFIG_DVB_BUDGET) += budget-core.o budget.o ttpci-eeprom.o
+obj-$(CONFIG_DVB_BUDGET_AV) += budget-core.o budget-av.o ttpci-eeprom.o
+obj-$(CONFIG_DVB_BUDGET_CI) += budget-core.o budget-ci.o ttpci-eeprom.o
+obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-core.o budget-patch.o ttpci-eeprom.o
+obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o ttpci-eeprom.o
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/trunk/drivers/media/dvb/ttpci/av7110.c b/trunk/drivers/media/dvb/ttpci/av7110.c
index 0e5701bdff19..0d36c155695b 100644
--- a/trunk/drivers/media/dvb/ttpci/av7110.c
+++ b/trunk/drivers/media/dvb/ttpci/av7110.c
@@ -2595,8 +2595,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
mutex_init(&av7110->osd_mutex);
/* TV standard */
- av7110->vidmode = tv_standard == 1 ? AV7110_VIDEO_MODE_NTSC
- : AV7110_VIDEO_MODE_PAL;
+ av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;
/* ARM "watchdog" */
init_waitqueue_head(&av7110->arm_wait);
diff --git a/trunk/drivers/media/dvb/ttpci/av7110.h b/trunk/drivers/media/dvb/ttpci/av7110.h
index 39fbf7d5cffb..0cb439527498 100644
--- a/trunk/drivers/media/dvb/ttpci/av7110.h
+++ b/trunk/drivers/media/dvb/ttpci/av7110.h
@@ -46,11 +46,6 @@ extern int av7110_debug;
enum {AV_PES_STREAM, PS_STREAM, TS_STREAM, PES_STREAM};
-enum av7110_video_mode {
- AV7110_VIDEO_MODE_PAL = 0,
- AV7110_VIDEO_MODE_NTSC = 1
-};
-
struct av7110_p2t {
u8 pes[TS_SIZE];
u8 counter;
@@ -175,7 +170,7 @@ struct av7110 {
ca_slot_info_t ci_slot[2];
- enum av7110_video_mode vidmode;
+ int vidmode;
struct dmxdev dmxdev;
struct dvb_demux demux;
diff --git a/trunk/drivers/media/dvb/ttpci/av7110_av.c b/trunk/drivers/media/dvb/ttpci/av7110_av.c
index aef6e36d7c5c..d75e7e48addc 100644
--- a/trunk/drivers/media/dvb/ttpci/av7110_av.c
+++ b/trunk/drivers/media/dvb/ttpci/av7110_av.c
@@ -329,7 +329,7 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright)
return 0;
}
-int av7110_set_vidmode(struct av7110 *av7110, enum av7110_video_mode mode)
+int av7110_set_vidmode(struct av7110 *av7110, int mode)
{
int ret;
dprintk(2, "av7110:%p, \n", av7110);
@@ -348,15 +348,11 @@ int av7110_set_vidmode(struct av7110 *av7110, enum av7110_video_mode mode)
}
-static enum av7110_video_mode sw2mode[16] = {
- AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_NTSC,
- AV7110_VIDEO_MODE_NTSC, AV7110_VIDEO_MODE_PAL,
- AV7110_VIDEO_MODE_NTSC, AV7110_VIDEO_MODE_NTSC,
- AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_NTSC,
- AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
- AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
- AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
- AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
+static int sw2mode[16] = {
+ VIDEO_MODE_PAL, VIDEO_MODE_NTSC, VIDEO_MODE_NTSC, VIDEO_MODE_PAL,
+ VIDEO_MODE_NTSC, VIDEO_MODE_NTSC, VIDEO_MODE_PAL, VIDEO_MODE_NTSC,
+ VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL,
+ VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL,
};
static int get_video_format(struct av7110 *av7110, u8 *buf, int count)
diff --git a/trunk/drivers/media/dvb/ttpci/av7110_av.h b/trunk/drivers/media/dvb/ttpci/av7110_av.h
index 5f02ef85e47d..45dc144b8b43 100644
--- a/trunk/drivers/media/dvb/ttpci/av7110_av.h
+++ b/trunk/drivers/media/dvb/ttpci/av7110_av.h
@@ -3,8 +3,7 @@
struct av7110;
-extern int av7110_set_vidmode(struct av7110 *av7110,
- enum av7110_video_mode mode);
+extern int av7110_set_vidmode(struct av7110 *av7110, int mode);
extern int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len);
extern int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen);
diff --git a/trunk/drivers/media/dvb/ttpci/av7110_v4l.c b/trunk/drivers/media/dvb/ttpci/av7110_v4l.c
index e2f066fb7967..76cca003252f 100644
--- a/trunk/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/trunk/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -876,11 +876,11 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
if (std->id & V4L2_STD_PAL) {
- av7110->vidmode = AV7110_VIDEO_MODE_PAL;
+ av7110->vidmode = VIDEO_MODE_PAL;
av7110_set_vidmode(av7110, av7110->vidmode);
}
else if (std->id & V4L2_STD_NTSC) {
- av7110->vidmode = AV7110_VIDEO_MODE_NTSC;
+ av7110->vidmode = VIDEO_MODE_NTSC;
av7110_set_vidmode(av7110, av7110->vidmode);
}
else
diff --git a/trunk/drivers/media/radio/Kconfig b/trunk/drivers/media/radio/Kconfig
index 8d5214f18cf0..11e962f1a97f 100644
--- a/trunk/drivers/media/radio/Kconfig
+++ b/trunk/drivers/media/radio/Kconfig
@@ -351,14 +351,4 @@ config USB_DSBR
To compile this driver as a module, choose M here: the
module will be called dsbr100.
-config USB_SI470X
- tristate "Silicon Labs Si470x FM Radio Receiver support"
- depends on USB && VIDEO_V4L2
- ---help---
- Say Y here if you want to connect this type of radio to your
- computer's USB port.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-silabs.
-
endif # RADIO_ADAPTERS
diff --git a/trunk/drivers/media/radio/Makefile b/trunk/drivers/media/radio/Makefile
index a30159f6fa42..cf55a18e3ddf 100644
--- a/trunk/drivers/media/radio/Makefile
+++ b/trunk/drivers/media/radio/Makefile
@@ -21,6 +21,5 @@ obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o
obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
-obj-$(CONFIG_USB_SI470X) += radio-si470x.o
EXTRA_CFLAGS += -Isound
diff --git a/trunk/drivers/media/radio/dsbr100.c b/trunk/drivers/media/radio/dsbr100.c
index 36c0e3651502..3bd07f7e3774 100644
--- a/trunk/drivers/media/radio/dsbr100.c
+++ b/trunk/drivers/media/radio/dsbr100.c
@@ -33,9 +33,6 @@
History:
- Version 0.43:
- Oliver Neukum: avoided DMA coherency issue
-
Version 0.42:
Converted dsbr100 to use video_ioctl2
by Douglas Landgraf
@@ -138,7 +135,7 @@ module_param(radio_nr, int, 0);
struct dsbr100_device {
struct usb_device *usbdev;
struct video_device *videodev;
- u8 *transfer_buffer;
+ unsigned char transfer_buffer[TB_LEN];
int curfreq;
int stereo;
int users;
@@ -240,7 +237,10 @@ static void dsbr100_getstat(struct dsbr100_device *radio)
/* handle unplugging of the device, release data structures
if nothing keeps us from doing it. If something is still
keeping us busy, the release callback of v4l will take care
-of releasing it. */
+of releasing it. stv680.c does not relase its private
+data, so I don't do this here either. Checking out the
+code I'd expect I better did that, but if there's a memory
+leak here it's tiny (~50 bytes per disconnect) */
static void usb_dsbr100_disconnect(struct usb_interface *intf)
{
struct dsbr100_device *radio = usb_get_intfdata(intf);
@@ -250,7 +250,6 @@ static void usb_dsbr100_disconnect(struct usb_interface *intf)
video_unregister_device(radio->videodev);
radio->videodev = NULL;
if (radio->users) {
- kfree(radio->transfer_buffer);
kfree(radio);
} else {
radio->removed = 1;
@@ -426,7 +425,6 @@ static int usb_dsbr100_close(struct inode *inode, struct file *file)
return -ENODEV;
radio->users = 0;
if (radio->removed) {
- kfree(radio->transfer_buffer);
kfree(radio);
}
return 0;
@@ -473,12 +471,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
return -ENOMEM;
- if (!(radio->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL))) {
- kfree(radio);
- return -ENOMEM;
- }
if (!(radio->videodev = video_device_alloc())) {
- kfree(radio->transfer_buffer);
kfree(radio);
return -ENOMEM;
}
@@ -492,7 +485,6 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
if (video_register_device(radio->videodev, VFL_TYPE_RADIO,radio_nr)) {
warn("Could not register video device");
video_device_release(radio->videodev);
- kfree(radio->transfer_buffer);
kfree(radio);
return -EIO;
}
diff --git a/trunk/drivers/media/radio/radio-gemtek.c b/trunk/drivers/media/radio/radio-gemtek.c
index 246422b49267..5e4b9ddb23c0 100644
--- a/trunk/drivers/media/radio/radio-gemtek.c
+++ b/trunk/drivers/media/radio/radio-gemtek.c
@@ -58,10 +58,10 @@ static int initmute = 1;
static int radio_nr = -1;
module_param(io, int, 0444);
-MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic "
+MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic"
"probing is disabled or fails. The most common I/O ports are: 0x20c "
"0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to "
- "work for the combined sound/radiocard).");
+ " work for the combined sound/radiocard).");
module_param(probe, bool, 0444);
MODULE_PARM_DESC(probe, "Enable automatic device probing. Note: only the most "
@@ -392,7 +392,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
}
};
-static const struct file_operations gemtek_fops = {
+static struct file_operations gemtek_fops = {
.owner = THIS_MODULE,
.open = video_exclusive_open,
.release = video_exclusive_release,
diff --git a/trunk/drivers/media/radio/radio-maestro.c b/trunk/drivers/media/radio/radio-maestro.c
index bc51f4d23a5a..8e33a19a22a3 100644
--- a/trunk/drivers/media/radio/radio-maestro.c
+++ b/trunk/drivers/media/radio/radio-maestro.c
@@ -423,7 +423,7 @@ static int __devinit maestro_probe(struct pci_dev *pdev,
errunr:
video_unregister_device(maestro_radio_inst);
errfr1:
- video_device_release(maestro_radio_inst);
+ kfree(maestro_radio_inst);
errfr:
kfree(radio_unit);
err:
diff --git a/trunk/drivers/media/radio/radio-sf16fmi.c b/trunk/drivers/media/radio/radio-sf16fmi.c
index 3118bdab3183..395165367f37 100644
--- a/trunk/drivers/media/radio/radio-sf16fmi.c
+++ b/trunk/drivers/media/radio/radio-sf16fmi.c
@@ -321,7 +321,7 @@ static struct isapnp_device_id id_table[] __devinitdata = {
MODULE_DEVICE_TABLE(isapnp, id_table);
-static int __init isapnp_fmi_probe(void)
+static int isapnp_fmi_probe(void)
{
int i = 0;
diff --git a/trunk/drivers/media/radio/radio-sf16fmr2.c b/trunk/drivers/media/radio/radio-sf16fmr2.c
index f7c8b000404f..c432c44bd634 100644
--- a/trunk/drivers/media/radio/radio-sf16fmr2.c
+++ b/trunk/drivers/media/radio/radio-sf16fmr2.c
@@ -476,7 +476,8 @@ static int __init fmr2_init(void)
return -EBUSY;
}
- if (video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
+ if(video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr)==-1)
+ {
release_region(io, 2);
return -EINVAL;
}
diff --git a/trunk/drivers/media/radio/radio-si470x.c b/trunk/drivers/media/radio/radio-si470x.c
deleted file mode 100644
index 8e4bd4769048..000000000000
--- a/trunk/drivers/media/radio/radio-si470x.c
+++ /dev/null
@@ -1,1432 +0,0 @@
-/*
- * drivers/media/radio/radio-si470x.c
- *
- * Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers:
- * - Silicon Labs USB FM Radio Reference Design
- * - ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF)
- *
- * Copyright (c) 2008 Tobias Lorenz
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/*
- * History:
- * 2008-01-12 Tobias Lorenz
- * Version 1.0.0
- * - First working version
- * 2008-01-13 Tobias Lorenz
- * Version 1.0.1
- * - Improved error handling, every function now returns errno
- * - Improved multi user access (start/mute/stop)
- * - Channel doesn't get lost anymore after start/mute/stop
- * - RDS support added (polling mode via interrupt EP 1)
- * - marked default module parameters with *value*
- * - switched from bit structs to bit masks
- * - header file cleaned and integrated
- * 2008-01-14 Tobias Lorenz
- * Version 1.0.2
- * - hex values are now lower case
- * - commented USB ID for ADS/Tech moved on todo list
- * - blacklisted si470x in hid-quirks.c
- * - rds buffer handling functions integrated into *_work, *_read
- * - rds_command in si470x_poll exchanged against simple retval
- * - check for firmware version 15
- * - code order and prototypes still remain the same
- * - spacing and bottom of band codes remain the same
- * 2008-01-16 Tobias Lorenz
- * Version 1.0.3
- * - code reordered to avoid function prototypes
- * - switch/case defaults are now more user-friendly
- * - unified comment style
- * - applied all checkpatch.pl v1.12 suggestions
- * except the warning about the too long lines with bit comments
- * - renamed FMRADIO to RADIO to cut line length (checkpatch.pl)
- * 2008-01-22 Tobias Lorenz
- * Version 1.0.4
- * - avoid poss. locking when doing copy_to_user which may sleep
- * - RDS is automatically activated on read now
- * - code cleaned of unnecessary rds_commands
- * - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified
- * (thanks to Guillaume RAMOUSSE)
- *
- * ToDo:
- * - add seeking support
- * - add firmware download/update support
- * - RDS support: interrupt mode, instead of polling
- * - add LED status output (check if that's not already done in firmware)
- */
-
-
-/* driver definitions */
-#define DRIVER_AUTHOR "Tobias Lorenz "
-#define DRIVER_NAME "radio-si470x"
-#define DRIVER_VERSION KERNEL_VERSION(1, 0, 4)
-#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
-#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
-
-
-/* kernel includes */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-/* USB Device ID List */
-static struct usb_device_id si470x_usb_driver_id_table[] = {
- /* Silicon Labs USB FM Radio Reference Design */
- { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },
- /* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */
- { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },
- /* Terminating entry */
- { }
-};
-MODULE_DEVICE_TABLE(usb, si470x_usb_driver_id_table);
-
-
-
-/**************************************************************************
- * Module Parameters
- **************************************************************************/
-
-/* Radio Nr */
-static int radio_nr = -1;
-module_param(radio_nr, int, 0);
-MODULE_PARM_DESC(radio_nr, "Radio Nr");
-
-/* Spacing (kHz) */
-/* 0: 200 kHz (USA, Australia) */
-/* 1: 100 kHz (Europe, Japan) */
-/* 2: 50 kHz */
-static int space = 2;
-module_param(space, int, 0);
-MODULE_PARM_DESC(radio_nr, "Spacing: 0=200kHz 1=100kHz *2=50kHz*");
-
-/* Bottom of Band (MHz) */
-/* 0: 87.5 - 108 MHz (USA, Europe)*/
-/* 1: 76 - 108 MHz (Japan wide band) */
-/* 2: 76 - 90 MHz (Japan) */
-static int band = 1;
-module_param(band, int, 0);
-MODULE_PARM_DESC(radio_nr, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz");
-
-/* De-emphasis */
-/* 0: 75 us (USA) */
-/* 1: 50 us (Europe, Australia, Japan) */
-static int de = 1;
-module_param(de, int, 0);
-MODULE_PARM_DESC(radio_nr, "De-emphasis: 0=75us *1=50us*");
-
-/* USB timeout */
-static int usb_timeout = 500;
-module_param(usb_timeout, int, 0);
-MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*");
-
-/* Seek retries */
-static int seek_retries = 100;
-module_param(seek_retries, int, 0);
-MODULE_PARM_DESC(seek_retries, "Seek retries: *100*");
-
-/* RDS buffer blocks */
-static int rds_buf = 100;
-module_param(rds_buf, int, 0);
-MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
-
-/* RDS maximum block errors */
-static int max_rds_errors = 1;
-/* 0 means 0 errors requiring correction */
-/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */
-/* 2 means 3-5 errors requiring correction */
-/* 3 means 6+ errors or errors in checkword, correction not possible */
-module_param(max_rds_errors, int, 0);
-MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
-
-/* RDS poll frequency */
-static int rds_poll_time = 40;
-/* 40 is used by the original USBRadio.exe */
-/* 50 is used by radio-cadet */
-/* 75 should be okay */
-/* 80 is the usual RDS receive interval */
-module_param(rds_poll_time, int, 0);
-MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
-
-
-
-/**************************************************************************
- * Register Definitions
- **************************************************************************/
-#define RADIO_REGISTER_SIZE 2 /* 16 register bit width */
-#define RADIO_REGISTER_NUM 16 /* DEVICEID ... RDSD */
-#define RDS_REGISTER_NUM 6 /* STATUSRSSI ... RDSD */
-
-#define DEVICEID 0 /* Device ID */
-#define DEVICEID_PN 0xf000 /* bits 15..12: Part Number */
-#define DEVICEID_MFGID 0x0fff /* bits 11..00: Manufacturer ID */
-
-#define CHIPID 1 /* Chip ID */
-#define CHIPID_REV 0xfc00 /* bits 15..10: Chip Version */
-#define CHIPID_DEV 0x0200 /* bits 09..09: Device */
-#define CHIPID_FIRMWARE 0x01ff /* bits 08..00: Firmware Version */
-
-#define POWERCFG 2 /* Power Configuration */
-#define POWERCFG_DSMUTE 0x8000 /* bits 15..15: Softmute Disable */
-#define POWERCFG_DMUTE 0x4000 /* bits 14..14: Mute Disable */
-#define POWERCFG_MONO 0x2000 /* bits 13..13: Mono Select */
-#define POWERCFG_RDSM 0x0800 /* bits 11..11: RDS Mode (Si4701 only) */
-#define POWERCFG_SKMODE 0x0400 /* bits 10..10: Seek Mode */
-#define POWERCFG_SEEKUP 0x0200 /* bits 09..09: Seek Direction */
-#define POWERCFG_SEEK 0x0100 /* bits 08..08: Seek */
-#define POWERCFG_DISABLE 0x0040 /* bits 06..06: Powerup Disable */
-#define POWERCFG_ENABLE 0x0001 /* bits 00..00: Powerup Enable */
-
-#define CHANNEL 3 /* Channel */
-#define CHANNEL_TUNE 0x8000 /* bits 15..15: Tune */
-#define CHANNEL_CHAN 0x03ff /* bits 09..00: Channel Select */
-
-#define SYSCONFIG1 4 /* System Configuration 1 */
-#define SYSCONFIG1_RDSIEN 0x8000 /* bits 15..15: RDS Interrupt Enable (Si4701 only) */
-#define SYSCONFIG1_STCIEN 0x4000 /* bits 14..14: Seek/Tune Complete Interrupt Enable */
-#define SYSCONFIG1_RDS 0x1000 /* bits 12..12: RDS Enable (Si4701 only) */
-#define SYSCONFIG1_DE 0x0800 /* bits 11..11: De-emphasis (0=75us 1=50us) */
-#define SYSCONFIG1_AGCD 0x0400 /* bits 10..10: AGC Disable */
-#define SYSCONFIG1_BLNDADJ 0x00c0 /* bits 07..06: Stereo/Mono Blend Level Adjustment */
-#define SYSCONFIG1_GPIO3 0x0030 /* bits 05..04: General Purpose I/O 3 */
-#define SYSCONFIG1_GPIO2 0x000c /* bits 03..02: General Purpose I/O 2 */
-#define SYSCONFIG1_GPIO1 0x0003 /* bits 01..00: General Purpose I/O 1 */
-
-#define SYSCONFIG2 5 /* System Configuration 2 */
-#define SYSCONFIG2_SEEKTH 0xff00 /* bits 15..08: RSSI Seek Threshold */
-#define SYSCONFIG2_BAND 0x0080 /* bits 07..06: Band Select */
-#define SYSCONFIG2_SPACE 0x0030 /* bits 05..04: Channel Spacing */
-#define SYSCONFIG2_VOLUME 0x000f /* bits 03..00: Volume */
-
-#define SYSCONFIG3 6 /* System Configuration 3 */
-#define SYSCONFIG3_SMUTER 0xc000 /* bits 15..14: Softmute Attack/Recover Rate */
-#define SYSCONFIG3_SMUTEA 0x3000 /* bits 13..12: Softmute Attenuation */
-#define SYSCONFIG3_SKSNR 0x00f0 /* bits 07..04: Seek SNR Threshold */
-#define SYSCONFIG3_SKCNT 0x000f /* bits 03..00: Seek FM Impulse Detection Threshold */
-
-#define TEST1 7 /* Test 1 */
-#define TEST1_AHIZEN 0x4000 /* bits 14..14: Audio High-Z Enable */
-
-#define TEST2 8 /* Test 2 */
-/* TEST2 only contains reserved bits */
-
-#define BOOTCONFIG 9 /* Boot Configuration */
-/* BOOTCONFIG only contains reserved bits */
-
-#define STATUSRSSI 10 /* Status RSSI */
-#define STATUSRSSI_RDSR 0x8000 /* bits 15..15: RDS Ready (Si4701 only) */
-#define STATUSRSSI_STC 0x4000 /* bits 14..14: Seek/Tune Complete */
-#define STATUSRSSI_SF 0x2000 /* bits 13..13: Seek Fail/Band Limit */
-#define STATUSRSSI_AFCRL 0x1000 /* bits 12..12: AFC Rail */
-#define STATUSRSSI_RDSS 0x0800 /* bits 11..11: RDS Synchronized (Si4701 only) */
-#define STATUSRSSI_BLERA 0x0600 /* bits 10..09: RDS Block A Errors (Si4701 only) */
-#define STATUSRSSI_ST 0x0100 /* bits 08..08: Stereo Indicator */
-#define STATUSRSSI_RSSI 0x00ff /* bits 07..00: RSSI (Received Signal Strength Indicator) */
-
-#define READCHAN 11 /* Read Channel */
-#define READCHAN_BLERB 0xc000 /* bits 15..14: RDS Block D Errors (Si4701 only) */
-#define READCHAN_BLERC 0x3000 /* bits 13..12: RDS Block C Errors (Si4701 only) */
-#define READCHAN_BLERD 0x0c00 /* bits 11..10: RDS Block B Errors (Si4701 only) */
-#define READCHAN_READCHAN 0x03ff /* bits 09..00: Read Channel */
-
-#define RDSA 12 /* RDSA */
-#define RDSA_RDSA 0xffff /* bits 15..00: RDS Block A Data (Si4701 only) */
-
-#define RDSB 13 /* RDSB */
-#define RDSB_RDSB 0xffff /* bits 15..00: RDS Block B Data (Si4701 only) */
-
-#define RDSC 14 /* RDSC */
-#define RDSC_RDSC 0xffff /* bits 15..00: RDS Block C Data (Si4701 only) */
-
-#define RDSD 15 /* RDSD */
-#define RDSD_RDSD 0xffff /* bits 15..00: RDS Block D Data (Si4701 only) */
-
-
-
-/**************************************************************************
- * USB HID Reports
- **************************************************************************/
-
-/* Reports 1-16 give direct read/write access to the 16 Si470x registers */
-/* with the (REPORT_ID - 1) corresponding to the register address across USB */
-/* endpoint 0 using GET_REPORT and SET_REPORT */
-#define REGISTER_REPORT_SIZE (RADIO_REGISTER_SIZE + 1)
-#define REGISTER_REPORT(reg) ((reg) + 1)
-
-/* Report 17 gives direct read/write access to the entire Si470x register */
-/* map across endpoint 0 using GET_REPORT and SET_REPORT */
-#define ENTIRE_REPORT_SIZE (RADIO_REGISTER_NUM * RADIO_REGISTER_SIZE + 1)
-#define ENTIRE_REPORT 17
-
-/* Report 18 is used to send the lowest 6 Si470x registers up the HID */
-/* interrupt endpoint 1 to Windows every 20 milliseconds for status */
-#define RDS_REPORT_SIZE (RDS_REGISTER_NUM * RADIO_REGISTER_SIZE + 1)
-#define RDS_REPORT 18
-
-/* Report 19: LED state */
-#define LED_REPORT_SIZE 3
-#define LED_REPORT 19
-
-/* Report 19: stream */
-#define STREAM_REPORT_SIZE 3
-#define STREAM_REPORT 19
-
-/* Report 20: scratch */
-#define SCRATCH_PAGE_SIZE 63
-#define SCRATCH_REPORT_SIZE (SCRATCH_PAGE_SIZE + 1)
-#define SCRATCH_REPORT 20
-
-/* Reports 19-22: flash upgrade of the C8051F321 */
-#define WRITE_REPORT 19
-#define FLASH_REPORT 20
-#define CRC_REPORT 21
-#define RESPONSE_REPORT 22
-
-/* Report 23: currently unused, but can accept 60 byte reports on the HID */
-/* interrupt out endpoint 2 every 1 millisecond */
-#define UNUSED_REPORT 23
-
-
-
-/**************************************************************************
- * Software/Hardware Versions
- **************************************************************************/
-#define RADIO_SW_VERSION_NOT_BOOTLOADABLE 6
-#define RADIO_SW_VERSION 7
-#define RADIO_SW_VERSION_CURRENT 15
-#define RADIO_HW_VERSION 1
-
-#define SCRATCH_PAGE_SW_VERSION 1
-#define SCRATCH_PAGE_HW_VERSION 2
-
-
-
-/**************************************************************************
- * LED State Definitions
- **************************************************************************/
-#define LED_COMMAND 0x35
-
-#define NO_CHANGE_LED 0x00
-#define ALL_COLOR_LED 0x01 /* streaming state */
-#define BLINK_GREEN_LED 0x02 /* connect state */
-#define BLINK_RED_LED 0x04
-#define BLINK_ORANGE_LED 0x10 /* disconnect state */
-#define SOLID_GREEN_LED 0x20 /* tuning/seeking state */
-#define SOLID_RED_LED 0x40 /* bootload state */
-#define SOLID_ORANGE_LED 0x80
-
-
-
-/**************************************************************************
- * Stream State Definitions
- **************************************************************************/
-#define STREAM_COMMAND 0x36
-#define STREAM_VIDPID 0x00
-#define STREAM_AUDIO 0xff
-
-
-
-/**************************************************************************
- * Bootloader / Flash Commands
- **************************************************************************/
-
-/* unique id sent to bootloader and required to put into a bootload state */
-#define UNIQUE_BL_ID 0x34
-
-/* mask for the flash data */
-#define FLASH_DATA_MASK 0x55
-
-/* bootloader commands */
-#define GET_SW_VERSION_COMMAND 0x00
-#define SET_PAGE_COMMAND 0x01
-#define ERASE_PAGE_COMMAND 0x02
-#define WRITE_PAGE_COMMAND 0x03
-#define CRC_ON_PAGE_COMMAND 0x04
-#define READ_FLASH_BYTE_COMMAND 0x05
-#define RESET_DEVICE_COMMAND 0x06
-#define GET_HW_VERSION_COMMAND 0x07
-#define BLANK 0xff
-
-/* bootloader command responses */
-#define COMMAND_OK 0x01
-#define COMMAND_FAILED 0x02
-#define COMMAND_PENDING 0x03
-
-/* buffer sizes */
-#define COMMAND_BUFFER_SIZE 4
-#define RESPONSE_BUFFER_SIZE 2
-#define FLASH_BUFFER_SIZE 64
-#define CRC_BUFFER_SIZE 3
-
-
-
-/**************************************************************************
- * General Driver Definitions
- **************************************************************************/
-
-/*
- * si470x_device - private data
- */
-struct si470x_device {
- /* reference to USB and video device */
- struct usb_device *usbdev;
- struct video_device *videodev;
-
- /* are these really necessary ? */
- int users;
-
- /* report buffer (maximum 64 bytes) */
- unsigned char buf[64];
-
- /* Silabs internal registers (0..15) */
- unsigned short registers[RADIO_REGISTER_NUM];
-
- /* RDS receive buffer */
- struct work_struct work;
- wait_queue_head_t read_queue;
- struct timer_list timer;
- spinlock_t lock; /* buffer locking */
- unsigned char *buffer; /* size is always multiple of three */
- unsigned int buf_size;
- unsigned int rd_index;
- unsigned int wr_index;
-};
-
-
-/*
- * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW,
- * 62.5 kHz otherwise.
- * The tuner is able to have a channel spacing of 50, 100 or 200 kHz.
- * tuner->capability is therefore set to V4L2_TUNER_CAP_LOW
- * The FREQ_MUL is then: 1 MHz / 62.5 Hz = 16000
- */
-#define FREQ_MUL (1000000 / 62.5)
-
-
-
-/**************************************************************************
- * General Driver Functions
- **************************************************************************/
-
-/*
- * si470x_get_report - receive a HID report
- */
-static int si470x_get_report(struct si470x_device *radio, int size)
-{
- return usb_control_msg(radio->usbdev,
- usb_rcvctrlpipe(radio->usbdev, 0),
- HID_REQ_GET_REPORT,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
- radio->buf[0], 2,
- radio->buf, size, usb_timeout);
-}
-
-
-/*
- * si470x_set_report - send a HID report
- */
-static int si470x_set_report(struct si470x_device *radio, int size)
-{
- return usb_control_msg(radio->usbdev,
- usb_sndctrlpipe(radio->usbdev, 0),
- HID_REQ_SET_REPORT,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
- radio->buf[0], 2,
- radio->buf, size, usb_timeout);
-}
-
-
-/*
- * si470x_get_register - read register
- */
-static int si470x_get_register(struct si470x_device *radio, int regnr)
-{
- int retval;
-
- radio->buf[0] = REGISTER_REPORT(regnr);
-
- retval = si470x_get_report(radio, REGISTER_REPORT_SIZE);
- if (retval >= 0)
- radio->registers[regnr] = (radio->buf[1] << 8) | radio->buf[2];
-
- return (retval < 0) ? -EINVAL : 0;
-}
-
-
-/*
- * si470x_set_register - write register
- */
-static int si470x_set_register(struct si470x_device *radio, int regnr)
-{
- int retval;
-
- radio->buf[0] = REGISTER_REPORT(regnr);
- radio->buf[1] = (radio->registers[regnr] & 0xff00) >> 8;
- radio->buf[2] = (radio->registers[regnr] & 0x00ff);
-
- retval = si470x_set_report(radio, REGISTER_REPORT_SIZE);
-
- return (retval < 0) ? -EINVAL : 0;
-}
-
-
-/*
- * si470x_get_all_registers - read entire registers
- */
-static int si470x_get_all_registers(struct si470x_device *radio)
-{
- int retval;
- int regnr;
-
- radio->buf[0] = ENTIRE_REPORT;
-
- retval = si470x_get_report(radio, ENTIRE_REPORT_SIZE);
-
- if (retval >= 0)
- for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)
- radio->registers[regnr] =
- (radio->buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) |
- radio->buf[regnr * RADIO_REGISTER_SIZE + 2];
-
- return (retval < 0) ? -EINVAL : 0;
-}
-
-
-/*
- * si470x_get_rds_registers - read rds registers
- */
-static int si470x_get_rds_registers(struct si470x_device *radio)
-{
- int retval;
- int regnr;
- int size;
-
- radio->buf[0] = RDS_REPORT;
-
- retval = usb_interrupt_msg(radio->usbdev,
- usb_rcvctrlpipe(radio->usbdev, 1),
- radio->buf, RDS_REPORT_SIZE, &size, usb_timeout);
-
- if (retval >= 0)
- for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
- radio->registers[STATUSRSSI + regnr] =
- (radio->buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) |
- radio->buf[regnr * RADIO_REGISTER_SIZE + 2];
-
- return (retval < 0) ? -EINVAL : 0;
-}
-
-
-/*
- * si470x_set_chan - set the channel
- */
-static int si470x_set_chan(struct si470x_device *radio, int chan)
-{
- int retval, i;
-
- /* start tuning */
- radio->registers[CHANNEL] &= ~CHANNEL_CHAN;
- radio->registers[CHANNEL] |= CHANNEL_TUNE | chan;
- retval = si470x_set_register(radio, CHANNEL);
- if (retval < 0)
- return retval;
-
- /* wait till seek operation has completed */
- i = 0;
- do {
- retval = si470x_get_register(radio, STATUSRSSI);
- if (retval < 0)
- return retval;
- } while ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) &&
- (++i < seek_retries));
- if (i >= seek_retries)
- printk(KERN_WARNING DRIVER_NAME
- ": seek does not finish after %d tries\n", i);
-
- /* stop tuning */
- radio->registers[CHANNEL] &= ~CHANNEL_TUNE;
- return si470x_set_register(radio, CHANNEL);
-}
-
-
-/*
- * si470x_get_freq - get the frequency
- */
-static int si470x_get_freq(struct si470x_device *radio)
-{
- int spacing, band_bottom, chan, freq;
- int retval;
-
- /* Spacing (kHz) */
- switch (space) {
- /* 0: 200 kHz (USA, Australia) */
- case 0 : spacing = 0.200 * FREQ_MUL; break;
- /* 1: 100 kHz (Europe, Japan) */
- case 1 : spacing = 0.100 * FREQ_MUL; break;
- /* 2: 50 kHz */
- default: spacing = 0.050 * FREQ_MUL; break;
- };
-
- /* Bottom of Band (MHz) */
- switch (band) {
- /* 0: 87.5 - 108 MHz (USA, Europe) */
- case 0 : band_bottom = 87.5 * FREQ_MUL; break;
- /* 1: 76 - 108 MHz (Japan wide band) */
- default: band_bottom = 76 * FREQ_MUL; break;
- /* 2: 76 - 90 MHz (Japan) */
- case 2 : band_bottom = 76 * FREQ_MUL; break;
- };
-
- /* read channel */
- retval = si470x_get_register(radio, READCHAN);
- if (retval < 0)
- return retval;
- chan = radio->registers[READCHAN] & READCHAN_READCHAN;
-
- /* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */
- freq = chan * spacing + band_bottom;
-
- return freq;
-}
-
-
-/*
- * si470x_set_freq - set the frequency
- */
-static int si470x_set_freq(struct si470x_device *radio, int freq)
-{
- int spacing, band_bottom, chan;
-
- /* Spacing (kHz) */
- switch (space) {
- /* 0: 200 kHz (USA, Australia) */
- case 0 : spacing = 0.200 * FREQ_MUL; break;
- /* 1: 100 kHz (Europe, Japan) */
- case 1 : spacing = 0.100 * FREQ_MUL; break;
- /* 2: 50 kHz */
- default: spacing = 0.050 * FREQ_MUL; break;
- };
-
- /* Bottom of Band (MHz) */
- switch (band) {
- /* 0: 87.5 - 108 MHz (USA, Europe) */
- case 0 : band_bottom = 87.5 * FREQ_MUL; break;
- /* 1: 76 - 108 MHz (Japan wide band) */
- default: band_bottom = 76 * FREQ_MUL; break;
- /* 2: 76 - 90 MHz (Japan) */
- case 2 : band_bottom = 76 * FREQ_MUL; break;
- };
-
- /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
- chan = (freq - band_bottom) / spacing;
-
- return si470x_set_chan(radio, chan);
-}
-
-
-/*
- * si470x_start - switch on radio
- */
-static int si470x_start(struct si470x_device *radio)
-{
- int retval;
-
- /* powercfg */
- radio->registers[POWERCFG] =
- POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM;
- retval = si470x_set_register(radio, POWERCFG);
- if (retval < 0)
- return retval;
-
- /* sysconfig 1 */
- radio->registers[SYSCONFIG1] = SYSCONFIG1_DE;
- retval = si470x_set_register(radio, SYSCONFIG1);
- if (retval < 0)
- return retval;
-
- /* sysconfig 2 */
- radio->registers[SYSCONFIG2] =
- (0x3f << 8) | /* SEEKTH */
- (band << 6) | /* BAND */
- (space << 4) | /* SPACE */
- 15; /* VOLUME (max) */
- retval = si470x_set_register(radio, SYSCONFIG2);
- if (retval < 0)
- return retval;
-
- /* reset last channel */
- return si470x_set_chan(radio,
- radio->registers[CHANNEL] & CHANNEL_CHAN);
-}
-
-
-/*
- * si470x_stop - switch off radio
- */
-static int si470x_stop(struct si470x_device *radio)
-{
- int retval;
-
- /* sysconfig 1 */
- radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
- retval = si470x_set_register(radio, SYSCONFIG1);
- if (retval < 0)
- return retval;
-
- /* powercfg */
- radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
- /* POWERCFG_ENABLE has to automatically go low */
- radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE;
- return si470x_set_register(radio, POWERCFG);
-}
-
-
-/*
- * si470x_rds_on - switch on rds reception
- */
-static int si470x_rds_on(struct si470x_device *radio)
-{
- /* sysconfig 1 */
- radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS;
- return si470x_set_register(radio, SYSCONFIG1);
-}
-
-
-
-/**************************************************************************
- * RDS Driver Functions
- **************************************************************************/
-
-/*
- * si470x_rds - rds processing function
- */
-static void si470x_rds(struct si470x_device *radio)
-{
- unsigned char tmpbuf[3];
- unsigned char blocknum;
- unsigned char bler; /* rds block errors */
- unsigned short rds;
- unsigned int i;
-
- /* get rds blocks */
- if (si470x_get_rds_registers(radio) < 0)
- return;
- if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) {
- /* No RDS group ready */
- return;
- }
- if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSS) == 0) {
- /* RDS decoder not synchronized */
- return;
- }
-
- /* copy four RDS blocks to internal buffer */
- if (spin_trylock(&radio->lock)) {
- /* process each rds block */
- for (blocknum = 0; blocknum < 4; blocknum++) {
- switch (blocknum) {
- default:
- bler = (radio->registers[STATUSRSSI] &
- STATUSRSSI_BLERA) >> 9;
- rds = radio->registers[RDSA];
- break;
- case 1:
- bler = (radio->registers[READCHAN] &
- READCHAN_BLERB) >> 14;
- rds = radio->registers[RDSB];
- break;
- case 2:
- bler = (radio->registers[READCHAN] &
- READCHAN_BLERC) >> 12;
- rds = radio->registers[RDSC];
- break;
- case 3:
- bler = (radio->registers[READCHAN] &
- READCHAN_BLERD) >> 10;
- rds = radio->registers[RDSD];
- break;
- };
-
- /* Fill the V4L2 RDS buffer */
- tmpbuf[0] = rds & 0x00ff; /* LSB */
- tmpbuf[1] = (rds & 0xff00) >> 8;/* MSB */
- tmpbuf[2] = blocknum; /* offset name */
- tmpbuf[2] |= blocknum << 3; /* received offset */
- if (bler > max_rds_errors)
- tmpbuf[2] |= 0x80; /* uncorrectable errors */
- else if (bler > 0)
- tmpbuf[2] |= 0x40; /* corrected error(s) */
-
- /* copy RDS block to internal buffer */
- for (i = 0; i < 3; i++) {
- radio->buffer[radio->wr_index] = tmpbuf[i];
- radio->wr_index++;
- }
-
- /* wrap write pointer */
- if (radio->wr_index >= radio->buf_size)
- radio->wr_index = 0;
-
- /* check for overflow */
- if (radio->wr_index == radio->rd_index) {
- /* increment and wrap read pointer */
- radio->rd_index += 3;
- if (radio->rd_index >= radio->buf_size)
- radio->rd_index = 0;
- }
- }
- spin_unlock(&radio->lock);
- }
-
- /* wake up read queue */
- if (radio->wr_index != radio->rd_index)
- wake_up_interruptible(&radio->read_queue);
-}
-
-
-/*
- * si470x_timer - rds timer function
- */
-static void si470x_timer(unsigned long data)
-{
- struct si470x_device *radio = (struct si470x_device *) data;
-
- schedule_work(&radio->work);
-}
-
-
-/*
- * si470x_work - rds work function
- */
-static void si470x_work(struct work_struct *work)
-{
- struct si470x_device *radio = container_of(work, struct si470x_device,
- work);
-
- if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
- return;
-
- si470x_rds(radio);
- mod_timer(&radio->timer, jiffies + msecs_to_jiffies(rds_poll_time));
-}
-
-
-
-/**************************************************************************
- * File Operations Interface
- **************************************************************************/
-
-/*
- * si470x_fops_read - read RDS data
- */
-static ssize_t si470x_fops_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
- int retval = 0;
- unsigned int block_count = 0;
-
- /* switch on rds reception */
- if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) {
- si470x_rds_on(radio);
- schedule_work(&radio->work);
- }
-
- /* block if no new data available */
- while (radio->wr_index == radio->rd_index) {
- if (file->f_flags & O_NONBLOCK)
- return -EWOULDBLOCK;
- interruptible_sleep_on(&radio->read_queue);
- }
-
- /* calculate block count from byte count */
- count /= 3;
-
- /* copy RDS block out of internal buffer and to user buffer */
- if (spin_trylock(&radio->lock)) {
- while (block_count < count) {
- if (radio->rd_index == radio->wr_index)
- break;
-
- /* always transfer rds complete blocks */
- if (copy_to_user(buf,
- &radio->buffer[radio->rd_index], 3))
- /* retval = -EFAULT; */
- break;
-
- /* increment and wrap read pointer */
- radio->rd_index += 3;
- if (radio->rd_index >= radio->buf_size)
- radio->rd_index = 0;
-
- /* increment counters */
- block_count++;
- buf += 3;
- retval += 3;
- }
-
- spin_unlock(&radio->lock);
- }
-
- return retval;
-}
-
-
-/*
- * si470x_fops_poll - poll RDS data
- */
-static unsigned int si470x_fops_poll(struct file *file,
- struct poll_table_struct *pts)
-{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
-
- /* switch on rds reception */
- if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) {
- si470x_rds_on(radio);
- schedule_work(&radio->work);
- }
-
- poll_wait(file, &radio->read_queue, pts);
-
- if (radio->rd_index != radio->wr_index)
- return POLLIN | POLLRDNORM;
-
- return 0;
-}
-
-
-/*
- * si470x_fops_open - file open
- */
-static int si470x_fops_open(struct inode *inode, struct file *file)
-{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
-
- radio->users++;
- if (radio->users == 1)
- return si470x_start(radio);
-
- return 0;
-}
-
-
-/*
- * si470x_fops_release - file release
- */
-static int si470x_fops_release(struct inode *inode, struct file *file)
-{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
-
- if (!radio)
- return -ENODEV;
-
- radio->users--;
- if (radio->users == 0) {
- /* stop rds reception */
- del_timer_sync(&radio->timer);
- flush_scheduled_work();
-
- /* cancel read processes */
- wake_up_interruptible(&radio->read_queue);
-
- return si470x_stop(radio);
- }
-
- return 0;
-}
-
-
-/*
- * si470x_fops - file operations interface
- */
-static const struct file_operations si470x_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = si470x_fops_read,
- .poll = si470x_fops_poll,
- .ioctl = video_ioctl2,
- .compat_ioctl = v4l_compat_ioctl32,
- .open = si470x_fops_open,
- .release = si470x_fops_release,
-};
-
-
-
-/**************************************************************************
- * Video4Linux Interface
- **************************************************************************/
-
-/*
- * si470x_v4l2_queryctrl - query control
- */
-static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = {
-/* HINT: the disabled controls are only here to satify kradio and such apps */
- {
- .id = V4L2_CID_AUDIO_VOLUME,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Volume",
- .minimum = 0,
- .maximum = 15,
- .step = 1,
- .default_value = 15,
- },
- {
- .id = V4L2_CID_AUDIO_BALANCE,
- .flags = V4L2_CTRL_FLAG_DISABLED,
- },
- {
- .id = V4L2_CID_AUDIO_BASS,
- .flags = V4L2_CTRL_FLAG_DISABLED,
- },
- {
- .id = V4L2_CID_AUDIO_TREBLE,
- .flags = V4L2_CTRL_FLAG_DISABLED,
- },
- {
- .id = V4L2_CID_AUDIO_MUTE,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Mute",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 1,
- },
- {
- .id = V4L2_CID_AUDIO_LOUDNESS,
- .flags = V4L2_CTRL_FLAG_DISABLED,
- },
-};
-
-
-/*
- * si470x_vidioc_querycap - query device capabilities
- */
-static int si470x_vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *capability)
-{
- strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
- strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
- sprintf(capability->bus_info, "USB");
- capability->version = DRIVER_VERSION;
- capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
-
- return 0;
-}
-
-
-/*
- * si470x_vidioc_g_input - get input
- */
-static int si470x_vidioc_g_input(struct file *filp, void *priv,
- unsigned int *i)
-{
- *i = 0;
-
- return 0;
-}
-
-
-/*
- * si470x_vidioc_s_input - set input
- */
-static int si470x_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
- if (i != 0)
- return -EINVAL;
-
- return 0;
-}
-
-
-/*
- * si470x_vidioc_queryctrl - enumerate control items
- */
-static int si470x_vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) {
- if (qc->id && qc->id == si470x_v4l2_queryctrl[i].id) {
- memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc));
- return 0;
- }
- }
-
- return -EINVAL;
-}
-
-
-/*
- * si470x_vidioc_g_ctrl - get the value of a control
- */
-static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_VOLUME:
- ctrl->value = radio->registers[SYSCONFIG2] &
- SYSCONFIG2_VOLUME;
- break;
- case V4L2_CID_AUDIO_MUTE:
- ctrl->value = ((radio->registers[POWERCFG] &
- POWERCFG_DMUTE) == 0) ? 1 : 0;
- break;
- }
-
- return 0;
-}
-
-
-/*
- * si470x_vidioc_s_ctrl - set the value of a control
- */
-static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_VOLUME:
- radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
- radio->registers[SYSCONFIG2] |= ctrl->value;
- return si470x_set_register(radio, SYSCONFIG2);
- case V4L2_CID_AUDIO_MUTE:
- if (ctrl->value == 1)
- radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
- else
- radio->registers[POWERCFG] |= POWERCFG_DMUTE;
- return si470x_set_register(radio, POWERCFG);
- }
-
- return -EINVAL;
-}
-
-
-/*
- * si470x_vidioc_g_audio - get audio attributes
- */
-static int si470x_vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *audio)
-{
- if (audio->index > 1)
- return -EINVAL;
-
- strcpy(audio->name, "Radio");
- audio->capability = V4L2_AUDCAP_STEREO;
-
- return 0;
-}
-
-
-/*
- * si470x_vidioc_s_audio - set audio attributes
- */
-static int si470x_vidioc_s_audio(struct file *file, void *priv,
- struct v4l2_audio *audio)
-{
- if (audio->index != 0)
- return -EINVAL;
-
- return 0;
-}
-
-
-/*
- * si470x_vidioc_g_tuner - get tuner attributes
- */
-static int si470x_vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *tuner)
-{
- int retval;
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
-
- if (tuner->index > 0)
- return -EINVAL;
-
- /* read status rssi */
- retval = si470x_get_register(radio, STATUSRSSI);
- if (retval < 0)
- return retval;
-
- strcpy(tuner->name, "FM");
- tuner->type = V4L2_TUNER_RADIO;
- switch (band) {
- /* 0: 87.5 - 108 MHz (USA, Europe, default) */
- default:
- tuner->rangelow = 87.5 * FREQ_MUL;
- tuner->rangehigh = 108 * FREQ_MUL;
- break;
- /* 1: 76 - 108 MHz (Japan wide band) */
- case 1 :
- tuner->rangelow = 76 * FREQ_MUL;
- tuner->rangehigh = 108 * FREQ_MUL;
- break;
- /* 2: 76 - 90 MHz (Japan) */
- case 2 :
- tuner->rangelow = 76 * FREQ_MUL;
- tuner->rangehigh = 90 * FREQ_MUL;
- break;
- };
- tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
- tuner->capability = V4L2_TUNER_CAP_LOW;
-
- /* Stereo indicator == Stereo (instead of Mono) */
- if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 1)
- tuner->audmode = V4L2_TUNER_MODE_STEREO;
- else
- tuner->audmode = V4L2_TUNER_MODE_MONO;
-
- /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */
- tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI)
- * 0x0101;
-
- /* automatic frequency control: -1: freq to low, 1 freq to high */
- tuner->afc = 0;
-
- return 0;
-}
-
-
-/*
- * si470x_vidioc_s_tuner - set tuner attributes
- */
-static int si470x_vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *tuner)
-{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
-
- if (tuner->index > 0)
- return -EINVAL;
-
- if (tuner->audmode == V4L2_TUNER_MODE_MONO)
- radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */
- else
- radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
-
- return si470x_set_register(radio, POWERCFG);
-}
-
-
-/*
- * si470x_vidioc_g_frequency - get tuner or modulator radio frequency
- */
-static int si470x_vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *freq)
-{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
-
- freq->type = V4L2_TUNER_RADIO;
- freq->frequency = si470x_get_freq(radio);
-
- return 0;
-}
-
-
-/*
- * si470x_vidioc_s_frequency - set tuner or modulator radio frequency
- */
-static int si470x_vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *freq)
-{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
-
- if (freq->type != V4L2_TUNER_RADIO)
- return -EINVAL;
-
- return si470x_set_freq(radio, freq->frequency);
-}
-
-
-/*
- * si470x_viddev_tamples - video device interface
- */
-static struct video_device si470x_viddev_template = {
- .fops = &si470x_fops,
- .name = DRIVER_NAME,
- .type = VID_TYPE_TUNER,
- .release = video_device_release,
- .vidioc_querycap = si470x_vidioc_querycap,
- .vidioc_g_input = si470x_vidioc_g_input,
- .vidioc_s_input = si470x_vidioc_s_input,
- .vidioc_queryctrl = si470x_vidioc_queryctrl,
- .vidioc_g_ctrl = si470x_vidioc_g_ctrl,
- .vidioc_s_ctrl = si470x_vidioc_s_ctrl,
- .vidioc_g_audio = si470x_vidioc_g_audio,
- .vidioc_s_audio = si470x_vidioc_s_audio,
- .vidioc_g_tuner = si470x_vidioc_g_tuner,
- .vidioc_s_tuner = si470x_vidioc_s_tuner,
- .vidioc_g_frequency = si470x_vidioc_g_frequency,
- .vidioc_s_frequency = si470x_vidioc_s_frequency,
- .owner = THIS_MODULE,
-};
-
-
-
-/**************************************************************************
- * USB Interface
- **************************************************************************/
-
-/*
- * si470x_usb_driver_probe - probe for the device
- */
-static int si470x_usb_driver_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct si470x_device *radio;
-
- /* memory and interface allocations */
- radio = kmalloc(sizeof(struct si470x_device), GFP_KERNEL);
- if (!radio)
- return -ENOMEM;
- radio->videodev = video_device_alloc();
- if (!radio->videodev) {
- kfree(radio);
- return -ENOMEM;
- }
- memcpy(radio->videodev, &si470x_viddev_template,
- sizeof(si470x_viddev_template));
- radio->users = 0;
- radio->usbdev = interface_to_usbdev(intf);
- video_set_drvdata(radio->videodev, radio);
- if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
- printk(KERN_WARNING DRIVER_NAME
- ": Could not register video device\n");
- video_device_release(radio->videodev);
- kfree(radio);
- return -EIO;
- }
- usb_set_intfdata(intf, radio);
-
- /* show some infos about the specific device */
- if (si470x_get_all_registers(radio) < 0) {
- video_device_release(radio->videodev);
- kfree(radio);
- return -EIO;
- }
- printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4x ChipID=0x%4.4x\n",
- radio->registers[DEVICEID], radio->registers[CHIPID]);
-
- /* check if firmware is current */
- if ((radio->registers[CHIPID] & CHIPID_FIRMWARE)
- < RADIO_SW_VERSION_CURRENT)
- printk(KERN_WARNING DRIVER_NAME
- ": This driver is known to work with chip version %d, "
- "but the device has firmware %d.\n"
- DRIVER_NAME
- "If you have some trouble using this driver, please "
- "report to V4L ML at video4linux-list@redhat.com\n",
- radio->registers[CHIPID] & CHIPID_FIRMWARE,
- RADIO_SW_VERSION_CURRENT);
-
- /* set initial frequency */
- si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
-
- /* rds initialization */
- radio->buf_size = rds_buf * 3;
- radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
- if (!radio->buffer) {
- video_device_release(radio->videodev);
- kfree(radio);
- return -ENOMEM;
- }
- radio->wr_index = 0;
- radio->rd_index = 0;
- init_waitqueue_head(&radio->read_queue);
-
- /* prepare polling via eventd */
- INIT_WORK(&radio->work, si470x_work);
- init_timer(&radio->timer);
- radio->timer.function = si470x_timer;
- radio->timer.data = (unsigned long) radio;
-
- return 0;
-}
-
-
-/*
- * si470x_usb_driver_disconnect - disconnect the device
- */
-static void si470x_usb_driver_disconnect(struct usb_interface *intf)
-{
- struct si470x_device *radio = usb_get_intfdata(intf);
-
- del_timer_sync(&radio->timer);
- flush_scheduled_work();
-
- usb_set_intfdata(intf, NULL);
- if (radio) {
- video_unregister_device(radio->videodev);
- kfree(radio->buffer);
- kfree(radio);
- }
-}
-
-
-/*
- * si470x_usb_driver - usb driver interface
- */
-static struct usb_driver si470x_usb_driver = {
- .name = DRIVER_NAME,
- .probe = si470x_usb_driver_probe,
- .disconnect = si470x_usb_driver_disconnect,
- .id_table = si470x_usb_driver_id_table,
-};
-
-
-
-/**************************************************************************
- * Module Interface
- **************************************************************************/
-
-/*
- * si470x_module_init - module init
- */
-static int __init si470x_module_init(void)
-{
- printk(KERN_INFO DRIVER_DESC "\n");
- return usb_register(&si470x_usb_driver);
-}
-
-
-/*
- * si470x_module_exit - module exit
- */
-static void __exit si470x_module_exit(void)
-{
- usb_deregister(&si470x_usb_driver);
-}
-
-
-module_init(si470x_module_init);
-module_exit(si470x_module_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION("1.0.4");
diff --git a/trunk/drivers/media/video/Kconfig b/trunk/drivers/media/video/Kconfig
index a2e8987a6195..c9f14bfc8544 100644
--- a/trunk/drivers/media/video/Kconfig
+++ b/trunk/drivers/media/video/Kconfig
@@ -45,7 +45,7 @@ comment "Audio decoders"
config VIDEO_TVAUDIO
tristate "Simple audio decoder chips"
- depends on VIDEO_V4L2 && I2C
+ depends on VIDEO_V4L1 && I2C
---help---
Support for several audio decoder chips found on some bt8xx boards:
Philips: tda9840, tda9873h, tda9874h/a, tda9850, tda985x, tea6300,
@@ -57,7 +57,7 @@ config VIDEO_TVAUDIO
config VIDEO_TDA7432
tristate "Philips TDA7432 audio processor"
- depends on VIDEO_V4L2 && I2C
+ depends on VIDEO_V4L1 && I2C
---help---
Support for tda7432 audio decoder chip found on some bt8xx boards.
@@ -75,7 +75,7 @@ config VIDEO_TDA9840
config VIDEO_TDA9875
tristate "Philips TDA9875 audio processor"
- depends on VIDEO_V4L2 && I2C
+ depends on VIDEO_V4L1 && I2C
---help---
Support for tda9875 audio decoder chip found on some bt8xx boards.
@@ -109,19 +109,9 @@ config VIDEO_MSP3400
To compile this driver as a module, choose M here: the
module will be called msp3400.
-config VIDEO_CS5345
- tristate "Cirrus Logic CS5345 audio ADC"
- depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
- ---help---
- Support for the Cirrus Logic CS5345 24-bit, 192 kHz
- stereo A/D converter.
-
- To compile this driver as a module, choose M here: the
- module will be called cs5345.
-
config VIDEO_CS53L32A
tristate "Cirrus Logic CS53L32A audio ADC"
- depends on VIDEO_V4L2 && I2C
+ depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
---help---
Support for the Cirrus Logic CS53L32A low voltage
stereo A/D converter.
@@ -129,15 +119,6 @@ config VIDEO_CS53L32A
To compile this driver as a module, choose M here: the
module will be called cs53l32a.
-config VIDEO_M52790
- tristate "Mitsubishi M52790 A/V switch"
- depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
- ---help---
- Support for the Mitsubishi M52790 A/V switch.
-
- To compile this driver as a module, choose M here: the
- module will be called m52790.
-
config VIDEO_TLV320AIC23B
tristate "Texas Instruments TLV320AIC23B audio codec"
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
@@ -149,7 +130,7 @@ config VIDEO_TLV320AIC23B
config VIDEO_WM8775
tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
- depends on VIDEO_V4L2 && I2C
+ depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
---help---
Support for the Wolfson Microelectronics WM8775 high
performance stereo A/D Converter with a 4 channel input mixer.
@@ -159,7 +140,7 @@ config VIDEO_WM8775
config VIDEO_WM8739
tristate "Wolfson Microelectronics WM8739 stereo audio ADC"
- depends on VIDEO_V4L2 && I2C
+ depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
---help---
Support for the Wolfson Microelectronics WM8739
stereo A/D Converter.
@@ -263,7 +244,7 @@ config VIDEO_SAA7114
config VIDEO_SAA711X
tristate "Philips SAA7113/4/5 video decoders"
- depends on VIDEO_V4L2 && I2C
+ depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
---help---
Support for the Philips SAA7113/4/5 video decoders.
@@ -319,7 +300,7 @@ comment "Video encoders"
config VIDEO_SAA7127
tristate "Philips SAA7127/9 digital video encoders"
- depends on VIDEO_V4L2 && I2C
+ depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
---help---
Support for the Philips SAA7127/9 digital video encoders.
@@ -357,7 +338,7 @@ comment "Video improvement chips"
config VIDEO_UPD64031A
tristate "NEC Electronics uPD64031A Ghost Reduction"
- depends on VIDEO_V4L2 && I2C
+ depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
---help---
Support for the NEC Electronics uPD64031A Ghost Reduction
video chip. It is most often found in NTSC TV cards made for
@@ -369,7 +350,7 @@ config VIDEO_UPD64031A
config VIDEO_UPD64083
tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation"
- depends on VIDEO_V4L2 && I2C
+ depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
---help---
Support for the NEC Electronics uPD64083 3-Dimensional Y/C
separation video chip. It is used to improve the quality of
@@ -821,19 +802,6 @@ config USB_ZR364XX
To compile this driver as a module, choose M here: the
module will be called zr364xx.
-config USB_STKWEBCAM
- tristate "USB Syntek DC1125 Camera support"
- depends on VIDEO_V4L2 && EXPERIMENTAL
- ---help---
- Say Y here if you want to use this type of camera.
- Supported devices are typically found in some Asus laptops,
- with USB id 174f:a311 and 05e1:0501. Other Syntek cameras
- may be supported by the stk11xx driver, from which this is
- derived, see http://stk11xx.sourceforge.net
-
- To compile this driver as a module, choose M here: the
- module will be called stkwebcam.
-
endif # V4L_USB_DRIVERS
endif # VIDEO_CAPTURE_DRIVERS
diff --git a/trunk/drivers/media/video/Makefile b/trunk/drivers/media/video/Makefile
index 28ddd146c1c5..b5a064163e03 100644
--- a/trunk/drivers/media/video/Makefile
+++ b/trunk/drivers/media/video/Makefile
@@ -4,12 +4,10 @@
zr36067-objs := zoran_procfs.o zoran_device.o \
zoran_driver.o zoran_card.o
-tuner-objs := tuner-core.o tuner-types.o
+tuner-objs := tuner-core.o tuner-types.o tda9887.o
msp3400-objs := msp3400-driver.o msp3400-kthreads.o
-stkwebcam-objs := stk-webcam.o stk-sensor.o
-
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o \
v4l2-int-device.o
@@ -68,9 +66,7 @@ obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
-obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
-obj-$(CONFIG_VIDEO_M52790) += m52790.o
obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
@@ -85,13 +81,11 @@ obj-$(CONFIG_TUNER_3036) += tuner-3036.o
obj-$(CONFIG_VIDEO_TUNER) += tuner.o
-obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o
obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o
obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o
obj-$(CONFIG_TUNER_TDA8290) += tda8290.o
obj-$(CONFIG_TUNER_TEA5767) += tea5767.o
obj-$(CONFIG_TUNER_TEA5761) += tea5761.o
-obj-$(CONFIG_TUNER_TDA9887) += tda9887.o
obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
@@ -118,7 +112,6 @@ obj-$(CONFIG_USB_SE401) += se401.o
obj-$(CONFIG_USB_STV680) += stv680.o
obj-$(CONFIG_USB_W9968CF) += w9968cf.o
obj-$(CONFIG_USB_ZR364XX) += zr364xx.o
-obj-$(CONFIG_USB_STKWEBCAM) += stkwebcam.o
obj-$(CONFIG_USB_SN9C102) += sn9c102/
obj-$(CONFIG_USB_ET61X251) += et61x251/
@@ -136,4 +129,3 @@ obj-$(CONFIG_VIDEO_VIVI) += vivi.o
obj-$(CONFIG_VIDEO_CX23885) += cx23885/
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/trunk/drivers/media/video/bt8xx/Kconfig b/trunk/drivers/media/video/bt8xx/Kconfig
index cfc822bb502a..2ca162b390a2 100644
--- a/trunk/drivers/media/video/bt8xx/Kconfig
+++ b/trunk/drivers/media/video/bt8xx/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_BT848
tristate "BT848 Video For Linux"
- depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 && INPUT
+ depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L1
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX
diff --git a/trunk/drivers/media/video/bt8xx/Makefile b/trunk/drivers/media/video/bt8xx/Makefile
index 924d216d9570..a096a03418aa 100644
--- a/trunk/drivers/media/video/bt8xx/Makefile
+++ b/trunk/drivers/media/video/bt8xx/Makefile
@@ -4,7 +4,7 @@
bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
- bttv-input.o bttv-audio-hook.o
+ bttv-input.o
obj-$(CONFIG_VIDEO_BT848) += bttv.o
diff --git a/trunk/drivers/media/video/bt8xx/bttv-audio-hook.c b/trunk/drivers/media/video/bt8xx/bttv-audio-hook.c
deleted file mode 100644
index 2364d16586b3..000000000000
--- a/trunk/drivers/media/video/bt8xx/bttv-audio-hook.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Handlers for board audio hooks, splitted from bttv-cards
- *
- * Copyright (c) 2006 Mauro Carvalho Chehab (mchehab@infradead.org)
- * This code is placed under the terms of the GNU General Public License
- */
-
-#include "bttv-audio-hook.h"
-
-#include
-
-/* ----------------------------------------------------------------------- */
-/* winview */
-
-void winview_volume(struct bttv *btv, __u16 volume)
-{
- /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */
- int bits_out, loops, vol, data;
-
- /* 32 levels logarithmic */
- vol = 32 - ((volume>>11));
- /* units */
- bits_out = (PT2254_DBS_IN_2>>(vol%5));
- /* tens */
- bits_out |= (PT2254_DBS_IN_10>>(vol/5));
- bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL;
- data = gpio_read();
- data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA|
- WINVIEW_PT2254_STROBE);
- for (loops = 17; loops >= 0 ; loops--) {
- if (bits_out & (1<audmode & V4L2_TUNER_MODE_LANG1)
- con = 0x000;
- if (t->audmode & V4L2_TUNER_MODE_LANG2)
- con = 0x300;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- con = 0x200;
-/* if (t->audmode & V4L2_TUNER_MODE_MONO)
- * con = 0x100; */
- gpio_bits(0x300, con);
- } else {
- t->audmode = V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
- }
-}
-
-void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
- unsigned int val, con;
-
- if (btv->radio_user)
- return;
-
- val = gpio_read();
- if (set) {
- con = 0x000;
- if (t->audmode & V4L2_TUNER_MODE_LANG2) {
- if (t->audmode & V4L2_TUNER_MODE_LANG1) {
- /* LANG1 + LANG2 */
- con = 0x100;
- }
- else {
- /* LANG2 */
- con = 0x300;
- }
- }
- if (con != (val & 0x300)) {
- gpio_bits(0x300, con);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"gvbctv5pci");
- }
- } else {
- switch (val & 0x70) {
- case 0x10:
- t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
- break;
- case 0x30:
- t->rxsubchans = V4L2_TUNER_SUB_LANG2;
- break;
- case 0x50:
- t->rxsubchans = V4L2_TUNER_SUB_LANG1;
- break;
- case 0x60:
- t->rxsubchans = V4L2_TUNER_SUB_STEREO;
- break;
- case 0x70:
- t->rxsubchans = V4L2_TUNER_SUB_MONO;
- break;
- default:
- t->rxsubchans = V4L2_TUNER_SUB_MONO |
- V4L2_TUNER_SUB_STEREO |
- V4L2_TUNER_SUB_LANG1 |
- V4L2_TUNER_SUB_LANG2;
- }
- t->audmode = V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
- }
-}
-
-/*
- * Mario Medina Nussbaum
- * I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo,
- * 0xdde enables mono and 0xccd enables sap
- *
- * Petr Vandrovec
- * P.S.: At least mask in line above is wrong - GPIO pins 3,2 select
- * input/output sound connection, so both must be set for output mode.
- *
- * Looks like it's needed only for the "tvphone", the "tvphone 98"
- * handles this with a tda9840
- *
- */
-
-void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
- int val = 0;
-
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
- val = 0x02;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- val = 0x01;
- if (val) {
- gpio_bits(0x03,val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"avermedia");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1;
- return;
- }
-}
-
-
-void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
- int val = 0;
-
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
- val = 0x01;
- if (t->audmode & V4L2_TUNER_MODE_STEREO) /* STEREO */
- val = 0x02;
- btaor(val, ~0x03, BT848_GPIO_DATA);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"avermedia");
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
- return;
- }
-}
-
-/* Lifetec 9415 handling */
-
-void lt9415_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
- int val = 0;
-
- if (gpio_read() & 0x4000) {
- t->audmode = V4L2_TUNER_MODE_MONO;
- return;
- }
-
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_LANG2) /* A2 SAP */
- val = 0x0080;
- if (t->audmode & V4L2_TUNER_MODE_STEREO) /* A2 stereo */
- val = 0x0880;
- if ((t->audmode & V4L2_TUNER_MODE_LANG1) ||
- (t->audmode & V4L2_TUNER_MODE_MONO))
- val = 0;
- gpio_bits(0x0880, val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"lt9415");
- } else {
- /* autodetect doesn't work with this card :-( */
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
- return;
- }
-}
-
-/* TDA9821 on TerraTV+ Bt848, Bt878 */
-void terratv_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
- unsigned int con = 0;
-
- if (set) {
- gpio_inout(0x180000,0x180000);
- if (t->audmode & V4L2_TUNER_MODE_LANG2)
- con = 0x080000;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- con = 0x180000;
- gpio_bits(0x180000, con);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"terratv");
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
- }
-}
-
-
-void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
- unsigned long val = 0;
-
- if (set) {
- /*btor (0xc32000, BT848_GPIO_OUT_EN);*/
- if (t->audmode & V4L2_TUNER_MODE_MONO) /* Mono */
- val = 0x420000;
- if (t->audmode & V4L2_TUNER_MODE_LANG1) /* Mono */
- val = 0x420000;
- if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
- val = 0x410000;
- if (t->audmode & V4L2_TUNER_MODE_STEREO) /* Stereo */
- val = 0x020000;
- if (val) {
- gpio_bits(0x430000, val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"winfast2000");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
- }
-}
-
-/*
- * Dariusz Kowalewski
- * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM
- * revision 9B has on-board TDA9874A sound decoder).
- *
- * Note: There are card variants without tda9874a. Forcing the "stereo sound route"
- * will mute this cards.
- */
-void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
- unsigned int val = 0;
-
- if (btv->radio_user)
- return;
-
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_MONO) {
- val = 0x01;
- }
- if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
- || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
- val = 0x02;
- }
- if (val) {
- gpio_bits(0x03,val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"pvbt878p9b");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
- }
-}
-
-/*
- * Dariusz Kowalewski
- * sound control for FlyVideo 2000S (with tda9874 decoder)
- * based on pvbt878p9b_audio() - this is not tested, please fix!!!
- */
-void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
- unsigned int val = 0xffff;
-
- if (btv->radio_user)
- return;
-
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_MONO) {
- val = 0x0000;
- }
- if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
- || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
- val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
- }
- if (val != 0xffff) {
- gpio_bits(0x1800, val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"fv2000s");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
- }
-}
-
-/*
- * sound control for Canopus WinDVR PCI
- * Masaki Suzuki
- */
-void windvr_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
- unsigned long val = 0;
-
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_MONO)
- val = 0x040000;
- if (t->audmode & V4L2_TUNER_MODE_LANG1)
- val = 0;
- if (t->audmode & V4L2_TUNER_MODE_LANG2)
- val = 0x100000;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- val = 0;
- if (val) {
- gpio_bits(0x140000, val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"windvr");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
- }
-}
-
-/*
- * sound control for AD-TVK503
- * Hiroshi Takekawa
- */
-void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
- unsigned int con = 0xffffff;
-
- /* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
-
- if (set) {
- /* btor(***, BT848_GPIO_OUT_EN); */
- if (t->audmode & V4L2_TUNER_MODE_LANG1)
- con = 0x00000000;
- if (t->audmode & V4L2_TUNER_MODE_LANG2)
- con = 0x00180000;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- con = 0x00000000;
- if (t->audmode & V4L2_TUNER_MODE_MONO)
- con = 0x00060000;
- if (con != 0xffffff) {
- gpio_bits(0x1e0000,con);
- if (bttv_gpio)
- bttv_gpio_tracking(btv, "adtvk503");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
- }
-}
diff --git a/trunk/drivers/media/video/bt8xx/bttv-audio-hook.h b/trunk/drivers/media/video/bt8xx/bttv-audio-hook.h
deleted file mode 100644
index 159d07adeff8..000000000000
--- a/trunk/drivers/media/video/bt8xx/bttv-audio-hook.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Handlers for board audio hooks, splitted from bttv-cards
- *
- * Copyright (c) 2006 Mauro Carvalho Chehab (mchehab@infradead.org)
- * This code is placed under the terms of the GNU General Public License
- */
-
-#include "bttvp.h"
-
-void winview_volume (struct bttv *btv, __u16 volume);
-
-void lt9415_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void terratv_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void windvr_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-
diff --git a/trunk/drivers/media/video/bt8xx/bttv-cards.c b/trunk/drivers/media/video/bt8xx/bttv-cards.c
index 63a47cd4c161..585d1ef95afd 100644
--- a/trunk/drivers/media/video/bt8xx/bttv-cards.c
+++ b/trunk/drivers/media/video/bt8xx/bttv-cards.c
@@ -39,7 +39,6 @@
#include "bttvp.h"
#include
#include
-#include "bttv-audio-hook.h"
/* fwd decl */
static void boot_msp34xx(struct bttv *btv, int pin);
@@ -51,6 +50,20 @@ static void modtec_eeprom(struct bttv *btv);
static void init_PXC200(struct bttv *btv);
static void init_RTV24(struct bttv *btv);
+static void winview_audio(struct bttv *btv, struct video_audio *v, int set);
+static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set);
+static void avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v,
+ int set);
+static void avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v,
+ int set);
+static void terratv_audio(struct bttv *btv, struct video_audio *v, int set);
+static void gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set);
+static void gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set);
+static void winfast2000_audio(struct bttv *btv, struct video_audio *v, int set);
+static void pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set);
+static void fv2000s_audio(struct bttv *btv, struct video_audio *v, int set);
+static void windvr_audio(struct bttv *btv, struct video_audio *v, int set);
+static void adtvk503_audio(struct bttv *btv, struct video_audio *v, int set);
static void rv605_muxsel(struct bttv *btv, unsigned int input);
static void eagle_muxsel(struct bttv *btv, unsigned int input);
static void xguard_muxsel(struct bttv *btv, unsigned int input);
@@ -414,7 +427,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .audio_mode_gpio= avermedia_tvphone_audio,
+ .audio_hook = avermedia_tvphone_audio,
.has_remote = 1,
},
[BTTV_BOARD_MATRIX_VISION] = {
@@ -526,7 +539,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .audio_mode_gpio= avermedia_tv_stereo_audio,
+ .audio_hook = avermedia_tv_stereo_audio,
.no_gpioirq = 1,
},
[BTTV_BOARD_VHX] = {
@@ -591,7 +604,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .volume_gpio = winview_volume,
+ .audio_hook = winview_audio,
.has_radio = 1,
},
[BTTV_BOARD_AVEC_INTERCAP] = {
@@ -715,7 +728,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .audio_mode_gpio= terratv_audio,
+ .audio_hook = terratv_audio,
},
[BTTV_BOARD_HAUPPAUG_WCAM] = {
.name = "Hauppauge WinCam newer (bt878)",
@@ -763,7 +776,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .audio_mode_gpio= terratv_audio,
+ .audio_hook = terratv_audio,
/* GPIO wiring:
External 20 pin connector (for Active Radio Upgrade board)
gpio00: i2c-sda
@@ -902,7 +915,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_PAL, /* default for now, gpio reads BFFF06 for Pal bg+dk */
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .audio_mode_gpio= winfast2000_audio,
+ .audio_hook = winfast2000_audio,
.has_remote = 1,
},
[BTTV_BOARD_CHRONOS_VS2] = {
@@ -1022,7 +1035,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.has_radio = 1,
- .audio_mode_gpio= avermedia_tvphone_audio,
+ .audio_hook = avermedia_tvphone_audio,
},
[BTTV_BOARD_PV951] = {
.name = "ProVideo PV951", /* pic16c54 */
@@ -1154,7 +1167,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_ALPS_TSHC6_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .audio_mode_gpio= gvbctv3pci_audio,
+ .audio_hook = gvbctv3pci_audio,
},
[BTTV_BOARD_PXELVWPLTVPAK] = {
.name = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP",
@@ -1459,7 +1472,7 @@ struct tvcard bttv_tvcards[] = {
/* -dk-???: set mute=0x1800 for tda9874h daughterboard */
.gpiomux = { 0x0000,0x0800,0x1000,0x1000 },
.gpiomute = 0x1800,
- .audio_mode_gpio= fv2000s_audio,
+ .audio_hook = fv2000s_audio,
.no_msp34xx = 1,
.no_tda9875 = 1,
.needs_tvaudio = 1,
@@ -1500,7 +1513,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_SHARP_2U5JF5540_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .audio_mode_gpio= gvbctv3pci_audio,
+ .audio_hook = gvbctv3pci_audio,
},
/* ---- card 0x44 ---------------------------------- */
@@ -1619,7 +1632,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .audio_mode_gpio= pvbt878p9b_audio, /* Note: not all cards have stereo */
+ .audio_hook = pvbt878p9b_audio, /* Note: not all cards have stereo */
.has_radio = 1, /* Note: not all cards have radio */
.has_remote = 1,
/* GPIO wiring:
@@ -1697,7 +1710,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .audio_mode_gpio= windvr_audio,
+ .audio_hook = windvr_audio,
},
[BTTV_BOARD_GRANDTEC_MULTI] = {
.name = "GrandTec Multi Capture Card (Bt878)",
@@ -1794,7 +1807,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_NTSC_M,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .audio_mode_gpio= gvbctv5pci_audio,
+ .audio_hook = gvbctv5pci_audio,
.has_radio = 1,
},
[BTTV_BOARD_OSPREY1x0] = {
@@ -2093,7 +2106,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .audio_mode_gpio= adtvk503_audio,
+ .audio_hook = adtvk503_audio,
},
/* ---- card 0x64 ---------------------------------- */
@@ -3160,8 +3173,8 @@ static void flyvideo_gpio(struct bttv *btv)
/* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
* LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
* Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */
- if(has_tda9820_tda9821) btv->audio_mode_gpio = lt9415_audio;
- /* todo: if(has_tda9874) btv->audio_mode_gpio = fv2000s_audio; */
+ if(has_tda9820_tda9821) btv->audio_hook = lt9415_audio;
+ /* todo: if(has_tda9874) btv->audio_hook = fv2000s_audio; */
}
static int miro_tunermap[] = { 0,6,2,3, 4,5,6,0, 3,0,4,5, 5,2,16,1,
@@ -3561,12 +3574,8 @@ void __devinit bttv_init_card2(struct bttv *btv)
}
if (btv->tda9887_conf) {
- struct v4l2_priv_tun_config tda9887_cfg;
-
- tda9887_cfg.tuner = TUNER_TDA9887;
- tda9887_cfg.priv = &btv->tda9887_conf;
-
- bttv_call_i2c_clients(btv, TUNER_SET_CONFIG, &tda9887_cfg);
+ bttv_call_i2c_clients(btv, TDA9887_SET_CONFIG,
+ &btv->tda9887_conf);
}
btv->svhs = bttv_tvcards[btv->c.type].svhs;
@@ -3581,10 +3590,8 @@ void __devinit bttv_init_card2(struct bttv *btv)
btv->has_remote=1;
if (!bttv_tvcards[btv->c.type].no_gpioirq)
btv->gpioirq=1;
- if (bttv_tvcards[btv->c.type].volume_gpio)
- btv->volume_gpio=bttv_tvcards[btv->c.type].volume_gpio;
- if (bttv_tvcards[btv->c.type].audio_mode_gpio)
- btv->audio_mode_gpio=bttv_tvcards[btv->c.type].audio_mode_gpio;
+ if (bttv_tvcards[btv->c.type].audio_hook)
+ btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook;
if (bttv_tvcards[btv->c.type].digital_mode == DIGITAL_MODE_CAMERA) {
/* detect Bt832 chip for quartzsight digital camera */
@@ -3943,7 +3950,7 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
void bttv_tda9880_setnorm(struct bttv *btv, int norm)
{
/* fix up our card entry */
- if(norm==V4L2_STD_NTSC) {
+ if(norm==VIDEO_MODE_NTSC) {
bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff;
bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x957fff;
bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff;
@@ -4312,6 +4319,387 @@ void tea5757_set_freq(struct bttv *btv, unsigned short freq)
tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */
}
+
+/* ----------------------------------------------------------------------- */
+/* winview */
+
+static void winview_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+ /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */
+ int bits_out, loops, vol, data;
+
+ if (!set) {
+ /* Fixed by Leandro Lucarella flags |= VIDEO_AUDIO_VOLUME;
+ return;
+ }
+
+ /* 32 levels logarithmic */
+ vol = 32 - ((v->volume>>11));
+ /* units */
+ bits_out = (PT2254_DBS_IN_2>>(vol%5));
+ /* tens */
+ bits_out |= (PT2254_DBS_IN_10>>(vol/5));
+ bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL;
+ data = gpio_read();
+ data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA|
+ WINVIEW_PT2254_STROBE);
+ for (loops = 17; loops >= 0 ; loops--) {
+ if (bits_out & (1<mode & VIDEO_SOUND_LANG1)
+ con = 0x000;
+ if (v->mode & VIDEO_SOUND_LANG2)
+ con = 0x300;
+ if (v->mode & VIDEO_SOUND_STEREO)
+ con = 0x200;
+/* if (v->mode & VIDEO_SOUND_MONO)
+ * con = 0x100; */
+ gpio_bits(0x300, con);
+ } else {
+ v->mode = VIDEO_SOUND_STEREO |
+ VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ }
+}
+
+static void
+gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+ unsigned int val, con;
+
+ if (btv->radio_user)
+ return;
+
+ val = gpio_read();
+ if (set) {
+ con = 0x000;
+ if (v->mode & VIDEO_SOUND_LANG2) {
+ if (v->mode & VIDEO_SOUND_LANG1) {
+ /* LANG1 + LANG2 */
+ con = 0x100;
+ }
+ else {
+ /* LANG2 */
+ con = 0x300;
+ }
+ }
+ if (con != (val & 0x300)) {
+ gpio_bits(0x300, con);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv,"gvbctv5pci");
+ }
+ } else {
+ switch (val & 0x70) {
+ case 0x10:
+ v->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ break;
+ case 0x30:
+ v->mode = VIDEO_SOUND_LANG2;
+ break;
+ case 0x50:
+ v->mode = VIDEO_SOUND_LANG1;
+ break;
+ case 0x60:
+ v->mode = VIDEO_SOUND_STEREO;
+ break;
+ case 0x70:
+ v->mode = VIDEO_SOUND_MONO;
+ break;
+ default:
+ v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+ VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ }
+ }
+}
+
+/*
+ * Mario Medina Nussbaum
+ * I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo,
+ * 0xdde enables mono and 0xccd enables sap
+ *
+ * Petr Vandrovec
+ * P.S.: At least mask in line above is wrong - GPIO pins 3,2 select
+ * input/output sound connection, so both must be set for output mode.
+ *
+ * Looks like it's needed only for the "tvphone", the "tvphone 98"
+ * handles this with a tda9840
+ *
+ */
+static void
+avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+ int val = 0;
+
+ if (set) {
+ if (v->mode & VIDEO_SOUND_LANG2) /* SAP */
+ val = 0x02;
+ if (v->mode & VIDEO_SOUND_STEREO)
+ val = 0x01;
+ if (val) {
+ gpio_bits(0x03,val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv,"avermedia");
+ }
+ } else {
+ v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+ VIDEO_SOUND_LANG1;
+ return;
+ }
+}
+
+static void
+avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+ int val = 0;
+
+ if (set) {
+ if (v->mode & VIDEO_SOUND_LANG2) /* SAP */
+ val = 0x01;
+ if (v->mode & VIDEO_SOUND_STEREO) /* STEREO */
+ val = 0x02;
+ btaor(val, ~0x03, BT848_GPIO_DATA);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv,"avermedia");
+ } else {
+ v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+ VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ return;
+ }
+}
+
+/* Lifetec 9415 handling */
+static void
+lt9415_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+ int val = 0;
+
+ if (gpio_read() & 0x4000) {
+ v->mode = VIDEO_SOUND_MONO;
+ return;
+ }
+
+ if (set) {
+ if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */
+ val = 0x0080;
+ if (v->mode & VIDEO_SOUND_STEREO) /* A2 stereo */
+ val = 0x0880;
+ if ((v->mode & VIDEO_SOUND_LANG1) ||
+ (v->mode & VIDEO_SOUND_MONO))
+ val = 0;
+ gpio_bits(0x0880, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv,"lt9415");
+ } else {
+ /* autodetect doesn't work with this card :-( */
+ v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+ VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ return;
+ }
+}
+
+/* TDA9821 on TerraTV+ Bt848, Bt878 */
+static void
+terratv_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+ unsigned int con = 0;
+
+ if (set) {
+ gpio_inout(0x180000,0x180000);
+ if (v->mode & VIDEO_SOUND_LANG2)
+ con = 0x080000;
+ if (v->mode & VIDEO_SOUND_STEREO)
+ con = 0x180000;
+ gpio_bits(0x180000, con);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv,"terratv");
+ } else {
+ v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+ VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ }
+}
+
+static void
+winfast2000_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+ unsigned long val = 0;
+
+ if (set) {
+ /*btor (0xc32000, BT848_GPIO_OUT_EN);*/
+ if (v->mode & VIDEO_SOUND_MONO) /* Mono */
+ val = 0x420000;
+ if (v->mode & VIDEO_SOUND_LANG1) /* Mono */
+ val = 0x420000;
+ if (v->mode & VIDEO_SOUND_LANG2) /* SAP */
+ val = 0x410000;
+ if (v->mode & VIDEO_SOUND_STEREO) /* Stereo */
+ val = 0x020000;
+ if (val) {
+ gpio_bits(0x430000, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv,"winfast2000");
+ }
+ } else {
+ v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+ VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ }
+}
+
+/*
+ * Dariusz Kowalewski
+ * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM
+ * revision 9B has on-board TDA9874A sound decoder).
+ *
+ * Note: There are card variants without tda9874a. Forcing the "stereo sound route"
+ * will mute this cards.
+ */
+static void
+pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+ unsigned int val = 0;
+
+ if (btv->radio_user)
+ return;
+
+ if (set) {
+ if (v->mode & VIDEO_SOUND_MONO) {
+ val = 0x01;
+ }
+ if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2))
+ || (v->mode & VIDEO_SOUND_STEREO)) {
+ val = 0x02;
+ }
+ if (val) {
+ gpio_bits(0x03,val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv,"pvbt878p9b");
+ }
+ } else {
+ v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+ VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ }
+}
+
+/*
+ * Dariusz Kowalewski
+ * sound control for FlyVideo 2000S (with tda9874 decoder)
+ * based on pvbt878p9b_audio() - this is not tested, please fix!!!
+ */
+static void
+fv2000s_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+ unsigned int val = 0xffff;
+
+ if (btv->radio_user)
+ return;
+ if (set) {
+ if (v->mode & VIDEO_SOUND_MONO) {
+ val = 0x0000;
+ }
+ if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2))
+ || (v->mode & VIDEO_SOUND_STEREO)) {
+ val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
+ }
+ if (val != 0xffff) {
+ gpio_bits(0x1800, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv,"fv2000s");
+ }
+ } else {
+ v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+ VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ }
+}
+
+/*
+ * sound control for Canopus WinDVR PCI
+ * Masaki Suzuki
+ */
+static void
+windvr_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+ unsigned long val = 0;
+
+ if (set) {
+ if (v->mode & VIDEO_SOUND_MONO)
+ val = 0x040000;
+ if (v->mode & VIDEO_SOUND_LANG1)
+ val = 0;
+ if (v->mode & VIDEO_SOUND_LANG2)
+ val = 0x100000;
+ if (v->mode & VIDEO_SOUND_STEREO)
+ val = 0;
+ if (val) {
+ gpio_bits(0x140000, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv,"windvr");
+ }
+ } else {
+ v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+ VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ }
+}
+
+/*
+ * sound control for AD-TVK503
+ * Hiroshi Takekawa
+ */
+static void
+adtvk503_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+ unsigned int con = 0xffffff;
+
+ /* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
+
+ if (set) {
+ /* btor(***, BT848_GPIO_OUT_EN); */
+ if (v->mode & VIDEO_SOUND_LANG1)
+ con = 0x00000000;
+ if (v->mode & VIDEO_SOUND_LANG2)
+ con = 0x00180000;
+ if (v->mode & VIDEO_SOUND_STEREO)
+ con = 0x00000000;
+ if (v->mode & VIDEO_SOUND_MONO)
+ con = 0x00060000;
+ if (con != 0xffffff) {
+ gpio_bits(0x1e0000,con);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "adtvk503");
+ }
+ } else {
+ v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+ VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ }
+}
+
/* RemoteVision MX (rv605) muxsel helper [Miguel Freitas]
*
* This is needed because rv605 don't use a normal multiplex, but a crosspoint
diff --git a/trunk/drivers/media/video/bt8xx/bttv-driver.c b/trunk/drivers/media/video/bt8xx/bttv-driver.c
index 907dc62c1783..581a3c955739 100644
--- a/trunk/drivers/media/video/bt8xx/bttv-driver.c
+++ b/trunk/drivers/media/video/bt8xx/bttv-driver.c
@@ -9,12 +9,6 @@
some v4l2 code lines are taken from Justin's bttv2 driver which is
(c) 2000 Justin Schoeman
- V4L1 removal from:
- (c) 2005-2006 Nickolay V. Shmyrev
-
- Fixes to be fully V4L2 compliant by
- (c) 2006 Mauro Carvalho Chehab
-
Cropping and overscan support
Copyright (C) 2005, 2006 Michael H. Schimek
Sponsored by OPQ Systems AB
@@ -163,7 +157,7 @@ MODULE_LICENSE("GPL");
static ssize_t show_card(struct device *cd,
struct device_attribute *attr, char *buf)
{
- struct video_device *vfd = container_of(cd, struct video_device, class_dev);
+ struct video_device *vfd = to_video_device(cd);
struct bttv *btv = dev_get_drvdata(vfd->dev);
return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
}
@@ -476,27 +470,31 @@ static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
/* ----------------------------------------------------------------------- */
/* bttv format list
packed pixel formats must come first */
-static const struct bttv_format formats[] = {
+static const struct bttv_format bttv_formats[] = {
{
.name = "8 bpp, gray",
+ .palette = VIDEO_PALETTE_GREY,
.fourcc = V4L2_PIX_FMT_GREY,
.btformat = BT848_COLOR_FMT_Y8,
.depth = 8,
.flags = FORMAT_FLAGS_PACKED,
},{
.name = "8 bpp, dithered color",
+ .palette = VIDEO_PALETTE_HI240,
.fourcc = V4L2_PIX_FMT_HI240,
.btformat = BT848_COLOR_FMT_RGB8,
.depth = 8,
.flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
},{
.name = "15 bpp RGB, le",
+ .palette = VIDEO_PALETTE_RGB555,
.fourcc = V4L2_PIX_FMT_RGB555,
.btformat = BT848_COLOR_FMT_RGB15,
.depth = 16,
.flags = FORMAT_FLAGS_PACKED,
},{
.name = "15 bpp RGB, be",
+ .palette = -1,
.fourcc = V4L2_PIX_FMT_RGB555X,
.btformat = BT848_COLOR_FMT_RGB15,
.btswap = 0x03, /* byteswap */
@@ -504,12 +502,14 @@ static const struct bttv_format formats[] = {
.flags = FORMAT_FLAGS_PACKED,
},{
.name = "16 bpp RGB, le",
+ .palette = VIDEO_PALETTE_RGB565,
.fourcc = V4L2_PIX_FMT_RGB565,
.btformat = BT848_COLOR_FMT_RGB16,
.depth = 16,
.flags = FORMAT_FLAGS_PACKED,
},{
.name = "16 bpp RGB, be",
+ .palette = -1,
.fourcc = V4L2_PIX_FMT_RGB565X,
.btformat = BT848_COLOR_FMT_RGB16,
.btswap = 0x03, /* byteswap */
@@ -517,18 +517,21 @@ static const struct bttv_format formats[] = {
.flags = FORMAT_FLAGS_PACKED,
},{
.name = "24 bpp RGB, le",
+ .palette = VIDEO_PALETTE_RGB24,
.fourcc = V4L2_PIX_FMT_BGR24,
.btformat = BT848_COLOR_FMT_RGB24,
.depth = 24,
.flags = FORMAT_FLAGS_PACKED,
},{
.name = "32 bpp RGB, le",
+ .palette = VIDEO_PALETTE_RGB32,
.fourcc = V4L2_PIX_FMT_BGR32,
.btformat = BT848_COLOR_FMT_RGB32,
.depth = 32,
.flags = FORMAT_FLAGS_PACKED,
},{
.name = "32 bpp RGB, be",
+ .palette = -1,
.fourcc = V4L2_PIX_FMT_RGB32,
.btformat = BT848_COLOR_FMT_RGB32,
.btswap = 0x0f, /* byte+word swap */
@@ -536,18 +539,21 @@ static const struct bttv_format formats[] = {
.flags = FORMAT_FLAGS_PACKED,
},{
.name = "4:2:2, packed, YUYV",
+ .palette = VIDEO_PALETTE_YUV422,
.fourcc = V4L2_PIX_FMT_YUYV,
.btformat = BT848_COLOR_FMT_YUY2,
.depth = 16,
.flags = FORMAT_FLAGS_PACKED,
},{
.name = "4:2:2, packed, YUYV",
+ .palette = VIDEO_PALETTE_YUYV,
.fourcc = V4L2_PIX_FMT_YUYV,
.btformat = BT848_COLOR_FMT_YUY2,
.depth = 16,
.flags = FORMAT_FLAGS_PACKED,
},{
.name = "4:2:2, packed, UYVY",
+ .palette = VIDEO_PALETTE_UYVY,
.fourcc = V4L2_PIX_FMT_UYVY,
.btformat = BT848_COLOR_FMT_YUY2,
.btswap = 0x03, /* byteswap */
@@ -555,6 +561,7 @@ static const struct bttv_format formats[] = {
.flags = FORMAT_FLAGS_PACKED,
},{
.name = "4:2:2, planar, Y-Cb-Cr",
+ .palette = VIDEO_PALETTE_YUV422P,
.fourcc = V4L2_PIX_FMT_YUV422P,
.btformat = BT848_COLOR_FMT_YCrCb422,
.depth = 16,
@@ -563,6 +570,7 @@ static const struct bttv_format formats[] = {
.vshift = 0,
},{
.name = "4:2:0, planar, Y-Cb-Cr",
+ .palette = VIDEO_PALETTE_YUV420P,
.fourcc = V4L2_PIX_FMT_YUV420,
.btformat = BT848_COLOR_FMT_YCrCb422,
.depth = 12,
@@ -571,6 +579,7 @@ static const struct bttv_format formats[] = {
.vshift = 1,
},{
.name = "4:2:0, planar, Y-Cr-Cb",
+ .palette = -1,
.fourcc = V4L2_PIX_FMT_YVU420,
.btformat = BT848_COLOR_FMT_YCrCb422,
.depth = 12,
@@ -579,6 +588,7 @@ static const struct bttv_format formats[] = {
.vshift = 1,
},{
.name = "4:1:1, planar, Y-Cb-Cr",
+ .palette = VIDEO_PALETTE_YUV411P,
.fourcc = V4L2_PIX_FMT_YUV411P,
.btformat = BT848_COLOR_FMT_YCrCb411,
.depth = 12,
@@ -587,6 +597,7 @@ static const struct bttv_format formats[] = {
.vshift = 0,
},{
.name = "4:1:0, planar, Y-Cb-Cr",
+ .palette = VIDEO_PALETTE_YUV410P,
.fourcc = V4L2_PIX_FMT_YUV410,
.btformat = BT848_COLOR_FMT_YCrCb411,
.depth = 9,
@@ -595,6 +606,7 @@ static const struct bttv_format formats[] = {
.vshift = 2,
},{
.name = "4:1:0, planar, Y-Cr-Cb",
+ .palette = -1,
.fourcc = V4L2_PIX_FMT_YVU410,
.btformat = BT848_COLOR_FMT_YCrCb411,
.depth = 9,
@@ -603,13 +615,14 @@ static const struct bttv_format formats[] = {
.vshift = 2,
},{
.name = "raw scanlines",
+ .palette = VIDEO_PALETTE_RAW,
.fourcc = -1,
.btformat = BT848_COLOR_FMT_RAW,
.depth = 8,
.flags = FORMAT_FLAGS_RAW,
}
};
-static const unsigned int FORMATS = ARRAY_SIZE(formats);
+static const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats);
/* ----------------------------------------------------------------------- */
@@ -785,17 +798,7 @@ static const struct v4l2_queryctrl bttv_ctls[] = {
};
-
-static const struct v4l2_queryctrl *ctrl_by_id(int id)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++)
- if (bttv_ctls[i].id == id)
- return bttv_ctls+i;
-
- return NULL;
-}
+static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls);
/* ----------------------------------------------------------------------- */
/* resource management */
@@ -1251,6 +1254,16 @@ audio_input(struct bttv *btv, int input)
return audio_mux(btv, input, btv->mute);
}
+static void
+i2c_vidiocschan(struct bttv *btv)
+{
+ v4l2_std_id std = bttv_tvnorms[btv->tvnorm].v4l2_id;
+
+ bttv_call_i2c_clients(btv, VIDIOC_S_STD, &std);
+ if (btv->c.type == BTTV_BOARD_VOODOOTV_FM || btv->c.type == BTTV_BOARD_VOODOOTV_200)
+ bttv_tda9880_setnorm(btv,btv->tvnorm);
+}
+
static void
bttv_crop_calc_limits(struct bttv_crop *c)
{
@@ -1285,7 +1298,6 @@ static int
set_tvnorm(struct bttv *btv, unsigned int norm)
{
const struct bttv_tvnorm *tvnorm;
- v4l2_std_id id;
if (norm < 0 || norm >= BTTV_TVNORMS)
return -EINVAL;
@@ -1322,9 +1334,6 @@ set_tvnorm(struct bttv *btv, unsigned int norm)
bttv_tda9880_setnorm(btv,norm);
break;
}
- id = tvnorm->v4l2_id;
- bttv_call_i2c_clients(btv, VIDIOC_S_STD, &id);
-
return 0;
}
@@ -1350,6 +1359,7 @@ set_input(struct bttv *btv, unsigned int input, unsigned int norm)
audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ?
TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN));
set_tvnorm(btv, norm);
+ i2c_vidiocschan(btv);
}
static void init_irqreg(struct bttv *btv)
@@ -1442,12 +1452,38 @@ static void bttv_reinit_bt848(struct bttv *btv)
set_input(btv, btv->input, btv->tvnorm);
}
-static int bttv_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *c)
+static int get_control(struct bttv *btv, struct v4l2_control *c)
{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
+ struct video_audio va;
+ int i;
+ for (i = 0; i < BTTV_CTLS; i++)
+ if (bttv_ctls[i].id == c->id)
+ break;
+ if (i == BTTV_CTLS)
+ return -EINVAL;
+ if (btv->audio_hook && i >= 4 && i <= 8) {
+ memset(&va,0,sizeof(va));
+ btv->audio_hook(btv,&va,0);
+ switch (c->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0;
+ break;
+ case V4L2_CID_AUDIO_VOLUME:
+ c->value = va.volume;
+ break;
+ case V4L2_CID_AUDIO_BALANCE:
+ c->value = va.balance;
+ break;
+ case V4L2_CID_AUDIO_BASS:
+ c->value = va.bass;
+ break;
+ case V4L2_CID_AUDIO_TREBLE:
+ c->value = va.treble;
+ break;
+ }
+ return 0;
+ }
switch (c->id) {
case V4L2_CID_BRIGHTNESS:
c->value = btv->bright;
@@ -1467,7 +1503,7 @@ static int bttv_g_ctrl(struct file *file, void *priv,
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
- bttv_call_i2c_clients(btv, VIDIOC_G_CTRL, c);
+ bttv_call_i2c_clients(btv,VIDIOC_G_CTRL,c);
break;
case V4L2_CID_PRIVATE_CHROMA_AGC:
@@ -1509,44 +1545,67 @@ static int bttv_g_ctrl(struct file *file, void *priv,
return 0;
}
-static int bttv_s_ctrl(struct file *file, void *f,
- struct v4l2_control *c)
+static int set_control(struct bttv *btv, struct v4l2_control *c)
{
- int err;
- int val;
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
+ struct video_audio va;
+ int i,val;
- err = v4l2_prio_check(&btv->prio, &fh->prio);
- if (0 != err)
- return err;
+ for (i = 0; i < BTTV_CTLS; i++)
+ if (bttv_ctls[i].id == c->id)
+ break;
+ if (i == BTTV_CTLS)
+ return -EINVAL;
+ if (btv->audio_hook && i >= 4 && i <= 8) {
+ memset(&va,0,sizeof(va));
+ btv->audio_hook(btv,&va,0);
+ switch (c->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ if (c->value) {
+ va.flags |= VIDEO_AUDIO_MUTE;
+ audio_mute(btv, 1);
+ } else {
+ va.flags &= ~VIDEO_AUDIO_MUTE;
+ audio_mute(btv, 0);
+ }
+ break;
+ case V4L2_CID_AUDIO_VOLUME:
+ va.volume = c->value;
+ break;
+ case V4L2_CID_AUDIO_BALANCE:
+ va.balance = c->value;
+ break;
+ case V4L2_CID_AUDIO_BASS:
+ va.bass = c->value;
+ break;
+ case V4L2_CID_AUDIO_TREBLE:
+ va.treble = c->value;
+ break;
+ }
+ btv->audio_hook(btv,&va,1);
+ return 0;
+ }
switch (c->id) {
case V4L2_CID_BRIGHTNESS:
- bt848_bright(btv, c->value);
+ bt848_bright(btv,c->value);
break;
case V4L2_CID_HUE:
- bt848_hue(btv, c->value);
+ bt848_hue(btv,c->value);
break;
case V4L2_CID_CONTRAST:
- bt848_contrast(btv, c->value);
+ bt848_contrast(btv,c->value);
break;
case V4L2_CID_SATURATION:
- bt848_sat(btv, c->value);
+ bt848_sat(btv,c->value);
break;
case V4L2_CID_AUDIO_MUTE:
audio_mute(btv, c->value);
/* fall through */
case V4L2_CID_AUDIO_VOLUME:
- if (btv->volume_gpio)
- btv->volume_gpio(btv, c->value);
-
- bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c);
- break;
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
- bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c);
+ bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c);
break;
case V4L2_CID_PRIVATE_CHROMA_AGC:
@@ -1573,9 +1632,8 @@ static int bttv_s_ctrl(struct file *file, void *f,
break;
case V4L2_CID_PRIVATE_AGC_CRUSH:
btv->opt_adc_crush = c->value;
- btwrite(BT848_ADC_RESERVED |
- (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
- BT848_ADC);
+ btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
+ BT848_ADC);
break;
case V4L2_CID_PRIVATE_VCR_HACK:
btv->opt_vcr_hack = c->value;
@@ -1634,16 +1692,30 @@ static void bttv_field_count(struct bttv *btv)
}
}
+static const struct bttv_format*
+format_by_palette(int palette)
+{
+ unsigned int i;
+
+ for (i = 0; i < BTTV_FORMATS; i++) {
+ if (-1 == bttv_formats[i].palette)
+ continue;
+ if (bttv_formats[i].palette == palette)
+ return bttv_formats+i;
+ }
+ return NULL;
+}
+
static const struct bttv_format*
format_by_fourcc(int fourcc)
{
unsigned int i;
- for (i = 0; i < FORMATS; i++) {
- if (-1 == formats[i].fourcc)
+ for (i = 0; i < BTTV_FORMATS; i++) {
+ if (-1 == bttv_formats[i].fourcc)
continue;
- if (formats[i].fourcc == fourcc)
- return formats+i;
+ if (bttv_formats[i].fourcc == fourcc)
+ return bttv_formats+i;
}
return NULL;
}
@@ -1661,7 +1733,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
dprintk("switch_overlay: enter [new=%p]\n",new);
if (new)
- new->vb.state = VIDEOBUF_DONE;
+ new->vb.state = STATE_DONE;
spin_lock_irqsave(&btv->s_lock,flags);
old = btv->screen;
btv->screen = new;
@@ -1772,7 +1844,7 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
}
/* alloc risc memory */
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ if (STATE_NEEDS_INIT == buf->vb.state) {
redo_dma_risc = 1;
if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
goto fail;
@@ -1782,7 +1854,7 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
if (0 != (rc = bttv_buffer_risc(btv,buf)))
goto fail;
- buf->vb.state = VIDEOBUF_PREPARED;
+ buf->vb.state = STATE_PREPARED;
return 0;
fail:
@@ -1821,7 +1893,7 @@ buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct bttv_fh *fh = q->priv_data;
struct bttv *btv = fh->btv;
- buf->vb.state = VIDEOBUF_QUEUED;
+ buf->vb.state = STATE_QUEUED;
list_add_tail(&buf->vb.queue,&btv->capture);
if (!btv->curr.frame_irq) {
btv->loop_irq |= 1;
@@ -1844,255 +1916,395 @@ static struct videobuf_queue_ops bttv_video_qops = {
.buf_release = buffer_release,
};
-static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
+static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
- unsigned int i;
- int err;
-
- err = v4l2_prio_check(&btv->prio, &fh->prio);
- if (0 != err)
- return err;
+ switch (cmd) {
+ case BTTV_VERSION:
+ return BTTV_VERSION_CODE;
- for (i = 0; i < BTTV_TVNORMS; i++)
- if (*id & bttv_tvnorms[i].v4l2_id)
- break;
- if (i == BTTV_TVNORMS)
- return -EINVAL;
+ /* *** v4l1 *** ************************************************ */
+ case VIDIOCGFREQ:
+ {
+ unsigned long *freq = arg;
+ *freq = btv->freq;
+ return 0;
+ }
+ case VIDIOCSFREQ:
+ {
+ struct v4l2_frequency freq;
- mutex_lock(&btv->lock);
- set_tvnorm(btv, i);
- mutex_unlock(&btv->lock);
+ memset(&freq, 0, sizeof(freq));
+ freq.frequency = *(unsigned long *)arg;
+ mutex_lock(&btv->lock);
+ freq.type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+ btv->freq = *(unsigned long *)arg;
+ bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,&freq);
+ if (btv->has_matchbox && btv->radio_user)
+ tea5757_set_freq(btv,*(unsigned long *)arg);
+ mutex_unlock(&btv->lock);
+ return 0;
+ }
- return 0;
-}
+ case VIDIOCGTUNER:
+ {
+ struct video_tuner *v = arg;
-static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
-{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
+ if (UNSET == bttv_tvcards[btv->c.type].tuner)
+ return -EINVAL;
+ if (v->tuner) /* Only tuner 0 */
+ return -EINVAL;
+ strcpy(v->name, "Television");
+ v->rangelow = 0;
+ v->rangehigh = 0x7FFFFFFF;
+ v->flags = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
+ v->mode = btv->tvnorm;
+ v->signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0;
+ bttv_call_i2c_clients(btv,cmd,v);
+ return 0;
+ }
+ case VIDIOCSTUNER:
+ {
+ struct video_tuner *v = arg;
- if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
- *id = V4L2_STD_625_50;
- else
- *id = V4L2_STD_525_60;
- return 0;
-}
+ if (v->tuner) /* Only tuner 0 */
+ return -EINVAL;
+ if (v->mode >= BTTV_TVNORMS)
+ return -EINVAL;
-static int bttv_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
- unsigned int n;
+ mutex_lock(&btv->lock);
+ set_tvnorm(btv,v->mode);
+ bttv_call_i2c_clients(btv,cmd,v);
+ mutex_unlock(&btv->lock);
+ return 0;
+ }
- n = i->index;
+ case VIDIOCGCHAN:
+ {
+ struct video_channel *v = arg;
+ unsigned int channel = v->channel;
- if (n >= bttv_tvcards[btv->c.type].video_inputs)
- return -EINVAL;
+ if (channel >= bttv_tvcards[btv->c.type].video_inputs)
+ return -EINVAL;
+ v->tuners=0;
+ v->flags = VIDEO_VC_AUDIO;
+ v->type = VIDEO_TYPE_CAMERA;
+ v->norm = btv->tvnorm;
+ if (channel == bttv_tvcards[btv->c.type].tuner) {
+ strcpy(v->name,"Television");
+ v->flags|=VIDEO_VC_TUNER;
+ v->type=VIDEO_TYPE_TV;
+ v->tuners=1;
+ } else if (channel == btv->svhs) {
+ strcpy(v->name,"S-Video");
+ } else {
+ sprintf(v->name,"Composite%d",channel);
+ }
+ return 0;
+ }
+ case VIDIOCSCHAN:
+ {
+ struct video_channel *v = arg;
+ unsigned int channel = v->channel;
- memset(i, 0, sizeof(*i));
+ if (channel >= bttv_tvcards[btv->c.type].video_inputs)
+ return -EINVAL;
+ if (v->norm >= BTTV_TVNORMS)
+ return -EINVAL;
- i->index = n;
- i->type = V4L2_INPUT_TYPE_CAMERA;
- i->audioset = 1;
+ mutex_lock(&btv->lock);
+ if (channel == btv->input &&
+ v->norm == btv->tvnorm) {
+ /* nothing to do */
+ mutex_unlock(&btv->lock);
+ return 0;
+ }
- if (i->index == bttv_tvcards[btv->c.type].tuner) {
- sprintf(i->name, "Television");
- i->type = V4L2_INPUT_TYPE_TUNER;
- i->tuner = 0;
- } else if (i->index == btv->svhs) {
- sprintf(i->name, "S-Video");
- } else {
- sprintf(i->name, "Composite%d", i->index);
+ set_input(btv, v->channel, v->norm);
+ mutex_unlock(&btv->lock);
+ return 0;
}
- if (i->index == btv->input) {
- __u32 dstatus = btread(BT848_DSTATUS);
- if (0 == (dstatus & BT848_DSTATUS_PRES))
- i->status |= V4L2_IN_ST_NO_SIGNAL;
- if (0 == (dstatus & BT848_DSTATUS_HLOC))
- i->status |= V4L2_IN_ST_NO_H_LOCK;
- }
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio *v = arg;
- for (n = 0; n < BTTV_TVNORMS; n++)
- i->std |= bttv_tvnorms[n].v4l2_id;
+ memset(v,0,sizeof(*v));
+ strcpy(v->name,"Television");
+ v->flags |= VIDEO_AUDIO_MUTABLE;
+ v->mode = VIDEO_SOUND_MONO;
- return 0;
-}
+ mutex_lock(&btv->lock);
+ bttv_call_i2c_clients(btv,cmd,v);
-static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
+ /* card specific hooks */
+ if (btv->audio_hook)
+ btv->audio_hook(btv,v,0);
- *i = btv->input;
- return 0;
-}
+ mutex_unlock(&btv->lock);
+ return 0;
+ }
+ case VIDIOCSAUDIO:
+ {
+ struct video_audio *v = arg;
+ unsigned int audio = v->audio;
-static int bttv_s_input(struct file *file, void *priv, unsigned int i)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
+ if (audio >= bttv_tvcards[btv->c.type].audio_inputs)
+ return -EINVAL;
- int err;
+ mutex_lock(&btv->lock);
+ audio_mute(btv, (v->flags&VIDEO_AUDIO_MUTE) ? 1 : 0);
+ bttv_call_i2c_clients(btv,cmd,v);
- err = v4l2_prio_check(&btv->prio, &fh->prio);
- if (0 != err)
- return err;
+ /* card specific hooks */
+ if (btv->audio_hook)
+ btv->audio_hook(btv,v,1);
- if (i > bttv_tvcards[btv->c.type].video_inputs)
- return -EINVAL;
+ mutex_unlock(&btv->lock);
+ return 0;
+ }
- mutex_lock(&btv->lock);
- set_input(btv, i, btv->tvnorm);
- mutex_unlock(&btv->lock);
- return 0;
-}
+ /* *** v4l2 *** ************************************************ */
+ case VIDIOC_ENUMSTD:
+ {
+ struct v4l2_standard *e = arg;
+ unsigned int index = e->index;
-static int bttv_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
- int err;
+ if (index >= BTTV_TVNORMS)
+ return -EINVAL;
+ v4l2_video_std_construct(e, bttv_tvnorms[e->index].v4l2_id,
+ bttv_tvnorms[e->index].name);
+ e->index = index;
+ return 0;
+ }
+ case VIDIOC_G_STD:
+ {
+ v4l2_std_id *id = arg;
+ *id = bttv_tvnorms[btv->tvnorm].v4l2_id;
+ return 0;
+ }
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *id = arg;
+ unsigned int i;
- err = v4l2_prio_check(&btv->prio, &fh->prio);
- if (0 != err)
- return err;
+ for (i = 0; i < BTTV_TVNORMS; i++)
+ if (*id & bttv_tvnorms[i].v4l2_id)
+ break;
+ if (i == BTTV_TVNORMS)
+ return -EINVAL;
- if (UNSET == bttv_tvcards[btv->c.type].tuner)
- return -EINVAL;
+ mutex_lock(&btv->lock);
+ set_tvnorm(btv,i);
+ i2c_vidiocschan(btv);
+ mutex_unlock(&btv->lock);
+ return 0;
+ }
+ case VIDIOC_QUERYSTD:
+ {
+ v4l2_std_id *id = arg;
- if (0 != t->index)
- return -EINVAL;
+ if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
+ *id = V4L2_STD_625_50;
+ else
+ *id = V4L2_STD_525_60;
+ return 0;
+ }
- mutex_lock(&btv->lock);
- bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t);
+ case VIDIOC_ENUMINPUT:
+ {
+ struct v4l2_input *i = arg;
+ unsigned int n;
- if (btv->audio_mode_gpio)
- btv->audio_mode_gpio(btv, t, 1);
+ n = i->index;
+ if (n >= bttv_tvcards[btv->c.type].video_inputs)
+ return -EINVAL;
+ memset(i,0,sizeof(*i));
+ i->index = n;
+ i->type = V4L2_INPUT_TYPE_CAMERA;
+ i->audioset = 1;
+ if (i->index == bttv_tvcards[btv->c.type].tuner) {
+ sprintf(i->name, "Television");
+ i->type = V4L2_INPUT_TYPE_TUNER;
+ i->tuner = 0;
+ } else if (i->index == btv->svhs) {
+ sprintf(i->name, "S-Video");
+ } else {
+ sprintf(i->name,"Composite%d",i->index);
+ }
+ if (i->index == btv->input) {
+ __u32 dstatus = btread(BT848_DSTATUS);
+ if (0 == (dstatus & BT848_DSTATUS_PRES))
+ i->status |= V4L2_IN_ST_NO_SIGNAL;
+ if (0 == (dstatus & BT848_DSTATUS_HLOC))
+ i->status |= V4L2_IN_ST_NO_H_LOCK;
+ }
+ for (n = 0; n < BTTV_TVNORMS; n++)
+ i->std |= bttv_tvnorms[n].v4l2_id;
+ return 0;
+ }
+ case VIDIOC_G_INPUT:
+ {
+ int *i = arg;
+ *i = btv->input;
+ return 0;
+ }
+ case VIDIOC_S_INPUT:
+ {
+ unsigned int *i = arg;
- mutex_unlock(&btv->lock);
+ if (*i > bttv_tvcards[btv->c.type].video_inputs)
+ return -EINVAL;
+ mutex_lock(&btv->lock);
+ set_input(btv, *i, btv->tvnorm);
+ mutex_unlock(&btv->lock);
+ return 0;
+ }
- return 0;
-}
+ case VIDIOC_G_TUNER:
+ {
+ struct v4l2_tuner *t = arg;
-static int bttv_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
- int err;
+ if (UNSET == bttv_tvcards[btv->c.type].tuner)
+ return -EINVAL;
+ if (0 != t->index)
+ return -EINVAL;
+ mutex_lock(&btv->lock);
+ memset(t,0,sizeof(*t));
+ t->rxsubchans = V4L2_TUNER_SUB_MONO;
+ bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
+ strcpy(t->name, "Television");
+ t->capability = V4L2_TUNER_CAP_NORM;
+ t->type = V4L2_TUNER_ANALOG_TV;
+ if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
+ t->signal = 0xffff;
+
+ if (btv->audio_hook) {
+ /* Hmmm ... */
+ struct video_audio va;
+ memset(&va, 0, sizeof(struct video_audio));
+ btv->audio_hook(btv,&va,0);
+ t->audmode = V4L2_TUNER_MODE_MONO;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO;
+ if(va.mode & VIDEO_SOUND_STEREO) {
+ t->audmode = V4L2_TUNER_MODE_STEREO;
+ t->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ }
+ if(va.mode & VIDEO_SOUND_LANG2) {
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_LANG1
+ | V4L2_TUNER_SUB_LANG2;
+ }
+ }
+ /* FIXME: fill capability+audmode */
+ mutex_unlock(&btv->lock);
+ return 0;
+ }
+ case VIDIOC_S_TUNER:
+ {
+ struct v4l2_tuner *t = arg;
- err = v4l2_prio_check(&btv->prio, &fh->prio);
- if (0 != err)
- return err;
+ if (UNSET == bttv_tvcards[btv->c.type].tuner)
+ return -EINVAL;
+ if (0 != t->index)
+ return -EINVAL;
+ mutex_lock(&btv->lock);
+ bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t);
+ if (btv->audio_hook) {
+ struct video_audio va;
+ memset(&va, 0, sizeof(struct video_audio));
+ if (t->audmode == V4L2_TUNER_MODE_MONO)
+ va.mode = VIDEO_SOUND_MONO;
+ else if (t->audmode == V4L2_TUNER_MODE_STEREO ||
+ t->audmode == V4L2_TUNER_MODE_LANG1_LANG2)
+ va.mode = VIDEO_SOUND_STEREO;
+ else if (t->audmode == V4L2_TUNER_MODE_LANG1)
+ va.mode = VIDEO_SOUND_LANG1;
+ else if (t->audmode == V4L2_TUNER_MODE_LANG2)
+ va.mode = VIDEO_SOUND_LANG2;
+ btv->audio_hook(btv,&va,1);
+ }
+ mutex_unlock(&btv->lock);
+ return 0;
+ }
- f->type = V4L2_TUNER_ANALOG_TV;
- f->frequency = btv->freq;
+ case VIDIOC_G_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
- return 0;
-}
+ memset(f,0,sizeof(*f));
+ f->type = V4L2_TUNER_ANALOG_TV;
+ f->frequency = btv->freq;
+ return 0;
+ }
+ case VIDIOC_S_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
-static int bttv_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
- int err;
+ if (unlikely(f->tuner != 0))
+ return -EINVAL;
+ if (unlikely (f->type != V4L2_TUNER_ANALOG_TV))
+ return -EINVAL;
+ mutex_lock(&btv->lock);
+ btv->freq = f->frequency;
+ bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,f);
+ if (btv->has_matchbox && btv->radio_user)
+ tea5757_set_freq(btv,btv->freq);
+ mutex_unlock(&btv->lock);
+ return 0;
+ }
+ case VIDIOC_LOG_STATUS:
+ {
+ printk(KERN_INFO "bttv%d: ================= START STATUS CARD #%d =================\n", btv->c.nr, btv->c.nr);
+ bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL);
+ printk(KERN_INFO "bttv%d: ================== END STATUS CARD #%d ==================\n", btv->c.nr, btv->c.nr);
+ return 0;
+ }
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_DBG_G_REGISTER:
+ case VIDIOC_DBG_S_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ return -EINVAL;
+ /* bt848 has a 12-bit register space */
+ reg->reg &= 0xfff;
+ if (cmd == VIDIOC_DBG_G_REGISTER)
+ reg->val = btread(reg->reg);
+ else
+ btwrite(reg->val, reg->reg);
+ return 0;
+ }
+#endif
- err = v4l2_prio_check(&btv->prio, &fh->prio);
- if (0 != err)
- return err;
+ default:
+ return -ENOIOCTLCMD;
- if (unlikely(f->tuner != 0))
- return -EINVAL;
- if (unlikely(f->type != V4L2_TUNER_ANALOG_TV))
- return -EINVAL;
- mutex_lock(&btv->lock);
- btv->freq = f->frequency;
- bttv_call_i2c_clients(btv, VIDIOC_S_FREQUENCY, f);
- if (btv->has_matchbox && btv->radio_user)
- tea5757_set_freq(btv, btv->freq);
- mutex_unlock(&btv->lock);
+ }
return 0;
}
-static int bttv_log_status(struct file *file, void *f)
+/* Given cropping boundaries b and the scaled width and height of a
+ single field or frame, which must not exceed hardware limits, this
+ function adjusts the cropping parameters c. */
+static void
+bttv_crop_adjust (struct bttv_crop * c,
+ const struct v4l2_rect * b,
+ __s32 width,
+ __s32 height,
+ enum v4l2_field field)
{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
+ __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
+ __s32 max_left;
+ __s32 max_top;
- printk(KERN_INFO "bttv%d: ======== START STATUS CARD #%d ========\n",
- btv->c.nr, btv->c.nr);
- bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL);
- printk(KERN_INFO "bttv%d: ======== END STATUS CARD #%d ========\n",
- btv->c.nr, btv->c.nr);
- return 0;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int bttv_g_register(struct file *file, void *f,
- struct v4l2_register *reg)
-{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
- return -EINVAL;
-
- /* bt848 has a 12-bit register space */
- reg->reg &= 0xfff;
- reg->val = btread(reg->reg);
-
- return 0;
-}
-
-static int bttv_s_register(struct file *file, void *f,
- struct v4l2_register *reg)
-{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
- return -EINVAL;
-
- /* bt848 has a 12-bit register space */
- reg->reg &= 0xfff;
- btwrite(reg->val, reg->reg);
-
- return 0;
-}
-#endif
-
-/* Given cropping boundaries b and the scaled width and height of a
- single field or frame, which must not exceed hardware limits, this
- function adjusts the cropping parameters c. */
-static void
-bttv_crop_adjust (struct bttv_crop * c,
- const struct v4l2_rect * b,
- __s32 width,
- __s32 height,
- enum v4l2_field field)
-{
- __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
- __s32 max_left;
- __s32 max_top;
-
- if (width < c->min_scaled_width) {
- /* Max. hor. scale factor 16:1. */
- c->rect.width = width * 16;
- } else if (width > c->max_scaled_width) {
- /* Min. hor. scale factor 1:1. */
- c->rect.width = width;
+ if (width < c->min_scaled_width) {
+ /* Max. hor. scale factor 16:1. */
+ c->rect.width = width * 16;
+ } else if (width > c->max_scaled_width) {
+ /* Min. hor. scale factor 1:1. */
+ c->rect.width = width;
max_left = b->left + b->width - width;
max_left = min(max_left, (__s32) MAX_HDELAY);
@@ -2447,681 +2659,983 @@ pix_format_set_size (struct v4l2_pix_format * f,
}
}
-static int bttv_g_fmt_cap(struct file *file, void *priv,
- struct v4l2_format *f)
+static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f)
{
- struct bttv_fh *fh = priv;
-
- pix_format_set_size(&f->fmt.pix, fh->fmt,
- fh->width, fh->height);
- f->fmt.pix.field = fh->cap.field;
- f->fmt.pix.pixelformat = fh->fmt->fourcc;
-
- return 0;
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ memset(&f->fmt.pix,0,sizeof(struct v4l2_pix_format));
+ pix_format_set_size (&f->fmt.pix, fh->fmt,
+ fh->width, fh->height);
+ f->fmt.pix.field = fh->cap.field;
+ f->fmt.pix.pixelformat = fh->fmt->fourcc;
+ return 0;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ memset(&f->fmt.win,0,sizeof(struct v4l2_window));
+ f->fmt.win.w = fh->ov.w;
+ f->fmt.win.field = fh->ov.field;
+ return 0;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ bttv_vbi_get_fmt(fh, &f->fmt.vbi);
+ return 0;
+ default:
+ return -EINVAL;
+ }
}
-static int bttv_g_fmt_overlay(struct file *file, void *priv,
- struct v4l2_format *f)
+static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
+ struct v4l2_format *f, int adjust_crop)
{
- struct bttv_fh *fh = priv;
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ {
+ const struct bttv_format *fmt;
+ enum v4l2_field field;
+ __s32 width, height;
+ int rc;
- f->fmt.win.w = fh->ov.w;
- f->fmt.win.field = fh->ov.field;
+ fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ if (NULL == fmt)
+ return -EINVAL;
- return 0;
-}
+ field = f->fmt.pix.field;
+ if (V4L2_FIELD_ANY == field) {
+ __s32 height2;
-static int bttv_try_fmt_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- const struct bttv_format *fmt;
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
- enum v4l2_field field;
- __s32 width, height;
- int rc;
+ height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
+ field = (f->fmt.pix.height > height2)
+ ? V4L2_FIELD_INTERLACED
+ : V4L2_FIELD_BOTTOM;
+ }
+ if (V4L2_FIELD_SEQ_BT == field)
+ field = V4L2_FIELD_SEQ_TB;
+ switch (field) {
+ case V4L2_FIELD_TOP:
+ case V4L2_FIELD_BOTTOM:
+ case V4L2_FIELD_ALTERNATE:
+ case V4L2_FIELD_INTERLACED:
+ break;
+ case V4L2_FIELD_SEQ_TB:
+ if (fmt->flags & FORMAT_FLAGS_PLANAR)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
- fmt = format_by_fourcc(f->fmt.pix.pixelformat);
- if (NULL == fmt)
- return -EINVAL;
+ width = f->fmt.pix.width;
+ height = f->fmt.pix.height;
- field = f->fmt.pix.field;
+ rc = limit_scaled_size(fh, &width, &height, field,
+ /* width_mask: 4 pixels */ ~3,
+ /* width_bias: nearest */ 2,
+ /* adjust_size */ 1,
+ adjust_crop);
+ if (0 != rc)
+ return rc;
- if (V4L2_FIELD_ANY == field) {
- __s32 height2;
+ /* update data for the application */
+ f->fmt.pix.field = field;
+ pix_format_set_size(&f->fmt.pix, fmt, width, height);
- height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
- field = (f->fmt.pix.height > height2)
- ? V4L2_FIELD_INTERLACED
- : V4L2_FIELD_BOTTOM;
+ return 0;
}
-
- if (V4L2_FIELD_SEQ_BT == field)
- field = V4L2_FIELD_SEQ_TB;
-
- switch (field) {
- case V4L2_FIELD_TOP:
- case V4L2_FIELD_BOTTOM:
- case V4L2_FIELD_ALTERNATE:
- case V4L2_FIELD_INTERLACED:
- break;
- case V4L2_FIELD_SEQ_TB:
- if (fmt->flags & FORMAT_FLAGS_PLANAR)
- return -EINVAL;
- break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ return verify_window(fh, &f->fmt.win,
+ /* adjust_size */ 1,
+ /* adjust_crop */ 0);
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ return bttv_vbi_try_fmt(fh, &f->fmt.vbi);
default:
return -EINVAL;
}
-
- width = f->fmt.pix.width;
- height = f->fmt.pix.height;
-
- rc = limit_scaled_size(fh, &width, &height, field,
- /* width_mask: 4 pixels */ ~3,
- /* width_bias: nearest */ 2,
- /* adjust_size */ 1,
- /* adjust_crop */ 0);
- if (0 != rc)
- return rc;
-
- /* update data for the application */
- f->fmt.pix.field = field;
- pix_format_set_size(&f->fmt.pix, fmt, width, height);
-
- return 0;
}
-static int bttv_try_fmt_overlay(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct bttv_fh *fh = priv;
-
- return verify_window(fh, &f->fmt.win,
- /* adjust_size */ 1,
- /* adjust_crop */ 0);
-}
-
-static int bttv_s_fmt_cap(struct file *file, void *priv,
- struct v4l2_format *f)
+static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
+ struct v4l2_format *f)
{
int retval;
- const struct bttv_format *fmt;
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
- __s32 width, height;
- enum v4l2_field field;
-
- retval = bttv_switch_type(fh, f->type);
- if (0 != retval)
- return retval;
-
- retval = bttv_try_fmt_cap(file, priv, f);
- if (0 != retval)
- return retval;
- width = f->fmt.pix.width;
- height = f->fmt.pix.height;
- field = f->fmt.pix.field;
-
- retval = limit_scaled_size(fh, &width, &height, f->fmt.pix.field,
- /* width_mask: 4 pixels */ ~3,
- /* width_bias: nearest */ 2,
- /* adjust_size */ 1,
- /* adjust_crop */ 1);
- if (0 != retval)
- return retval;
-
- f->fmt.pix.field = field;
-
- fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-
- /* update our state informations */
- mutex_lock(&fh->cap.lock);
- fh->fmt = fmt;
- fh->cap.field = f->fmt.pix.field;
- fh->cap.last = V4L2_FIELD_NONE;
- fh->width = f->fmt.pix.width;
- fh->height = f->fmt.pix.height;
- btv->init.fmt = fmt;
- btv->init.width = f->fmt.pix.width;
- btv->init.height = f->fmt.pix.height;
- mutex_unlock(&fh->cap.lock);
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ {
+ const struct bttv_format *fmt;
- return 0;
-}
+ retval = bttv_switch_type(fh,f->type);
+ if (0 != retval)
+ return retval;
+ retval = bttv_try_fmt(fh,btv,f, /* adjust_crop */ 1);
+ if (0 != retval)
+ return retval;
+ fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-static int bttv_s_fmt_overlay(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
+ /* update our state informations */
+ mutex_lock(&fh->cap.lock);
+ fh->fmt = fmt;
+ fh->cap.field = f->fmt.pix.field;
+ fh->cap.last = V4L2_FIELD_NONE;
+ fh->width = f->fmt.pix.width;
+ fh->height = f->fmt.pix.height;
+ btv->init.fmt = fmt;
+ btv->init.width = f->fmt.pix.width;
+ btv->init.height = f->fmt.pix.height;
+ mutex_unlock(&fh->cap.lock);
- if (no_overlay > 0) {
- printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+ return 0;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ if (no_overlay > 0) {
+ printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+ return -EINVAL;
+ }
+ return setup_window(fh, btv, &f->fmt.win, 1);
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ retval = bttv_switch_type(fh,f->type);
+ if (0 != retval)
+ return retval;
+ return bttv_vbi_set_fmt(fh, &f->fmt.vbi);
+ default:
return -EINVAL;
}
-
- return setup_window(fh, btv, &f->fmt.win, 1);
}
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
+static int bttv_do_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
{
- int retval;
- unsigned int i;
- struct bttv_fh *fh = priv;
+ struct bttv_fh *fh = file->private_data;
+ struct bttv *btv = fh->btv;
+ unsigned long flags;
+ int retval = 0;
- mutex_lock(&fh->cap.lock);
- retval = videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,
- V4L2_MEMORY_MMAP);
- if (retval < 0) {
- mutex_unlock(&fh->cap.lock);
- return retval;
- }
+ if (bttv_debug > 1)
+ v4l_print_ioctl(btv->c.name, cmd);
+
+ if (btv->errors)
+ bttv_reinit_bt848(btv);
+
+ switch (cmd) {
+ case VIDIOCSFREQ:
+ case VIDIOCSTUNER:
+ case VIDIOCSCHAN:
+ case VIDIOC_S_CTRL:
+ case VIDIOC_S_STD:
+ case VIDIOC_S_INPUT:
+ case VIDIOC_S_TUNER:
+ case VIDIOC_S_FREQUENCY:
+ retval = v4l2_prio_check(&btv->prio,&fh->prio);
+ if (0 != retval)
+ return retval;
+ };
- gbuffers = retval;
- memset(mbuf, 0, sizeof(*mbuf));
- mbuf->frames = gbuffers;
- mbuf->size = gbuffers * gbufsize;
+ switch (cmd) {
- for (i = 0; i < gbuffers; i++)
- mbuf->offsets[i] = i * gbufsize;
+ /* *** v4l1 *** ************************************************ */
+ case VIDIOCGCAP:
+ {
+ struct video_capability *cap = arg;
- mutex_unlock(&fh->cap.lock);
- return 0;
-}
-#endif
+ memset(cap,0,sizeof(*cap));
+ strcpy(cap->name,btv->video_dev->name);
+ if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
+ /* vbi */
+ cap->type = VID_TYPE_TUNER|VID_TYPE_TELETEXT;
+ } else {
+ /* others */
+ cap->type = VID_TYPE_CAPTURE|
+ VID_TYPE_TUNER|
+ VID_TYPE_CLIPPING|
+ VID_TYPE_SCALES;
+ if (no_overlay <= 0)
+ cap->type |= VID_TYPE_OVERLAY;
+
+ cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth;
+ cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight;
+ cap->minwidth = 48;
+ cap->minheight = 32;
+ }
+ cap->channels = bttv_tvcards[btv->c.type].video_inputs;
+ cap->audios = bttv_tvcards[btv->c.type].audio_inputs;
+ return 0;
+ }
-static int bttv_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
+ case VIDIOCGPICT:
+ {
+ struct video_picture *pic = arg;
+
+ memset(pic,0,sizeof(*pic));
+ pic->brightness = btv->bright;
+ pic->contrast = btv->contrast;
+ pic->hue = btv->hue;
+ pic->colour = btv->saturation;
+ if (fh->fmt) {
+ pic->depth = fh->fmt->depth;
+ pic->palette = fh->fmt->palette;
+ }
+ return 0;
+ }
+ case VIDIOCSPICT:
+ {
+ struct video_picture *pic = arg;
+ const struct bttv_format *fmt;
- if (0 == v4l2)
- return -EINVAL;
+ fmt = format_by_palette(pic->palette);
+ if (NULL == fmt)
+ return -EINVAL;
+ mutex_lock(&fh->cap.lock);
+ if (fmt->flags & FORMAT_FLAGS_RAW) {
+ /* VIDIOCMCAPTURE uses gbufsize, not RAW_BPL *
+ RAW_LINES * 2. F1 is stored at offset 0, F2
+ at buffer size / 2. */
+ fh->width = RAW_BPL;
+ fh->height = gbufsize / RAW_BPL;
+ btv->init.width = RAW_BPL;
+ btv->init.height = gbufsize / RAW_BPL;
+ }
+ fh->ovfmt = fmt;
+ fh->fmt = fmt;
+ btv->init.ovfmt = fmt;
+ btv->init.fmt = fmt;
+ if (bigendian) {
+ /* dirty hack time: swap bytes for overlay if the
+ display adaptor is big endian (insmod option) */
+ if (fmt->palette == VIDEO_PALETTE_RGB555 ||
+ fmt->palette == VIDEO_PALETTE_RGB565 ||
+ fmt->palette == VIDEO_PALETTE_RGB32) {
+ fh->ovfmt = fmt+1;
+ }
+ }
+ bt848_bright(btv,pic->brightness);
+ bt848_contrast(btv,pic->contrast);
+ bt848_hue(btv,pic->hue);
+ bt848_sat(btv,pic->colour);
+ mutex_unlock(&fh->cap.lock);
+ return 0;
+ }
- strlcpy(cap->driver, "bttv", sizeof(cap->driver));
- strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
- snprintf(cap->bus_info, sizeof(cap->bus_info),
- "PCI:%s", pci_name(btv->c.pci));
- cap->version = BTTV_VERSION_CODE;
- cap->capabilities =
- V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_VBI_CAPTURE |
- V4L2_CAP_READWRITE |
- V4L2_CAP_STREAMING;
- if (no_overlay <= 0)
- cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
-
- if (bttv_tvcards[btv->c.type].tuner != UNSET &&
- bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
- cap->capabilities |= V4L2_CAP_TUNER;
- return 0;
-}
+ case VIDIOCGWIN:
+ {
+ struct video_window *win = arg;
-static int bttv_enum_fmt_vbi(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- if (0 != f->index)
- return -EINVAL;
+ memset(win,0,sizeof(*win));
+ win->x = fh->ov.w.left;
+ win->y = fh->ov.w.top;
+ win->width = fh->ov.w.width;
+ win->height = fh->ov.w.height;
+ return 0;
+ }
+ case VIDIOCSWIN:
+ {
+ struct video_window *win = arg;
+ struct v4l2_window w2;
- f->pixelformat = V4L2_PIX_FMT_GREY;
- strcpy(f->description, "vbi data");
+ if (no_overlay > 0) {
+ printk ("VIDIOCSWIN: no_overlay\n");
+ return -EINVAL;
+ }
- return 0;
-}
+ w2.field = V4L2_FIELD_ANY;
+ w2.w.left = win->x;
+ w2.w.top = win->y;
+ w2.w.width = win->width;
+ w2.w.height = win->height;
+ w2.clipcount = win->clipcount;
+ w2.clips = (struct v4l2_clip __user *)win->clips;
+ retval = setup_window(fh, btv, &w2, 0);
+ if (0 == retval) {
+ /* on v4l1 this ioctl affects the read() size too */
+ fh->width = fh->ov.w.width;
+ fh->height = fh->ov.w.height;
+ btv->init.width = fh->ov.w.width;
+ btv->init.height = fh->ov.w.height;
+ }
+ return retval;
+ }
-static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
-{
- int index = -1, i;
+ case VIDIOCGFBUF:
+ {
+ struct video_buffer *fbuf = arg;
+
+ fbuf->base = btv->fbuf.base;
+ fbuf->width = btv->fbuf.fmt.width;
+ fbuf->height = btv->fbuf.fmt.height;
+ fbuf->bytesperline = btv->fbuf.fmt.bytesperline;
+ if (fh->ovfmt)
+ fbuf->depth = fh->ovfmt->depth;
+ else {
+ if (fbuf->width)
+ fbuf->depth = ((fbuf->bytesperline<<3)
+ + (fbuf->width-1) )
+ /fbuf->width;
+ else
+ fbuf->depth = 0;
+ }
+ return 0;
+ }
+ case VIDIOCSFBUF:
+ {
+ struct video_buffer *fbuf = arg;
+ const struct bttv_format *fmt;
+ unsigned long end;
+
+ if(!capable(CAP_SYS_ADMIN) &&
+ !capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ end = (unsigned long)fbuf->base +
+ fbuf->height * fbuf->bytesperline;
+ mutex_lock(&fh->cap.lock);
+ retval = -EINVAL;
- for (i = 0; i < FORMATS; i++) {
- if (formats[i].fourcc != -1)
- index++;
- if ((unsigned int)index == f->index)
+ switch (fbuf->depth) {
+ case 8:
+ fmt = format_by_palette(VIDEO_PALETTE_HI240);
+ break;
+ case 16:
+ fmt = format_by_palette(VIDEO_PALETTE_RGB565);
+ break;
+ case 24:
+ fmt = format_by_palette(VIDEO_PALETTE_RGB24);
break;
+ case 32:
+ fmt = format_by_palette(VIDEO_PALETTE_RGB32);
+ break;
+ case 15:
+ fbuf->depth = 16;
+ fmt = format_by_palette(VIDEO_PALETTE_RGB555);
+ break;
+ default:
+ fmt = NULL;
+ break;
+ }
+ if (NULL == fmt)
+ goto fh_unlock_and_return;
+
+ fh->ovfmt = fmt;
+ fh->fmt = fmt;
+ btv->init.ovfmt = fmt;
+ btv->init.fmt = fmt;
+ btv->fbuf.base = fbuf->base;
+ btv->fbuf.fmt.width = fbuf->width;
+ btv->fbuf.fmt.height = fbuf->height;
+ if (fbuf->bytesperline)
+ btv->fbuf.fmt.bytesperline = fbuf->bytesperline;
+ else
+ btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fbuf->depth/8;
+ mutex_unlock(&fh->cap.lock);
+ return 0;
}
- if (FORMATS == i)
- return -EINVAL;
-
- f->pixelformat = formats[i].fourcc;
- strlcpy(f->description, formats[i].name, sizeof(f->description));
- return i;
-}
-
-static int bttv_enum_fmt_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- int rc = bttv_enum_fmt_cap_ovr(f);
+ case VIDIOCCAPTURE:
+ case VIDIOC_OVERLAY:
+ {
+ struct bttv_buffer *new;
+ int *on = arg;
- if (rc < 0)
- return rc;
+ if (*on) {
+ /* verify args */
+ if (NULL == btv->fbuf.base)
+ return -EINVAL;
+ if (!fh->ov.setup_ok) {
+ dprintk("bttv%d: overlay: !setup_ok\n",btv->c.nr);
+ return -EINVAL;
+ }
+ }
- return 0;
-}
+ if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY))
+ return -EBUSY;
-static int bttv_enum_fmt_overlay(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- int rc;
+ mutex_lock(&fh->cap.lock);
+ if (*on) {
+ fh->ov.tvnorm = btv->tvnorm;
+ new = videobuf_pci_alloc(sizeof(*new));
+ new->crop = btv->crop[!!fh->do_crop].rect;
+ bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+ } else {
+ new = NULL;
+ }
- if (no_overlay > 0) {
- printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
- return -EINVAL;
+ /* switch over */
+ retval = bttv_switch_overlay(btv,fh,new);
+ mutex_unlock(&fh->cap.lock);
+ return retval;
}
- rc = bttv_enum_fmt_cap_ovr(f);
-
- if (rc < 0)
- return rc;
-
- if (!(formats[rc].flags & FORMAT_FLAGS_PACKED))
- return -EINVAL;
-
- return 0;
-}
-
-static int bttv_g_fbuf(struct file *file, void *f,
- struct v4l2_framebuffer *fb)
-{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
-
- *fb = btv->fbuf;
- fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
- if (fh->ovfmt)
- fb->fmt.pixelformat = fh->ovfmt->fourcc;
- return 0;
-}
-
-static int bttv_overlay(struct file *file, void *f, unsigned int on)
-{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
- struct bttv_buffer *new;
- int retval;
-
- if (on) {
- /* verify args */
- if (NULL == btv->fbuf.base)
- return -EINVAL;
- if (!fh->ov.setup_ok) {
- dprintk("bttv%d: overlay: !setup_ok\n", btv->c.nr);
- return -EINVAL;
- }
- }
+ case VIDIOCGMBUF:
+ {
+ struct video_mbuf *mbuf = arg;
+ unsigned int i;
- if (!check_alloc_btres(btv, fh, RESOURCE_OVERLAY))
- return -EBUSY;
+ retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize,
+ V4L2_MEMORY_MMAP);
+ if (retval < 0)
+ return retval;
- mutex_lock(&fh->cap.lock);
- if (on) {
- fh->ov.tvnorm = btv->tvnorm;
- new = videobuf_pci_alloc(sizeof(*new));
- bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
- } else {
- new = NULL;
+ gbuffers = retval;
+ memset(mbuf,0,sizeof(*mbuf));
+ mbuf->frames = gbuffers;
+ mbuf->size = gbuffers * gbufsize;
+ for (i = 0; i < gbuffers; i++)
+ mbuf->offsets[i] = i * gbufsize;
+ return 0;
}
+ case VIDIOCMCAPTURE:
+ {
+ struct video_mmap *vm = arg;
+ struct bttv_buffer *buf;
+ enum v4l2_field field;
+ __s32 height2;
+ int res;
- /* switch over */
- retval = bttv_switch_overlay(btv, fh, new);
- mutex_unlock(&fh->cap.lock);
- return retval;
-}
-
-static int bttv_s_fbuf(struct file *file, void *f,
- struct v4l2_framebuffer *fb)
-{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
- const struct bttv_format *fmt;
- int retval;
+ if (vm->frame >= VIDEO_MAX_FRAME)
+ return -EINVAL;
- if (!capable(CAP_SYS_ADMIN) &&
- !capable(CAP_SYS_RAWIO))
- return -EPERM;
+ res = bttv_resource(fh);
+ if (!check_alloc_btres(btv, fh, res))
+ return -EBUSY;
- /* check args */
- fmt = format_by_fourcc(fb->fmt.pixelformat);
- if (NULL == fmt)
- return -EINVAL;
- if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
- return -EINVAL;
+ mutex_lock(&fh->cap.lock);
+ retval = -EINVAL;
+ buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame];
+ if (NULL == buf)
+ goto fh_unlock_and_return;
+ if (0 == buf->vb.baddr)
+ goto fh_unlock_and_return;
+ if (buf->vb.state == STATE_QUEUED ||
+ buf->vb.state == STATE_ACTIVE)
+ goto fh_unlock_and_return;
- retval = -EINVAL;
- if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
- __s32 width = fb->fmt.width;
- __s32 height = fb->fmt.height;
-
- retval = limit_scaled_size(fh, &width, &height,
- V4L2_FIELD_INTERLACED,
- /* width_mask */ ~3,
- /* width_bias */ 2,
- /* adjust_size */ 0,
- /* adjust_crop */ 0);
+ height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
+ field = (vm->height > height2)
+ ? V4L2_FIELD_INTERLACED
+ : V4L2_FIELD_BOTTOM;
+ retval = bttv_prepare_buffer(&fh->cap,btv,buf,
+ format_by_palette(vm->format),
+ vm->width,vm->height,field);
if (0 != retval)
- return retval;
+ goto fh_unlock_and_return;
+ btv->init.width = vm->width;
+ btv->init.height = vm->height;
+ spin_lock_irqsave(&btv->s_lock,flags);
+ buffer_queue(&fh->cap,&buf->vb);
+ spin_unlock_irqrestore(&btv->s_lock,flags);
+ mutex_unlock(&fh->cap.lock);
+ return 0;
}
+ case VIDIOCSYNC:
+ {
+ int *frame = arg;
+ struct bttv_buffer *buf;
- /* ok, accept it */
- mutex_lock(&fh->cap.lock);
- btv->fbuf.base = fb->base;
- btv->fbuf.fmt.width = fb->fmt.width;
- btv->fbuf.fmt.height = fb->fmt.height;
- if (0 != fb->fmt.bytesperline)
- btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
- else
- btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
-
- retval = 0;
- fh->ovfmt = fmt;
- btv->init.ovfmt = fmt;
- if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
- fh->ov.w.left = 0;
- fh->ov.w.top = 0;
- fh->ov.w.width = fb->fmt.width;
- fh->ov.w.height = fb->fmt.height;
- btv->init.ov.w.width = fb->fmt.width;
- btv->init.ov.w.height = fb->fmt.height;
- kfree(fh->ov.clips);
- fh->ov.clips = NULL;
- fh->ov.nclips = 0;
-
- if (check_btres(fh, RESOURCE_OVERLAY)) {
- struct bttv_buffer *new;
+ if (*frame >= VIDEO_MAX_FRAME)
+ return -EINVAL;
- new = videobuf_pci_alloc(sizeof(*new));
- new->crop = btv->crop[!!fh->do_crop].rect;
- bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
- retval = bttv_switch_overlay(btv, fh, new);
+ mutex_lock(&fh->cap.lock);
+ retval = -EINVAL;
+ buf = (struct bttv_buffer *)fh->cap.bufs[*frame];
+ if (NULL == buf)
+ goto fh_unlock_and_return;
+ retval = videobuf_waiton(&buf->vb,0,1);
+ if (0 != retval)
+ goto fh_unlock_and_return;
+ switch (buf->vb.state) {
+ case STATE_ERROR:
+ retval = -EIO;
+ /* fall through */
+ case STATE_DONE:
+ {
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+ videobuf_dma_sync(&fh->cap,dma);
+ bttv_dma_free(&fh->cap,btv,buf);
+ break;
}
+ default:
+ retval = -EINVAL;
+ break;
+ }
+ mutex_unlock(&fh->cap.lock);
+ return retval;
}
- mutex_unlock(&fh->cap.lock);
- return retval;
-}
-static int bttv_reqbufs(struct file *file, void *priv,
- struct v4l2_requestbuffers *p)
-{
- struct bttv_fh *fh = priv;
- return videobuf_reqbufs(bttv_queue(fh), p);
-}
+ case VIDIOCGVBIFMT:
+ if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) {
+ retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
+ if (0 != retval)
+ return retval;
+ }
+
+ /* fall through */
-static int bttv_querybuf(struct file *file, void *priv,
- struct v4l2_buffer *b)
-{
- struct bttv_fh *fh = priv;
- return videobuf_querybuf(bttv_queue(fh), b);
-}
+ case VIDIOCSVBIFMT:
+ return v4l_compat_translate_ioctl(inode, file, cmd,
+ arg, bttv_do_ioctl);
+
+ case BTTV_VERSION:
+ case VIDIOCGFREQ:
+ case VIDIOCSFREQ:
+ case VIDIOCGTUNER:
+ case VIDIOCSTUNER:
+ case VIDIOCGCHAN:
+ case VIDIOCSCHAN:
+ case VIDIOCGAUDIO:
+ case VIDIOCSAUDIO:
+ return bttv_common_ioctls(btv,cmd,arg);
+
+ /* *** v4l2 *** ************************************************ */
+ case VIDIOC_QUERYCAP:
+ {
+ struct v4l2_capability *cap = arg;
-static int bttv_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
- int res = bttv_resource(fh);
+ if (0 == v4l2)
+ return -EINVAL;
+ memset(cap, 0, sizeof (*cap));
+ strlcpy(cap->driver, "bttv", sizeof (cap->driver));
+ strlcpy(cap->card, btv->video_dev->name, sizeof (cap->card));
+ snprintf(cap->bus_info, sizeof (cap->bus_info),
+ "PCI:%s", pci_name(btv->c.pci));
+ cap->version = BTTV_VERSION_CODE;
+ cap->capabilities =
+ V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_VBI_CAPTURE |
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING;
+ if (no_overlay <= 0)
+ cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
+
+ if (bttv_tvcards[btv->c.type].tuner != UNSET &&
+ bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
+ cap->capabilities |= V4L2_CAP_TUNER;
+ return 0;
+ }
- if (!check_alloc_btres(btv, fh, res))
- return -EBUSY;
+ case VIDIOC_ENUM_FMT:
+ {
+ struct v4l2_fmtdesc *f = arg;
+ enum v4l2_buf_type type;
+ unsigned int i;
+ int index;
+
+ type = f->type;
+ if (V4L2_BUF_TYPE_VBI_CAPTURE == type) {
+ /* vbi */
+ index = f->index;
+ if (0 != index)
+ return -EINVAL;
+ memset(f,0,sizeof(*f));
+ f->index = index;
+ f->type = type;
+ f->pixelformat = V4L2_PIX_FMT_GREY;
+ strcpy(f->description,"vbi data");
+ return 0;
+ }
- return videobuf_qbuf(bttv_queue(fh), b);
-}
+ /* video capture + overlay */
+ index = -1;
+ for (i = 0; i < BTTV_FORMATS; i++) {
+ if (bttv_formats[i].fourcc != -1)
+ index++;
+ if ((unsigned int)index == f->index)
+ break;
+ }
+ if (BTTV_FORMATS == i)
+ return -EINVAL;
-static int bttv_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
- struct bttv_fh *fh = priv;
- return videobuf_dqbuf(bttv_queue(fh), b,
- file->f_flags & O_NONBLOCK);
-}
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ if (!(bttv_formats[i].flags & FORMAT_FLAGS_PACKED))
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ memset(f,0,sizeof(*f));
+ f->index = index;
+ f->type = type;
+ f->pixelformat = bttv_formats[i].fourcc;
+ strlcpy(f->description,bttv_formats[i].name,sizeof(f->description));
+ return 0;
+ }
-static int bttv_streamon(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
- int res = bttv_resource(fh);
+ case VIDIOC_TRY_FMT:
+ {
+ struct v4l2_format *f = arg;
+ return bttv_try_fmt(fh,btv,f, /* adjust_crop */ 0);
+ }
+ case VIDIOC_G_FMT:
+ {
+ struct v4l2_format *f = arg;
+ return bttv_g_fmt(fh,f);
+ }
+ case VIDIOC_S_FMT:
+ {
+ struct v4l2_format *f = arg;
+ return bttv_s_fmt(fh,btv,f);
+ }
- if (!check_alloc_btres(btv, fh, res))
- return -EBUSY;
- return videobuf_streamon(bttv_queue(fh));
-}
+ case VIDIOC_G_FBUF:
+ {
+ struct v4l2_framebuffer *fb = arg;
+ *fb = btv->fbuf;
+ fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+ if (fh->ovfmt)
+ fb->fmt.pixelformat = fh->ovfmt->fourcc;
+ return 0;
+ }
+ case VIDIOC_S_FBUF:
+ {
+ struct v4l2_framebuffer *fb = arg;
+ const struct bttv_format *fmt;
-static int bttv_streamoff(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
- int retval;
- int res = bttv_resource(fh);
+ if(!capable(CAP_SYS_ADMIN) &&
+ !capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ /* check args */
+ fmt = format_by_fourcc(fb->fmt.pixelformat);
+ if (NULL == fmt)
+ return -EINVAL;
+ if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
+ return -EINVAL;
+ retval = -EINVAL;
+ if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
+ __s32 width = fb->fmt.width;
+ __s32 height = fb->fmt.height;
+
+ retval = limit_scaled_size(fh, &width, &height,
+ V4L2_FIELD_INTERLACED,
+ /* width_mask */ ~3,
+ /* width_bias */ 2,
+ /* adjust_size */ 0,
+ /* adjust_crop */ 0);
+ if (0 != retval)
+ return retval;
+ }
- retval = videobuf_streamoff(bttv_queue(fh));
- if (retval < 0)
+ /* ok, accept it */
+ mutex_lock(&fh->cap.lock);
+ btv->fbuf.base = fb->base;
+ btv->fbuf.fmt.width = fb->fmt.width;
+ btv->fbuf.fmt.height = fb->fmt.height;
+ if (0 != fb->fmt.bytesperline)
+ btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
+ else
+ btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
+
+ retval = 0;
+ fh->ovfmt = fmt;
+ btv->init.ovfmt = fmt;
+ if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
+ fh->ov.w.left = 0;
+ fh->ov.w.top = 0;
+ fh->ov.w.width = fb->fmt.width;
+ fh->ov.w.height = fb->fmt.height;
+ btv->init.ov.w.width = fb->fmt.width;
+ btv->init.ov.w.height = fb->fmt.height;
+ kfree(fh->ov.clips);
+ fh->ov.clips = NULL;
+ fh->ov.nclips = 0;
+
+ if (check_btres(fh, RESOURCE_OVERLAY)) {
+ struct bttv_buffer *new;
+
+ new = videobuf_pci_alloc(sizeof(*new));
+ new->crop = btv->crop[!!fh->do_crop].rect;
+ bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new);
+ retval = bttv_switch_overlay(btv,fh,new);
+ }
+ }
+ mutex_unlock(&fh->cap.lock);
return retval;
- free_btres(btv, fh, res);
- return 0;
-}
+ }
-static int bttv_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *c)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
- const struct v4l2_queryctrl *ctrl;
+ case VIDIOC_REQBUFS:
+ return videobuf_reqbufs(bttv_queue(fh),arg);
- if ((c->id < V4L2_CID_BASE ||
- c->id >= V4L2_CID_LASTP1) &&
- (c->id < V4L2_CID_PRIVATE_BASE ||
- c->id >= V4L2_CID_PRIVATE_LASTP1))
- return -EINVAL;
+ case VIDIOC_QUERYBUF:
+ return videobuf_querybuf(bttv_queue(fh),arg);
- if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
- *c = no_ctl;
- else {
- ctrl = ctrl_by_id(c->id);
+ case VIDIOC_QBUF:
+ {
+ int res = bttv_resource(fh);
- *c = (NULL != ctrl) ? *ctrl : no_ctl;
+ if (!check_alloc_btres(btv, fh, res))
+ return -EBUSY;
+ return videobuf_qbuf(bttv_queue(fh),arg);
}
- return 0;
-}
-
-static int bttv_g_parm(struct file *file, void *f,
- struct v4l2_streamparm *parm)
-{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
- struct v4l2_standard s;
-
- if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id,
- bttv_tvnorms[btv->tvnorm].name);
- parm->parm.capture.timeperframe = s.frameperiod;
- return 0;
-}
+ case VIDIOC_DQBUF:
+ return videobuf_dqbuf(bttv_queue(fh),arg,
+ file->f_flags & O_NONBLOCK);
-static int bttv_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
+ case VIDIOC_STREAMON:
+ {
+ int res = bttv_resource(fh);
- if (UNSET == bttv_tvcards[btv->c.type].tuner)
- return -EINVAL;
- if (0 != t->index)
- return -EINVAL;
+ if (!check_alloc_btres(btv,fh,res))
+ return -EBUSY;
+ return videobuf_streamon(bttv_queue(fh));
+ }
+ case VIDIOC_STREAMOFF:
+ {
+ int res = bttv_resource(fh);
- mutex_lock(&btv->lock);
- memset(t, 0, sizeof(*t));
- t->rxsubchans = V4L2_TUNER_SUB_MONO;
- bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
- strcpy(t->name, "Television");
- t->capability = V4L2_TUNER_CAP_NORM;
- t->type = V4L2_TUNER_ANALOG_TV;
- if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
- t->signal = 0xffff;
-
- if (btv->audio_mode_gpio)
- btv->audio_mode_gpio(btv, t, 0);
+ retval = videobuf_streamoff(bttv_queue(fh));
+ if (retval < 0)
+ return retval;
+ free_btres(btv,fh,res);
+ return 0;
+ }
- mutex_unlock(&btv->lock);
- return 0;
-}
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *c = arg;
+ int i;
-static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
-{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
+ if ((c->id < V4L2_CID_BASE ||
+ c->id >= V4L2_CID_LASTP1) &&
+ (c->id < V4L2_CID_PRIVATE_BASE ||
+ c->id >= V4L2_CID_PRIVATE_LASTP1))
+ return -EINVAL;
+ for (i = 0; i < BTTV_CTLS; i++)
+ if (bttv_ctls[i].id == c->id)
+ break;
+ if (i == BTTV_CTLS) {
+ *c = no_ctl;
+ return 0;
+ }
+ *c = bttv_ctls[i];
+ if (btv->audio_hook && i >= 4 && i <= 8) {
+ struct video_audio va;
+ memset(&va,0,sizeof(va));
+ btv->audio_hook(btv,&va,0);
+ switch (bttv_ctls[i].id) {
+ case V4L2_CID_AUDIO_VOLUME:
+ if (!(va.flags & VIDEO_AUDIO_VOLUME))
+ *c = no_ctl;
+ break;
+ case V4L2_CID_AUDIO_BALANCE:
+ if (!(va.flags & VIDEO_AUDIO_BALANCE))
+ *c = no_ctl;
+ break;
+ case V4L2_CID_AUDIO_BASS:
+ if (!(va.flags & VIDEO_AUDIO_BASS))
+ *c = no_ctl;
+ break;
+ case V4L2_CID_AUDIO_TREBLE:
+ if (!(va.flags & VIDEO_AUDIO_TREBLE))
+ *c = no_ctl;
+ break;
+ }
+ }
+ return 0;
+ }
+ case VIDIOC_G_CTRL:
+ return get_control(btv,arg);
+ case VIDIOC_S_CTRL:
+ return set_control(btv,arg);
+ case VIDIOC_G_PARM:
+ {
+ struct v4l2_streamparm *parm = arg;
+ struct v4l2_standard s;
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ memset(parm,0,sizeof(*parm));
+ v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id,
+ bttv_tvnorms[btv->tvnorm].name);
+ parm->parm.capture.timeperframe = s.frameperiod;
+ return 0;
+ }
- *p = v4l2_prio_max(&btv->prio);
+ case VIDIOC_G_PRIORITY:
+ {
+ enum v4l2_priority *p = arg;
- return 0;
-}
+ *p = v4l2_prio_max(&btv->prio);
+ return 0;
+ }
+ case VIDIOC_S_PRIORITY:
+ {
+ enum v4l2_priority *prio = arg;
-static int bttv_s_priority(struct file *file, void *f,
- enum v4l2_priority prio)
-{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
+ return v4l2_prio_change(&btv->prio, &fh->prio, *prio);
+ }
- return v4l2_prio_change(&btv->prio, &fh->prio, prio);
-}
+ case VIDIOC_CROPCAP:
+ {
+ struct v4l2_cropcap *cap = arg;
+ enum v4l2_buf_type type;
-static int bttv_cropcap(struct file *file, void *priv,
- struct v4l2_cropcap *cap)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
+ type = cap->type;
- if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
- cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
- return -EINVAL;
+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+ return -EINVAL;
- *cap = bttv_tvnorms[btv->tvnorm].cropcap;
+ *cap = bttv_tvnorms[btv->tvnorm].cropcap;
+ cap->type = type;
- return 0;
-}
+ return 0;
+ }
+ case VIDIOC_G_CROP:
+ {
+ struct v4l2_crop * crop = arg;
-static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
-{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+ return -EINVAL;
- if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
- crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
- return -EINVAL;
+ /* No fh->do_crop = 1; because btv->crop[1] may be
+ inconsistent with fh->width or fh->height and apps
+ do not expect a change here. */
- /* No fh->do_crop = 1; because btv->crop[1] may be
- inconsistent with fh->width or fh->height and apps
- do not expect a change here. */
+ crop->c = btv->crop[!!fh->do_crop].rect;
- crop->c = btv->crop[!!fh->do_crop].rect;
+ return 0;
+ }
+ case VIDIOC_S_CROP:
+ {
+ struct v4l2_crop *crop = arg;
+ const struct v4l2_rect *b;
+ struct bttv_crop c;
+ __s32 b_left;
+ __s32 b_top;
+ __s32 b_right;
+ __s32 b_bottom;
+
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+ return -EINVAL;
- return 0;
-}
+ retval = v4l2_prio_check(&btv->prio,&fh->prio);
+ if (0 != retval)
+ return retval;
-static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
-{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
- const struct v4l2_rect *b;
- int retval;
- struct bttv_crop c;
- __s32 b_left;
- __s32 b_top;
- __s32 b_right;
- __s32 b_bottom;
+ /* Make sure tvnorm, vbi_end and the current cropping
+ parameters remain consistent until we're done. Note
+ read() may change vbi_end in check_alloc_btres(). */
+ mutex_lock(&btv->lock);
- if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
- crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
- return -EINVAL;
+ retval = -EBUSY;
- retval = v4l2_prio_check(&btv->prio, &fh->prio);
- if (0 != retval)
- return retval;
+ if (locked_btres(fh->btv, VIDEO_RESOURCES))
+ goto btv_unlock_and_return;
- /* Make sure tvnorm, vbi_end and the current cropping
- parameters remain consistent until we're done. Note
- read() may change vbi_end in check_alloc_btres(). */
- mutex_lock(&btv->lock);
+ b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
- retval = -EBUSY;
+ b_left = b->left;
+ b_right = b_left + b->width;
+ b_bottom = b->top + b->height;
- if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
- mutex_unlock(&btv->lock);
- return retval;
- }
+ b_top = max(b->top, btv->vbi_end);
+ if (b_top + 32 >= b_bottom)
+ goto btv_unlock_and_return;
- b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
+ /* Min. scaled size 48 x 32. */
+ c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
+ c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
- b_left = b->left;
- b_right = b_left + b->width;
- b_bottom = b->top + b->height;
+ c.rect.width = clamp(crop->c.width,
+ 48, b_right - c.rect.left);
- b_top = max(b->top, btv->vbi_end);
- if (b_top + 32 >= b_bottom) {
- mutex_unlock(&btv->lock);
- return retval;
- }
+ c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
+ /* Top and height must be a multiple of two. */
+ c.rect.top = (c.rect.top + 1) & ~1;
- /* Min. scaled size 48 x 32. */
- c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
- c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
+ c.rect.height = clamp(crop->c.height,
+ 32, b_bottom - c.rect.top);
+ c.rect.height = (c.rect.height + 1) & ~1;
- c.rect.width = clamp(crop->c.width,
- 48, b_right - c.rect.left);
+ bttv_crop_calc_limits(&c);
- c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
- /* Top and height must be a multiple of two. */
- c.rect.top = (c.rect.top + 1) & ~1;
+ btv->crop[1] = c;
- c.rect.height = clamp(crop->c.height,
- 32, b_bottom - c.rect.top);
- c.rect.height = (c.rect.height + 1) & ~1;
+ mutex_unlock(&btv->lock);
- bttv_crop_calc_limits(&c);
+ fh->do_crop = 1;
- btv->crop[1] = c;
+ mutex_lock(&fh->cap.lock);
- mutex_unlock(&btv->lock);
+ if (fh->width < c.min_scaled_width) {
+ fh->width = c.min_scaled_width;
+ btv->init.width = c.min_scaled_width;
+ } else if (fh->width > c.max_scaled_width) {
+ fh->width = c.max_scaled_width;
+ btv->init.width = c.max_scaled_width;
+ }
- fh->do_crop = 1;
+ if (fh->height < c.min_scaled_height) {
+ fh->height = c.min_scaled_height;
+ btv->init.height = c.min_scaled_height;
+ } else if (fh->height > c.max_scaled_height) {
+ fh->height = c.max_scaled_height;
+ btv->init.height = c.max_scaled_height;
+ }
- mutex_lock(&fh->cap.lock);
+ mutex_unlock(&fh->cap.lock);
- if (fh->width < c.min_scaled_width) {
- fh->width = c.min_scaled_width;
- btv->init.width = c.min_scaled_width;
- } else if (fh->width > c.max_scaled_width) {
- fh->width = c.max_scaled_width;
- btv->init.width = c.max_scaled_width;
+ return 0;
}
- if (fh->height < c.min_scaled_height) {
- fh->height = c.min_scaled_height;
- btv->init.height = c.min_scaled_height;
- } else if (fh->height > c.max_scaled_height) {
- fh->height = c.max_scaled_height;
- btv->init.height = c.max_scaled_height;
+ case VIDIOC_ENUMSTD:
+ case VIDIOC_G_STD:
+ case VIDIOC_S_STD:
+ case VIDIOC_ENUMINPUT:
+ case VIDIOC_G_INPUT:
+ case VIDIOC_S_INPUT:
+ case VIDIOC_G_TUNER:
+ case VIDIOC_S_TUNER:
+ case VIDIOC_G_FREQUENCY:
+ case VIDIOC_S_FREQUENCY:
+ case VIDIOC_LOG_STATUS:
+ case VIDIOC_DBG_G_REGISTER:
+ case VIDIOC_DBG_S_REGISTER:
+ return bttv_common_ioctls(btv,cmd,arg);
+
+ default:
+ return -ENOIOCTLCMD;
}
+ return 0;
+ fh_unlock_and_return:
mutex_unlock(&fh->cap.lock);
+ return retval;
- return 0;
+ btv_unlock_and_return:
+ mutex_unlock(&btv->lock);
+ return retval;
}
-static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+static int bttv_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
- strcpy(a->name, "audio");
- return 0;
-}
+ struct bttv_fh *fh = file->private_data;
-static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
- return 0;
+ switch (cmd) {
+ case BTTV_VBISIZE:
+ {
+ const struct bttv_tvnorm *tvnorm;
+
+ tvnorm = fh->vbi_fmt.tvnorm;
+
+ if (fh->vbi_fmt.fmt.start[0] != tvnorm->vbistart[0] ||
+ fh->vbi_fmt.fmt.start[1] != tvnorm->vbistart[1] ||
+ fh->vbi_fmt.fmt.count[0] != fh->vbi_fmt.fmt.count[1]) {
+ /* BTTV_VBISIZE cannot express these parameters,
+ however open() resets the paramters to defaults
+ and apps shouldn't call BTTV_VBISIZE after
+ VIDIOC_S_FMT. */
+ return -EINVAL;
+ }
+
+ bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
+ return (fh->vbi_fmt.fmt.count[0] * 2
+ * fh->vbi_fmt.fmt.samples_per_line);
+ }
+
+ default:
+ return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl);
+ }
}
static ssize_t bttv_read(struct file *file, char __user *data,
@@ -3205,8 +3719,8 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
}
poll_wait(file, &buf->vb.done, wait);
- if (buf->vb.state == VIDEOBUF_DONE ||
- buf->vb.state == VIDEOBUF_ERROR)
+ if (buf->vb.state == STATE_DONE ||
+ buf->vb.state == STATE_ERROR)
return POLLIN|POLLRDNORM;
return 0;
}
@@ -3263,7 +3777,7 @@ static int bttv_open(struct inode *inode, struct file *file)
V4L2_FIELD_SEQ_TB,
sizeof(struct bttv_buffer),
fh);
- set_tvnorm(btv,btv->tvnorm);
+ i2c_vidiocschan(btv);
btv->users++;
@@ -3343,7 +3857,7 @@ static const struct file_operations bttv_fops =
.owner = THIS_MODULE,
.open = bttv_open,
.release = bttv_release,
- .ioctl = video_ioctl2,
+ .ioctl = bttv_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
.read = bttv_read,
@@ -3353,61 +3867,19 @@ static const struct file_operations bttv_fops =
static struct video_device bttv_video_template =
{
+ .name = "UNSET",
+ .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|
+ VID_TYPE_CLIPPING|VID_TYPE_SCALES,
+ .fops = &bttv_fops,
+ .minor = -1,
+};
+
+static struct video_device bttv_vbi_template =
+{
+ .name = "bt848/878 vbi",
+ .type = VID_TYPE_TUNER|VID_TYPE_TELETEXT,
.fops = &bttv_fops,
.minor = -1,
- .vidioc_querycap = bttv_querycap,
- .vidioc_enum_fmt_cap = bttv_enum_fmt_cap,
- .vidioc_g_fmt_cap = bttv_g_fmt_cap,
- .vidioc_try_fmt_cap = bttv_try_fmt_cap,
- .vidioc_s_fmt_cap = bttv_s_fmt_cap,
- .vidioc_enum_fmt_overlay = bttv_enum_fmt_overlay,
- .vidioc_g_fmt_overlay = bttv_g_fmt_overlay,
- .vidioc_try_fmt_overlay = bttv_try_fmt_overlay,
- .vidioc_s_fmt_overlay = bttv_s_fmt_overlay,
- .vidioc_enum_fmt_vbi = bttv_enum_fmt_vbi,
- .vidioc_g_fmt_vbi = bttv_g_fmt_vbi,
- .vidioc_try_fmt_vbi = bttv_try_fmt_vbi,
- .vidioc_s_fmt_vbi = bttv_s_fmt_vbi,
- .vidioc_g_audio = bttv_g_audio,
- .vidioc_s_audio = bttv_s_audio,
- .vidioc_cropcap = bttv_cropcap,
- .vidioc_reqbufs = bttv_reqbufs,
- .vidioc_querybuf = bttv_querybuf,
- .vidioc_qbuf = bttv_qbuf,
- .vidioc_dqbuf = bttv_dqbuf,
- .vidioc_s_std = bttv_s_std,
- .vidioc_enum_input = bttv_enum_input,
- .vidioc_g_input = bttv_g_input,
- .vidioc_s_input = bttv_s_input,
- .vidioc_queryctrl = bttv_queryctrl,
- .vidioc_g_ctrl = bttv_g_ctrl,
- .vidioc_s_ctrl = bttv_s_ctrl,
- .vidioc_streamon = bttv_streamon,
- .vidioc_streamoff = bttv_streamoff,
- .vidioc_g_tuner = bttv_g_tuner,
- .vidioc_s_tuner = bttv_s_tuner,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
- .vidiocgmbuf = vidiocgmbuf,
-#endif
- .vidioc_g_crop = bttv_g_crop,
- .vidioc_g_crop = bttv_g_crop,
- .vidioc_s_crop = bttv_s_crop,
- .vidioc_g_fbuf = bttv_g_fbuf,
- .vidioc_s_fbuf = bttv_s_fbuf,
- .vidioc_overlay = bttv_overlay,
- .vidioc_g_priority = bttv_g_priority,
- .vidioc_s_priority = bttv_s_priority,
- .vidioc_g_parm = bttv_g_parm,
- .vidioc_g_frequency = bttv_g_frequency,
- .vidioc_s_frequency = bttv_s_frequency,
- .vidioc_log_status = bttv_log_status,
- .vidioc_querystd = bttv_querystd,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
- .vidioc_g_register = bttv_g_register,
- .vidioc_s_register = bttv_s_register,
-#endif
- .tvnorms = BTTV_NORMS,
- .current_norm = V4L2_STD_PAL,
};
/* ----------------------------------------------------------------------- */
@@ -3446,7 +3918,7 @@ static int radio_open(struct inode *inode, struct file *file)
static int radio_release(struct inode *inode, struct file *file)
{
- struct bttv *btv = file->private_data;
+ struct bttv *btv = file->private_data;
struct rds_command cmd;
btv->radio_user--;
@@ -3456,116 +3928,59 @@ static int radio_release(struct inode *inode, struct file *file)
return 0;
}
-static int radio_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
-
- strcpy(cap->driver, "bttv");
- strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
- sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
- cap->version = BTTV_VERSION_CODE;
- cap->capabilities = V4L2_CAP_TUNER;
-
- return 0;
-}
-
-static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
-
- if (UNSET == bttv_tvcards[btv->c.type].tuner)
- return -EINVAL;
- if (0 != t->index)
- return -EINVAL;
- mutex_lock(&btv->lock);
- memset(t, 0, sizeof(*t));
- strcpy(t->name, "Radio");
- t->type = V4L2_TUNER_RADIO;
-
- bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
-
- if (btv->audio_mode_gpio)
- btv->audio_mode_gpio(btv, t, 0);
-
- mutex_unlock(&btv->lock);
-
- return 0;
-}
-
-static int radio_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
-{
- if (i->index != 0)
- return -EINVAL;
-
- strcpy(i->name, "Radio");
- i->type = V4L2_INPUT_TYPE_TUNER;
-
- return 0;
-}
-
-static int radio_g_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- memset(a, 0, sizeof(*a));
- strcpy(a->name, "Radio");
- return 0;
-}
-
-static int radio_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
-
- if (0 != t->index)
- return -EINVAL;
-
- bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
- return 0;
-}
-
-static int radio_s_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
+static int radio_do_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
{
- return 0;
-}
+ struct bttv *btv = file->private_data;
-static int radio_s_input(struct file *filp, void *priv, unsigned int i)
-{
- return 0;
-}
+ switch (cmd) {
+ case VIDIOCGCAP:
+ {
+ struct video_capability *cap = arg;
-static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
-{
- return 0;
-}
+ memset(cap,0,sizeof(*cap));
+ strcpy(cap->name,btv->radio_dev->name);
+ cap->type = VID_TYPE_TUNER;
+ cap->channels = 1;
+ cap->audios = 1;
+ return 0;
+ }
-static int radio_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *c)
-{
- const struct v4l2_queryctrl *ctrl;
+ case VIDIOCGTUNER:
+ {
+ struct video_tuner *v = arg;
- if (c->id < V4L2_CID_BASE ||
- c->id >= V4L2_CID_LASTP1)
- return -EINVAL;
+ if(v->tuner)
+ return -EINVAL;
+ memset(v,0,sizeof(*v));
+ strcpy(v->name, "Radio");
+ bttv_call_i2c_clients(btv,cmd,v);
+ return 0;
+ }
+ case VIDIOCSTUNER:
+ /* nothing to do */
+ return 0;
- if (c->id == V4L2_CID_AUDIO_MUTE) {
- ctrl = ctrl_by_id(c->id);
- *c = *ctrl;
- } else
- *c = no_ctl;
+ case BTTV_VERSION:
+ case VIDIOCGFREQ:
+ case VIDIOCSFREQ:
+ case VIDIOCGAUDIO:
+ case VIDIOCSAUDIO:
+ case VIDIOC_LOG_STATUS:
+ case VIDIOC_DBG_G_REGISTER:
+ case VIDIOC_DBG_S_REGISTER:
+ return bttv_common_ioctls(btv,cmd,arg);
+ default:
+ return -ENOIOCTLCMD;
+ }
return 0;
}
-static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
+static int radio_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
- *i = 0;
- return 0;
+ return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
}
static ssize_t radio_read(struct file *file, char __user *data,
@@ -3601,29 +4016,17 @@ static const struct file_operations radio_fops =
.open = radio_open,
.read = radio_read,
.release = radio_release,
- .ioctl = video_ioctl2,
+ .ioctl = radio_ioctl,
.llseek = no_llseek,
.poll = radio_poll,
};
static struct video_device radio_template =
{
+ .name = "bt848/878 radio",
+ .type = VID_TYPE_TUNER,
.fops = &radio_fops,
.minor = -1,
- .vidioc_querycap = radio_querycap,
- .vidioc_g_tuner = radio_g_tuner,
- .vidioc_enum_input = radio_enum_input,
- .vidioc_g_audio = radio_g_audio,
- .vidioc_s_tuner = radio_s_tuner,
- .vidioc_s_audio = radio_s_audio,
- .vidioc_s_input = radio_s_input,
- .vidioc_s_std = radio_s_std,
- .vidioc_queryctrl = radio_queryctrl,
- .vidioc_g_input = radio_g_input,
- .vidioc_g_ctrl = bttv_g_ctrl,
- .vidioc_s_ctrl = bttv_s_ctrl,
- .vidioc_g_frequency = bttv_g_frequency,
- .vidioc_s_frequency = bttv_s_frequency,
};
/* ----------------------------------------------------------------------- */
@@ -3905,20 +4308,20 @@ static void bttv_irq_timeout(unsigned long data)
bttv_set_dma(btv, 0);
/* wake up */
- bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_ERROR);
- bttv_irq_wakeup_vbi(btv, ovbi, VIDEOBUF_ERROR);
+ bttv_irq_wakeup_video(btv, &old, &new, STATE_ERROR);
+ bttv_irq_wakeup_vbi(btv, ovbi, STATE_ERROR);
/* cancel all outstanding capture / vbi requests */
while (!list_empty(&btv->capture)) {
item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
list_del(&item->vb.queue);
- item->vb.state = VIDEOBUF_ERROR;
+ item->vb.state = STATE_ERROR;
wake_up(&item->vb.done);
}
while (!list_empty(&btv->vcapture)) {
item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
list_del(&item->vb.queue);
- item->vb.state = VIDEOBUF_ERROR;
+ item->vb.state = STATE_ERROR;
wake_up(&item->vb.done);
}
@@ -3941,7 +4344,7 @@ bttv_irq_wakeup_top(struct bttv *btv)
do_gettimeofday(&wakeup->vb.ts);
wakeup->vb.field_count = btv->field_count;
- wakeup->vb.state = VIDEOBUF_DONE;
+ wakeup->vb.state = STATE_DONE;
wake_up(&wakeup->vb.done);
spin_unlock(&btv->s_lock);
}
@@ -3990,7 +4393,7 @@ bttv_irq_switch_video(struct bttv *btv)
}
/* wake up finished buffers */
- bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_DONE);
+ bttv_irq_wakeup_video(btv, &old, &new, STATE_DONE);
spin_unlock(&btv->s_lock);
}
@@ -4023,7 +4426,7 @@ bttv_irq_switch_vbi(struct bttv *btv)
bttv_buffer_activate_vbi(btv, new);
bttv_set_dma(btv, 0);
- bttv_irq_wakeup_vbi(btv, old, VIDEOBUF_DONE);
+ bttv_irq_wakeup_vbi(btv, old, STATE_DONE);
spin_unlock(&btv->s_lock);
}
@@ -4145,9 +4548,8 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
/* initialitation */
static struct video_device *vdev_init(struct bttv *btv,
- const struct video_device *template,
- const char *type_name,
- const int type)
+ struct video_device *template,
+ char *type)
{
struct video_device *vfd;
@@ -4158,10 +4560,9 @@ static struct video_device *vdev_init(struct bttv *btv,
vfd->minor = -1;
vfd->dev = &btv->c.pci->dev;
vfd->release = video_device_release;
- vfd->type = type;
snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
- type_name, bttv_tvcards[btv->c.type].name);
+ type, bttv_tvcards[btv->c.type].name);
return vfd;
}
@@ -4193,11 +4594,6 @@ static void bttv_unregister_video(struct bttv *btv)
/* register video4linux devices */
static int __devinit bttv_register_video(struct bttv *btv)
{
- int video_type = VID_TYPE_CAPTURE |
- VID_TYPE_TUNER |
- VID_TYPE_CLIPPING|
- VID_TYPE_SCALES;
-
if (no_overlay <= 0) {
bttv_video_template.type |= VID_TYPE_OVERLAY;
} else {
@@ -4205,9 +4601,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
}
/* video */
- btv->video_dev = vdev_init(btv, &bttv_video_template,
- "video", video_type);
-
+ btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
if (NULL == btv->video_dev)
goto err;
if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0)
@@ -4222,9 +4616,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
}
/* vbi */
- btv->vbi_dev = vdev_init(btv, &bttv_video_template,
- "vbi", VID_TYPE_TUNER | VID_TYPE_TELETEXT);
-
+ btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi");
if (NULL == btv->vbi_dev)
goto err;
if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0)
@@ -4235,8 +4627,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
if (!btv->has_radio)
return 0;
/* radio */
- btv->radio_dev = vdev_init(btv, &radio_template,
- "radio", VID_TYPE_TUNER);
+ btv->radio_dev = vdev_init(btv, &radio_template, "radio");
if (NULL == btv->radio_dev)
goto err;
if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0)
@@ -4377,7 +4768,7 @@ static int __devinit bttv_probe(struct pci_dev *dev,
btv->init.btv = btv;
btv->init.ov.w.width = 320;
btv->init.ov.w.height = 240;
- btv->init.fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+ btv->init.fmt = format_by_palette(VIDEO_PALETTE_RGB24);
btv->init.width = 320;
btv->init.height = 240;
btv->input = 0;
@@ -4622,17 +5013,14 @@ static int __init bttv_init_module(void)
printk(KERN_WARNING "bttv: bus_register error: %d\n", ret);
return ret;
}
- ret = pci_register_driver(&bttv_pci_driver);
- if (ret < 0)
- bus_unregister(&bttv_sub_bus_type);
-
- return ret;
+ return pci_register_driver(&bttv_pci_driver);
}
static void __exit bttv_cleanup_module(void)
{
pci_unregister_driver(&bttv_pci_driver);
bus_unregister(&bttv_sub_bus_type);
+ return;
}
module_init(bttv_init_module);
diff --git a/trunk/drivers/media/video/bt8xx/bttv-input.c b/trunk/drivers/media/video/bt8xx/bttv-input.c
index fc9ecb21eec6..e7c521b8444a 100644
--- a/trunk/drivers/media/video/bt8xx/bttv-input.c
+++ b/trunk/drivers/media/video/bt8xx/bttv-input.c
@@ -69,11 +69,6 @@ static void ir_handle_key(struct bttv *btv)
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
ir_input_keydown(ir->dev,&ir->ir,data,data);
} else {
- /* HACK: Probably, ir->mask_keydown is missing
- for this board */
- if (btv->c.type == BTTV_BOARD_WINFAST2000)
- ir_input_keydown(ir->dev, &ir->ir, data, data);
-
ir_input_nokey(ir->dev,&ir->ir);
}
diff --git a/trunk/drivers/media/video/bt8xx/bttv-risc.c b/trunk/drivers/media/video/bt8xx/bttv-risc.c
index e5979f77504c..58986f1a5f1a 100644
--- a/trunk/drivers/media/video/bt8xx/bttv-risc.c
+++ b/trunk/drivers/media/video/bt8xx/bttv-risc.c
@@ -582,7 +582,7 @@ bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf
videobuf_dma_free(dma);
btcx_riscmem_free(btv->c.pci,&buf->bottom);
btcx_riscmem_free(btv->c.pci,&buf->top);
- buf->vb.state = VIDEOBUF_NEEDS_INIT;
+ buf->vb.state = STATE_NEEDS_INIT;
}
int
@@ -602,7 +602,7 @@ bttv_buffer_activate_vbi(struct bttv *btv,
if (vbi) {
unsigned int crop, vdelay;
- vbi->vb.state = VIDEOBUF_ACTIVE;
+ vbi->vb.state = STATE_ACTIVE;
list_del(&vbi->vb.queue);
/* VDELAY is start of video, end of VBI capturing. */
@@ -644,12 +644,12 @@ bttv_buffer_activate_video(struct bttv *btv,
/* video capture */
if (NULL != set->top && NULL != set->bottom) {
if (set->top == set->bottom) {
- set->top->vb.state = VIDEOBUF_ACTIVE;
+ set->top->vb.state = STATE_ACTIVE;
if (set->top->vb.queue.next)
list_del(&set->top->vb.queue);
} else {
- set->top->vb.state = VIDEOBUF_ACTIVE;
- set->bottom->vb.state = VIDEOBUF_ACTIVE;
+ set->top->vb.state = STATE_ACTIVE;
+ set->bottom->vb.state = STATE_ACTIVE;
if (set->top->vb.queue.next)
list_del(&set->top->vb.queue);
if (set->bottom->vb.queue.next)
@@ -666,7 +666,7 @@ bttv_buffer_activate_video(struct bttv *btv,
btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
~0x0f, BT848_COLOR_CTL);
} else if (NULL != set->top) {
- set->top->vb.state = VIDEOBUF_ACTIVE;
+ set->top->vb.state = STATE_ACTIVE;
if (set->top->vb.queue.next)
list_del(&set->top->vb.queue);
bttv_apply_geo(btv, &set->top->geo,1);
@@ -677,7 +677,7 @@ bttv_buffer_activate_video(struct bttv *btv,
btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
} else if (NULL != set->bottom) {
- set->bottom->vb.state = VIDEOBUF_ACTIVE;
+ set->bottom->vb.state = STATE_ACTIVE;
if (set->bottom->vb.queue.next)
list_del(&set->bottom->vb.queue);
bttv_apply_geo(btv, &set->bottom->geo,1);
diff --git a/trunk/drivers/media/video/bt8xx/bttv-vbi.c b/trunk/drivers/media/video/bt8xx/bttv-vbi.c
index 1f0cc79e2a33..346ce019bdcb 100644
--- a/trunk/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/trunk/drivers/media/video/bt8xx/bttv-vbi.c
@@ -142,7 +142,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q,
redo_dma_risc = 1;
}
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ if (STATE_NEEDS_INIT == buf->vb.state) {
redo_dma_risc = 1;
if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
goto fail;
@@ -189,7 +189,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q,
/* For bttv_buffer_activate_vbi(). */
buf->geo.vdelay = min_vdelay;
- buf->vb.state = VIDEOBUF_PREPARED;
+ buf->vb.state = STATE_PREPARED;
buf->vb.field = field;
dprintk("buf prepare %p: top=%p bottom=%p field=%s\n",
vb, &buf->top, &buf->bottom,
@@ -209,7 +209,7 @@ vbi_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
dprintk("queue %p\n",vb);
- buf->vb.state = VIDEOBUF_QUEUED;
+ buf->vb.state = STATE_QUEUED;
list_add_tail(&buf->vb.queue,&btv->vcapture);
if (NULL == btv->cvbi) {
fh->btv->loop_irq |= 4;
@@ -236,8 +236,10 @@ struct videobuf_queue_ops bttv_vbi_qops = {
/* ----------------------------------------------------------------------- */
-static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
- __s32 crop_start)
+static int
+try_fmt (struct v4l2_vbi_format * f,
+ const struct bttv_tvnorm * tvnorm,
+ __s32 crop_start)
{
__s32 min_start, max_start, max_end, f2_offset;
unsigned int i;
@@ -303,9 +305,10 @@ static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
return 0;
}
-int bttv_try_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
+int
+bttv_vbi_try_fmt (struct bttv_fh * fh,
+ struct v4l2_vbi_format * f)
{
- struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
const struct bttv_tvnorm *tvnorm;
__s32 crop_start;
@@ -317,13 +320,13 @@ int bttv_try_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
mutex_unlock(&btv->lock);
- return try_fmt(&frt->fmt.vbi, tvnorm, crop_start);
+ return try_fmt(f, tvnorm, crop_start);
}
-
-int bttv_s_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
+int
+bttv_vbi_set_fmt (struct bttv_fh * fh,
+ struct v4l2_vbi_format * f)
{
- struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
const struct bttv_tvnorm *tvnorm;
__s32 start1, end;
@@ -337,12 +340,11 @@ int bttv_s_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
tvnorm = &bttv_tvnorms[btv->tvnorm];
- rc = try_fmt(&frt->fmt.vbi, tvnorm, btv->crop_start);
+ rc = try_fmt(f, tvnorm, btv->crop_start);
if (0 != rc)
goto fail;
- start1 = frt->fmt.vbi.start[1] - tvnorm->vbistart[1] +
- tvnorm->vbistart[0];
+ start1 = f->start[1] - tvnorm->vbistart[1] + tvnorm->vbistart[0];
/* First possible line of video capturing. Should be
max(f->start[0] + f->count[0], start1 + f->count[1]) * 2
@@ -350,11 +352,11 @@ int bttv_s_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
pretend the VBI and video capture window may overlap,
so end = start + 1, the lowest possible value, times two
because vbi_fmt.end counts field lines times two. */
- end = max(frt->fmt.vbi.start[0], start1) * 2 + 2;
+ end = max(f->start[0], start1) * 2 + 2;
mutex_lock(&fh->vbi.lock);
- fh->vbi_fmt.fmt = frt->fmt.vbi;
+ fh->vbi_fmt.fmt = *f;
fh->vbi_fmt.tvnorm = tvnorm;
fh->vbi_fmt.end = end;
@@ -368,13 +370,13 @@ int bttv_s_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
return rc;
}
-
-int bttv_g_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
+void
+bttv_vbi_get_fmt (struct bttv_fh * fh,
+ struct v4l2_vbi_format * f)
{
- struct bttv_fh *fh = f;
const struct bttv_tvnorm *tvnorm;
- frt->fmt.vbi = fh->vbi_fmt.fmt;
+ *f = fh->vbi_fmt.fmt;
tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
@@ -389,28 +391,28 @@ int bttv_g_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
max_end = (tvnorm->cropcap.bounds.top
+ tvnorm->cropcap.bounds.height) >> 1;
- frt->fmt.vbi.sampling_rate = tvnorm->Fsc;
+ f->sampling_rate = tvnorm->Fsc;
for (i = 0; i < 2; ++i) {
__s32 new_start;
- new_start = frt->fmt.vbi.start[i]
+ new_start = f->start[i]
+ tvnorm->vbistart[i]
- fh->vbi_fmt.tvnorm->vbistart[i];
- frt->fmt.vbi.start[i] = min(new_start, max_end - 1);
- frt->fmt.vbi.count[i] =
- min((__s32) frt->fmt.vbi.count[i],
- max_end - frt->fmt.vbi.start[i]);
+ f->start[i] = min(new_start, max_end - 1);
+ f->count[i] = min((__s32) f->count[i],
+ max_end - f->start[i]);
max_end += tvnorm->vbistart[1]
- tvnorm->vbistart[0];
}
}
- return 0;
}
-void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, int norm)
+void
+bttv_vbi_fmt_reset (struct bttv_vbi_fmt * f,
+ int norm)
{
const struct bttv_tvnorm *tvnorm;
unsigned int real_samples_per_line;
diff --git a/trunk/drivers/media/video/bt8xx/bttv.h b/trunk/drivers/media/video/bt8xx/bttv.h
index bf4c339a520c..19e75d50a107 100644
--- a/trunk/drivers/media/video/bt8xx/bttv.h
+++ b/trunk/drivers/media/video/bt8xx/bttv.h
@@ -241,10 +241,7 @@ struct tvcard
unsigned int radio_addr;
unsigned int has_radio;
-
- void (*volume_gpio)(struct bttv *btv, __u16 volume);
- void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-
+ void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set);
void (*muxsel_hook)(struct bttv *btv, unsigned int input);
};
diff --git a/trunk/drivers/media/video/bt8xx/bttvp.h b/trunk/drivers/media/video/bt8xx/bttvp.h
index 1305d315cfc5..d4ac4c4b49b4 100644
--- a/trunk/drivers/media/video/bt8xx/bttvp.h
+++ b/trunk/drivers/media/video/bt8xx/bttvp.h
@@ -84,11 +84,6 @@
#define clamp(x, low, high) min (max (low, x), high)
-#define BTTV_NORMS (\
- V4L2_STD_PAL | V4L2_STD_PAL_N | \
- V4L2_STD_PAL_Nc | V4L2_STD_SECAM | \
- V4L2_STD_NTSC | V4L2_STD_PAL_M | \
- V4L2_STD_PAL_60)
/* ---------------------------------------------------------- */
struct bttv_tvnorm {
@@ -117,6 +112,7 @@ extern const struct bttv_tvnorm bttv_tvnorms[];
struct bttv_format {
char *name;
+ int palette; /* video4linux 1 */
int fourcc; /* video4linux 2 */
int btformat; /* BT848_COLOR_FMT_* */
int btswap; /* BT848_COLOR_CTL_* */
@@ -257,9 +253,9 @@ int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov,
/* ---------------------------------------------------------- */
/* bttv-vbi.c */
-int bttv_try_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f);
-int bttv_g_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f);
-int bttv_s_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f);
+int bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f);
+void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f);
+int bttv_vbi_set_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f);
extern struct videobuf_queue_ops bttv_vbi_qops;
@@ -341,9 +337,7 @@ struct bttv {
/* old gpio interface */
wait_queue_head_t gpioq;
int shutdown;
-
- void (*volume_gpio)(struct bttv *btv, __u16 volume);
- void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+ void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set);
/* new gpio interface */
spinlock_t gpio_lock;
@@ -464,6 +458,10 @@ struct bttv {
extern unsigned int bttv_num;
extern struct bttv bttvs[BTTV_MAX];
+/* private ioctls */
+#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int)
+#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int)
+
#endif
#define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr))
diff --git a/trunk/drivers/media/video/bw-qcam.c b/trunk/drivers/media/video/bw-qcam.c
index 032265383df2..58423525591f 100644
--- a/trunk/drivers/media/video/bw-qcam.c
+++ b/trunk/drivers/media/video/bw-qcam.c
@@ -82,16 +82,11 @@ OTHER DEALINGS IN THE SOFTWARE.
static unsigned int maxpoll=250; /* Maximum busy-loop count for qcam I/O */
static unsigned int yieldlines=4; /* Yield after this many during capture */
static int video_nr = -1;
-static unsigned int force_init; /* Whether to probe aggressively */
module_param(maxpoll, int, 0);
module_param(yieldlines, int, 0);
module_param(video_nr, int, 0);
-/* Set force_init=1 to avoid detection by polling status register and
- * immediately attempt to initialize qcam */
-module_param(force_init, int, 0);
-
static inline int read_lpstatus(struct qcam_device *q)
{
return parport_read_status(q->pport);
@@ -336,9 +331,6 @@ static int qc_detect(struct qcam_device *q)
int count = 0;
int i;
- if (force_init)
- return 1;
-
lastreg = reg = read_lpstatus(q) & 0xf0;
for (i = 0; i < 500; i++)
@@ -362,12 +354,12 @@ static int qc_detect(struct qcam_device *q)
/* Be (even more) liberal in what you accept... */
+/* if (count > 30 && count < 200) */
if (count > 20 && count < 400) {
return 1; /* found */
} else {
printk(KERN_ERR "No Quickcam found on port %s\n",
q->pport->name);
- printk(KERN_DEBUG "Quickcam detection counter: %u\n", count);
return 0; /* not found */
}
}
diff --git a/trunk/drivers/media/video/cs5345.c b/trunk/drivers/media/video/cs5345.c
deleted file mode 100644
index fae469ce16f5..000000000000
--- a/trunk/drivers/media/video/cs5345.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * cs5345 Cirrus Logic 24-bit, 192 kHz Stereo Audio ADC
- * Copyright (C) 2007 Hans Verkuil
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-MODULE_DESCRIPTION("i2c device driver for cs5345 Audio ADC");
-MODULE_AUTHOR("Hans Verkuil");
-MODULE_LICENSE("GPL");
-
-static int debug;
-
-module_param(debug, bool, 0644);
-
-MODULE_PARM_DESC(debug, "Debugging messages\n\t\t\t0=Off (default), 1=On");
-
-
-/* ----------------------------------------------------------------------- */
-
-static inline int cs5345_write(struct i2c_client *client, u8 reg, u8 value)
-{
- return i2c_smbus_write_byte_data(client, reg, value);
-}
-
-static inline int cs5345_read(struct i2c_client *client, u8 reg)
-{
- return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int cs5345_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
- struct v4l2_routing *route = arg;
- struct v4l2_control *ctrl = arg;
-
- switch (cmd) {
- case VIDIOC_INT_G_AUDIO_ROUTING:
- route->input = cs5345_read(client, 0x09) & 7;
- route->input |= cs5345_read(client, 0x05) & 0x70;
- route->output = 0;
- break;
-
- case VIDIOC_INT_S_AUDIO_ROUTING:
- if ((route->input & 0xf) > 6) {
- v4l_err(client, "Invalid input %d.\n", route->input);
- return -EINVAL;
- }
- cs5345_write(client, 0x09, route->input & 0xf);
- cs5345_write(client, 0x05, route->input & 0xf0);
- break;
-
- case VIDIOC_G_CTRL:
- if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
- ctrl->value = (cs5345_read(client, 0x04) & 0x08) != 0;
- break;
- }
- if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
- return -EINVAL;
- ctrl->value = cs5345_read(client, 0x07) & 0x3f;
- if (ctrl->value >= 32)
- ctrl->value = ctrl->value - 64;
- break;
-
- case VIDIOC_S_CTRL:
- break;
- if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
- cs5345_write(client, 0x04, ctrl->value ? 0x80 : 0);
- break;
- }
- if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
- return -EINVAL;
- if (ctrl->value > 24 || ctrl->value < -24)
- return -EINVAL;
- cs5345_write(client, 0x07, ((u8)ctrl->value) & 0x3f);
- cs5345_write(client, 0x08, ((u8)ctrl->value) & 0x3f);
- break;
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
- case VIDIOC_DBG_G_REGISTER:
- case VIDIOC_DBG_S_REGISTER:
- {
- struct v4l2_register *reg = arg;
-
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
- return -EINVAL;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (cmd == VIDIOC_DBG_G_REGISTER)
- reg->val = cs5345_read(client, reg->reg & 0x1f);
- else
- cs5345_write(client, reg->reg & 0x1f, reg->val & 0x1f);
- break;
- }
-#endif
-
- case VIDIOC_G_CHIP_IDENT:
- return v4l2_chip_ident_i2c_client(client,
- arg, V4L2_IDENT_CS5345, 0);
-
- case VIDIOC_LOG_STATUS:
- {
- u8 v = cs5345_read(client, 0x09) & 7;
- u8 m = cs5345_read(client, 0x04);
- int vol = cs5345_read(client, 0x08) & 0x3f;
-
- v4l_info(client, "Input: %d%s\n", v,
- (m & 0x80) ? " (muted)" : "");
- if (vol >= 32)
- vol = vol - 64;
- v4l_info(client, "Volume: %d dB\n", vol);
- break;
- }
-
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static int cs5345_probe(struct i2c_client *client)
-{
- /* Check if the adapter supports the needed features */
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return -EIO;
-
- v4l_info(client, "chip found @ 0x%x (%s)\n",
- client->addr << 1, client->adapter->name);
-
- cs5345_write(client, 0x02, 0x00);
- cs5345_write(client, 0x04, 0x01);
- cs5345_write(client, 0x09, 0x01);
- return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static struct v4l2_i2c_driver_data v4l2_i2c_data = {
- .name = "cs5345",
- .driverid = I2C_DRIVERID_CS5345,
- .command = cs5345_command,
- .probe = cs5345_probe,
-};
-
diff --git a/trunk/drivers/media/video/cs53l32a.c b/trunk/drivers/media/video/cs53l32a.c
index f41bfde045fe..a73e285af730 100644
--- a/trunk/drivers/media/video/cs53l32a.c
+++ b/trunk/drivers/media/video/cs53l32a.c
@@ -29,13 +29,12 @@
#include
#include
#include
-#include
MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
MODULE_AUTHOR("Martin Vaughan");
MODULE_LICENSE("GPL");
-static int debug;
+static int debug = 0;
module_param(debug, bool, 0644);
@@ -58,7 +57,8 @@ static int cs53l32a_read(struct i2c_client *client, u8 reg)
return i2c_smbus_read_byte_data(client, reg);
}
-static int cs53l32a_command(struct i2c_client *client, unsigned cmd, void *arg)
+static int cs53l32a_command(struct i2c_client *client, unsigned int cmd,
+ void *arg)
{
struct v4l2_routing *route = arg;
struct v4l2_control *ctrl = arg;
@@ -105,8 +105,7 @@ static int cs53l32a_command(struct i2c_client *client, unsigned cmd, void *arg)
break;
case VIDIOC_G_CHIP_IDENT:
- return v4l2_chip_ident_i2c_client(client,
- arg, V4L2_IDENT_CS53l32A, 0);
+ return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_CS53l32A, 0);
case VIDIOC_LOG_STATUS:
{
@@ -135,18 +134,27 @@ static int cs53l32a_command(struct i2c_client *client, unsigned cmd, void *arg)
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
-static int cs53l32a_probe(struct i2c_client *client)
+static struct i2c_driver i2c_driver;
+
+static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind)
{
+ struct i2c_client *client;
int i;
/* Check if the adapter supports the needed features */
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return -EIO;
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return 0;
+
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == 0)
+ return -ENOMEM;
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &i2c_driver;
snprintf(client->name, sizeof(client->name) - 1, "cs53l32a");
- v4l_info(client, "chip found @ 0x%x (%s)\n",
- client->addr << 1, client->adapter->name);
+ v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
for (i = 1; i <= 7; i++) {
u8 v = cs53l32a_read(client, i);
@@ -171,13 +179,55 @@ static int cs53l32a_probe(struct i2c_client *client)
v4l_dbg(1, debug, client, "Read Reg %d %02x\n", i, v);
}
+
+ i2c_attach_client(client);
+
return 0;
}
-static struct v4l2_i2c_driver_data v4l2_i2c_data = {
- .name = "cs53l32a",
- .driverid = I2C_DRIVERID_CS53L32A,
+static int cs53l32a_probe(struct i2c_adapter *adapter)
+{
+ if (adapter->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adapter, &addr_data, cs53l32a_attach);
+ return 0;
+}
+
+static int cs53l32a_detach(struct i2c_client *client)
+{
+ int err;
+
+ err = i2c_detach_client(client);
+ if (err) {
+ return err;
+ }
+ kfree(client);
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+ .driver = {
+ .name = "cs53l32a",
+ },
+ .id = I2C_DRIVERID_CS53L32A,
+ .attach_adapter = cs53l32a_probe,
+ .detach_client = cs53l32a_detach,
.command = cs53l32a_command,
- .probe = cs53l32a_probe,
};
+
+static int __init cs53l32a_init_module(void)
+{
+ return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit cs53l32a_cleanup_module(void)
+{
+ i2c_del_driver(&i2c_driver);
+}
+
+module_init(cs53l32a_init_module);
+module_exit(cs53l32a_cleanup_module);
diff --git a/trunk/drivers/media/video/cx2341x.c b/trunk/drivers/media/video/cx2341x.c
index c592899a2317..62304255dcae 100644
--- a/trunk/drivers/media/video/cx2341x.c
+++ b/trunk/drivers/media/video/cx2341x.c
@@ -34,7 +34,7 @@ MODULE_DESCRIPTION("cx23415/6 driver");
MODULE_AUTHOR("Hans Verkuil");
MODULE_LICENSE("GPL");
-static int debug;
+static int debug = 0;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
@@ -75,7 +75,6 @@ const u32 cx2341x_mpeg_ctrls[] = {
V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
0
};
-EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
/* Map the control ID to the correct field in the cx2341x_mpeg_params
@@ -282,14 +281,13 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
return -EBUSY;
params->stream_type = ctrl->value;
params->video_encoding =
- (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
- params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
- V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
- V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
- if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
+ (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
+ params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
+ V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+ if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
/* MPEG-1 implies CBR */
- params->video_bitrate_mode =
- V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
+ params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
+ }
break;
case V4L2_CID_MPEG_STREAM_VBI_FMT:
params->stream_vbi_fmt = ctrl->value;
@@ -336,8 +334,7 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
return 0;
}
-static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
- s32 min, s32 max, s32 step, s32 def)
+static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
{
const char *name;
@@ -420,8 +417,7 @@ static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
return 0;
}
-int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
- struct v4l2_queryctrl *qctrl)
+int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl)
{
int err;
@@ -444,8 +440,7 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
err = v4l2_ctrl_query_fill_std(qctrl);
- if (err == 0 &&
- params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
+ if (err == 0 && params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
return err;
@@ -460,16 +455,13 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
err = v4l2_ctrl_query_fill_std(qctrl);
- if (err == 0 &&
- params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
+ if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
return err;
case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
err = v4l2_ctrl_query_fill_std(qctrl);
- if (err == 0 &&
- params->video_bitrate_mode ==
- V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+ if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
return err;
@@ -484,90 +476,80 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
/* CX23415/6 specific */
case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
return cx2341x_ctrl_query_fill(qctrl,
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
+ V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
+ V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
+ V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
- if (params->video_spatial_filter_mode ==
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+ if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+ qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
return 0;
case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
cx2341x_ctrl_query_fill(qctrl,
- V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
- V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
- 1,
- V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
- if (params->video_spatial_filter_mode ==
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+ V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
+ V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1,
+ V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
+ if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+ qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
return 0;
case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
cx2341x_ctrl_query_fill(qctrl,
- V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
- V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
- 1,
- V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
- if (params->video_spatial_filter_mode ==
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+ V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
+ V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1,
+ V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
+ if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+ qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
return 0;
case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
return cx2341x_ctrl_query_fill(qctrl,
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
+ V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
+ V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
+ V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
- if (params->video_temporal_filter_mode ==
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+ if (params->video_temporal_filter_mode == V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
+ qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
return 0;
case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
return cx2341x_ctrl_query_fill(qctrl,
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
+ V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
+ V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
+ V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
- if (params->video_median_filter_type ==
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+ if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+ qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
return 0;
case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
- if (params->video_median_filter_type ==
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+ if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+ qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
return 0;
case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
- if (params->video_median_filter_type ==
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+ if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+ qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
return 0;
case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
- if (params->video_median_filter_type ==
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+ if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+ qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
return 0;
case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
@@ -578,7 +560,6 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
}
}
-EXPORT_SYMBOL(cx2341x_ctrl_query);
const char **cx2341x_ctrl_get_menu(u32 id)
{
@@ -648,7 +629,6 @@ const char **cx2341x_ctrl_get_menu(u32 id)
return v4l2_ctrl_get_menu(id);
}
}
-EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
{
@@ -657,8 +637,9 @@ static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
((1 + params->audio_l2_bitrate) << 4) |
(params->audio_mode << 8) |
(params->audio_mode_extension << 10) |
- (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
- ? 3 : params->audio_emphasis) << 12) |
+ (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ?
+ 3 :
+ params->audio_emphasis) << 12) |
(params->audio_crc << 14);
}
@@ -698,19 +679,19 @@ int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
if (err)
break;
}
- if (err == 0 &&
- params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
- params->video_bitrate_peak < params->video_bitrate) {
+ if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
+ params->video_bitrate_peak < params->video_bitrate) {
err = -ERANGE;
ctrls->error_idx = ctrls->count;
}
- if (err)
+ if (err) {
ctrls->error_idx = i;
- else
+ }
+ else {
cx2341x_calc_audio_properties(params);
+ }
return err;
}
-EXPORT_SYMBOL(cx2341x_ext_ctrls);
void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
{
@@ -751,18 +732,13 @@ void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
.video_mute_yuv = 0x008080, /* YCbCr value for black */
/* encoding filters */
- .video_spatial_filter_mode =
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
+ .video_spatial_filter_mode = V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
.video_spatial_filter = 0,
- .video_luma_spatial_filter_type =
- V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
- .video_chroma_spatial_filter_type =
- V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
- .video_temporal_filter_mode =
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
+ .video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
+ .video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
+ .video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
.video_temporal_filter = 8,
- .video_median_filter_type =
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
+ .video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
.video_luma_median_filter_top = 255,
.video_luma_median_filter_bottom = 0,
.video_chroma_median_filter_top = 255,
@@ -772,10 +748,8 @@ void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
*p = default_params;
cx2341x_calc_audio_properties(p);
}
-EXPORT_SYMBOL(cx2341x_fill_defaults);
-static int cx2341x_api(void *priv, cx2341x_mbox_func func,
- u32 cmd, int args, ...)
+static int cx2341x_api(void *priv, cx2341x_mbox_func func, int cmd, int args, ...)
{
u32 data[CX2341X_MBOX_MAX_DATA];
va_list vargs;
@@ -783,17 +757,15 @@ static int cx2341x_api(void *priv, cx2341x_mbox_func func,
va_start(vargs, args);
- for (i = 0; i < args; i++)
+ for (i = 0; i < args; i++) {
data[i] = va_arg(vargs, int);
+ }
va_end(vargs);
return func(priv, cmd, args, 0, data);
}
-#define NEQ(field) (old->field != new->field)
-
int cx2341x_update(void *priv, cx2341x_mbox_func func,
- const struct cx2341x_mpeg_params *old,
- const struct cx2341x_mpeg_params *new)
+ const struct cx2341x_mpeg_params *old, const struct cx2341x_mpeg_params *new)
{
static int mpeg_stream_type[] = {
0, /* MPEG-2 PS */
@@ -805,18 +777,17 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func,
};
int err = 0;
- int force = (old == NULL);
u16 temporal = new->video_temporal_filter;
cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
- if (force || NEQ(is_50hz)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
- new->is_50hz);
+ if (old == NULL || old->is_50hz != new->is_50hz) {
+ err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz);
if (err) return err;
}
- if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
+ if (old == NULL || old->width != new->width || old->height != new->height ||
+ old->video_encoding != new->video_encoding) {
u16 w = new->width;
u16 h = new->height;
@@ -824,74 +795,69 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func,
w /= 2;
h /= 2;
}
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
- h, w);
+ err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
if (err) return err;
}
if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
- /* Adjust temporal filter if necessary. The problem with the
- temporal filter is that it works well with full resolution
- capturing, but not when the capture window is scaled (the
- filter introduces a ghosting effect). So if the capture
- window is scaled, then force the filter to 0.
+ /* Adjust temporal filter if necessary. The problem with the temporal
+ filter is that it works well with full resolution capturing, but
+ not when the capture window is scaled (the filter introduces
+ a ghosting effect). So if the capture window is scaled, then
+ force the filter to 0.
For full resolution the filter really improves the video
- quality, especially if the original video quality is
- suboptimal. */
+ quality, especially if the original video quality is suboptimal. */
temporal = 0;
}
- if (force || NEQ(stream_type)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
- mpeg_stream_type[new->stream_type]);
+ if (old == NULL || old->stream_type != new->stream_type) {
+ err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]);
if (err) return err;
}
- if (force || NEQ(video_aspect)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
- 1 + new->video_aspect);
+ if (old == NULL || old->video_aspect != new->video_aspect) {
+ err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect);
if (err) return err;
}
- if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
+ if (old == NULL || old->video_b_frames != new->video_b_frames ||
+ old->video_gop_size != new->video_gop_size) {
err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
new->video_gop_size, new->video_b_frames + 1);
if (err) return err;
}
- if (force || NEQ(video_gop_closure)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
- new->video_gop_closure);
+ if (old == NULL || old->video_gop_closure != new->video_gop_closure) {
+ err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
if (err) return err;
}
- if (force || NEQ(audio_properties)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
- 1, new->audio_properties);
+ if (old == NULL || old->audio_properties != new->audio_properties) {
+ err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
if (err) return err;
}
- if (force || NEQ(audio_mute)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
- new->audio_mute);
+ if (old == NULL || old->audio_mute != new->audio_mute) {
+ err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1, new->audio_mute);
if (err) return err;
}
- if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
- NEQ(video_bitrate_peak)) {
+ if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode ||
+ old->video_bitrate != new->video_bitrate ||
+ old->video_bitrate_peak != new->video_bitrate_peak) {
err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
new->video_bitrate_mode, new->video_bitrate,
new->video_bitrate_peak / 400, 0, 0);
if (err) return err;
}
- if (force || NEQ(video_spatial_filter_mode) ||
- NEQ(video_temporal_filter_mode) ||
- NEQ(video_median_filter_type)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
- 2, new->video_spatial_filter_mode |
- (new->video_temporal_filter_mode << 1),
+ if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode ||
+ old->video_temporal_filter_mode != new->video_temporal_filter_mode ||
+ old->video_median_filter_type != new->video_median_filter_type) {
+ err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
+ new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1),
new->video_median_filter_type);
if (err) return err;
}
- if (force || NEQ(video_luma_median_filter_bottom) ||
- NEQ(video_luma_median_filter_top) ||
- NEQ(video_chroma_median_filter_bottom) ||
- NEQ(video_chroma_median_filter_top)) {
+ if (old == NULL ||
+ old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom ||
+ old->video_luma_median_filter_top != new->video_luma_median_filter_top ||
+ old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom ||
+ old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) {
err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
new->video_luma_median_filter_bottom,
new->video_luma_median_filter_top,
@@ -899,39 +865,36 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func,
new->video_chroma_median_filter_top);
if (err) return err;
}
- if (force || NEQ(video_luma_spatial_filter_type) ||
- NEQ(video_chroma_spatial_filter_type)) {
- err = cx2341x_api(priv, func,
- CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
- 2, new->video_luma_spatial_filter_type,
- new->video_chroma_spatial_filter_type);
+ if (old == NULL ||
+ old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type ||
+ old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) {
+ err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
+ new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type);
if (err) return err;
}
- if (force || NEQ(video_spatial_filter) ||
- old->video_temporal_filter != temporal) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
- 2, new->video_spatial_filter, temporal);
+ if (old == NULL ||
+ old->video_spatial_filter != new->video_spatial_filter ||
+ old->video_temporal_filter != temporal) {
+ err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
+ new->video_spatial_filter, temporal);
if (err) return err;
}
- if (force || NEQ(video_temporal_decimation)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
- 1, new->video_temporal_decimation);
+ if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) {
+ err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1,
+ new->video_temporal_decimation);
if (err) return err;
}
- if (force || NEQ(video_mute) ||
- (new->video_mute && NEQ(video_mute_yuv))) {
- err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
- new->video_mute | (new->video_mute_yuv << 8));
+ if (old == NULL || old->video_mute != new->video_mute ||
+ (new->video_mute && old->video_mute_yuv != new->video_mute_yuv)) {
+ err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1, new->video_mute | (new->video_mute_yuv << 8));
if (err) return err;
}
- if (force || NEQ(stream_insert_nav_packets)) {
- err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
- 7, new->stream_insert_nav_packets);
+ if (old == NULL || old->stream_insert_nav_packets != new->stream_insert_nav_packets) {
+ err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2, 7, new->stream_insert_nav_packets);
if (err) return err;
}
return 0;
}
-EXPORT_SYMBOL(cx2341x_update);
static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
{
@@ -980,17 +943,18 @@ void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
p->video_bitrate);
- if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
+ if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
printk(", Peak %d", p->video_bitrate_peak);
+ }
printk("\n");
- printk(KERN_INFO
- "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
+ printk(KERN_INFO "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
prefix,
p->video_gop_size, p->video_b_frames,
p->video_gop_closure ? "" : "No ");
- if (p->video_temporal_decimation)
+ if (p->video_temporal_decimation) {
printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
prefix, p->video_temporal_decimation);
+ }
/* Audio */
printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s",
@@ -1000,9 +964,10 @@ void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
p->audio_mute ? " (muted)" : "");
- if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
- printk(", %s", cx2341x_menu_item(p,
- V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
+ if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) {
+ printk(", %s",
+ cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
+ }
printk(", %s, %s\n",
cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
@@ -1010,33 +975,33 @@ void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
/* Encoding filters */
printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
prefix,
- cx2341x_menu_item(p,
- V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
- cx2341x_menu_item(p,
- V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
- cx2341x_menu_item(p,
- V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
+ cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
+ cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
+ cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
p->video_spatial_filter);
-
- if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
+ if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480)) {
temporal = 0;
-
+ }
printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
prefix,
- cx2341x_menu_item(p,
- V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
+ cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
temporal);
- printk(KERN_INFO
- "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
+ printk(KERN_INFO "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
prefix,
- cx2341x_menu_item(p,
- V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
+ cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
p->video_luma_median_filter_bottom,
p->video_luma_median_filter_top,
p->video_chroma_median_filter_bottom,
p->video_chroma_median_filter_top);
}
+
+EXPORT_SYMBOL(cx2341x_fill_defaults);
+EXPORT_SYMBOL(cx2341x_ctrl_query);
+EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
+EXPORT_SYMBOL(cx2341x_ext_ctrls);
+EXPORT_SYMBOL(cx2341x_update);
EXPORT_SYMBOL(cx2341x_log_status);
+EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
/*
* Local variables:
diff --git a/trunk/drivers/media/video/cx23885/Kconfig b/trunk/drivers/media/video/cx23885/Kconfig
index 1fd326fe4113..081ee6e1536f 100644
--- a/trunk/drivers/media/video/cx23885/Kconfig
+++ b/trunk/drivers/media/video/cx23885/Kconfig
@@ -12,10 +12,6 @@ config VIDEO_CX23885
select DVB_S5H1409 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
select DVB_PLL if !DVB_FE_CUSTOMISE
- select TUNER_XC2028 if !DVB_FE_CUSTOMIZE
- select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
- select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
- select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
---help---
This is a video4linux driver for Conexant 23885 based
TV cards.
diff --git a/trunk/drivers/media/video/cx23885/Makefile b/trunk/drivers/media/video/cx23885/Makefile
index 32c90be50602..665067022d2a 100644
--- a/trunk/drivers/media/video/cx23885/Makefile
+++ b/trunk/drivers/media/video/cx23885/Makefile
@@ -1,4 +1,4 @@
-cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o
+cx23885-objs := cx23885-cards.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o
obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
diff --git a/trunk/drivers/media/video/cx23885/cx23885-cards.c b/trunk/drivers/media/video/cx23885/cx23885-cards.c
index 2d414dad5c31..b9012acabb2f 100644
--- a/trunk/drivers/media/video/cx23885/cx23885-cards.c
+++ b/trunk/drivers/media/video/cx23885/cx23885-cards.c
@@ -23,7 +23,6 @@
#include
#include
#include
-#include
#include "cx23885.h"
@@ -33,8 +32,6 @@
struct cx23885_board cx23885_boards[] = {
[CX23885_BOARD_UNKNOWN] = {
.name = "UNKNOWN/GENERIC",
- /* Ensure safe default for unknown boards */
- .clk_freq = 0,
.input = {{
.type = CX23885_VMUX_COMPOSITE1,
.vmux = 0,
@@ -72,29 +69,23 @@ struct cx23885_board cx23885_boards[] = {
},
[CX23885_BOARD_HAUPPAUGE_HVR1800] = {
.name = "Hauppauge WinTV-HVR1800",
- .porta = CX23885_ANALOG_VIDEO,
.portc = CX23885_MPEG_DVB,
- .tuner_type = TUNER_PHILIPS_TDA8290,
- .tuner_addr = 0x42, /* 0x84 >> 1 */
.input = {{
.type = CX23885_VMUX_TELEVISION,
- .vmux = CX25840_VIN7_CH3 |
- CX25840_VIN5_CH2 |
- CX25840_VIN2_CH1,
- .gpio0 = 0,
+ .vmux = 0,
+ .gpio0 = 0xff00,
+ },{
+ .type = CX23885_VMUX_DEBUG,
+ .vmux = 0,
+ .gpio0 = 0xff01,
},{
.type = CX23885_VMUX_COMPOSITE1,
- .vmux = CX25840_VIN7_CH3 |
- CX25840_VIN4_CH2 |
- CX25840_VIN6_CH1,
- .gpio0 = 0,
+ .vmux = 1,
+ .gpio0 = 0xff02,
},{
.type = CX23885_VMUX_SVIDEO,
- .vmux = CX25840_VIN7_CH3 |
- CX25840_VIN4_CH2 |
- CX25840_VIN8_CH1 |
- CX25840_SVIDEO_ON,
- .gpio0 = 0,
+ .vmux = 2,
+ .gpio0 = 0xff02,
}},
},
[CX23885_BOARD_HAUPPAUGE_HVR1250] = {
@@ -122,14 +113,6 @@ struct cx23885_board cx23885_boards[] = {
.name = "DViCO FusionHDTV5 Express",
.portb = CX23885_MPEG_DVB,
},
- [CX23885_BOARD_HAUPPAUGE_HVR1500Q] = {
- .name = "Hauppauge WinTV-HVR1500Q",
- .portc = CX23885_MPEG_DVB,
- },
- [CX23885_BOARD_HAUPPAUGE_HVR1500] = {
- .name = "Hauppauge WinTV-HVR1500",
- .portc = CX23885_MPEG_DVB,
- },
};
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
@@ -153,10 +136,6 @@ struct cx23885_subid cx23885_subids[] = {
.subvendor = 0x0070,
.subdevice = 0x7801,
.card = CX23885_BOARD_HAUPPAUGE_HVR1800,
- },{
- .subvendor = 0x0070,
- .subdevice = 0x7809,
- .card = CX23885_BOARD_HAUPPAUGE_HVR1800,
},{
.subvendor = 0x0070,
.subdevice = 0x7911,
@@ -165,22 +144,6 @@ struct cx23885_subid cx23885_subids[] = {
.subvendor = 0x18ac,
.subdevice = 0xd500,
.card = CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP,
- },{
- .subvendor = 0x0070,
- .subdevice = 0x7790,
- .card = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
- },{
- .subvendor = 0x0070,
- .subdevice = 0x7797,
- .card = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
- },{
- .subvendor = 0x0070,
- .subdevice = 0x7710,
- .card = CX23885_BOARD_HAUPPAUGE_HVR1500,
- },{
- .subvendor = 0x0070,
- .subdevice = 0x7717,
- .card = CX23885_BOARD_HAUPPAUGE_HVR1500,
},
};
const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -221,19 +184,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
switch (tv.model)
{
case 76601: /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual channel ATSC and MPEG2 HW Encoder */
- case 77001: /* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC and Basic analog */
- case 77011: /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC and Basic analog */
- case 77041: /* WinTV-HVR1500Q (Express Card, OEM, No IR, ATSC/QAM and Basic analog */
- case 77051: /* WinTV-HVR1500Q (Express Card, Retail, No IR, ATSC/QAM and Basic analog */
- case 78011: /* WinTV-HVR1800 (PCIe, Retail, 3.5mm in, IR, No FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 78501: /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 78521: /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 78531: /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, No FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 78631: /* WinTV-HVR1800 (PCIe, OEM, No IR, No FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 79001: /* WinTV-HVR1250 (PCIe, Retail, IR, full height, ATSC and Basic analog */
- case 79101: /* WinTV-HVR1250 (PCIe, Retail, IR, half height, ATSC and Basic analog */
- case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */
- case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
+ case 77001: /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC and Basic analog */
+ case 78501: /* WinTV-HVR1800 (PCIe, Retail, IR, Dual channel ATSC and MPEG2 HW Encoder */
+ case 78521: /* WinTV-HVR1800 (PCIe, Retail, IR, Dual channel ATSC and MPEG2 HW Encoder */
break;
default:
printk("%s: warning: unknown hauppauge model #%d\n", dev->name, tv.model);
@@ -244,34 +197,6 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
dev->name, tv.model);
}
-/* Tuner callback function for cx23885 boards. Currently only needed
- * for HVR1500Q, which has an xc5000 tuner.
- */
-int cx23885_tuner_callback(void *priv, int command, int arg)
-{
- struct cx23885_i2c *bus = priv;
- struct cx23885_dev *dev = bus->dev;
-
- switch(dev->board) {
- case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
- if(command == 0) { /* Tuner Reset Command from xc5000 */
- /* Drive the tuner into reset and out */
- cx_clear(GP0_IO, 0x00000004);
- mdelay(200);
- cx_set(GP0_IO, 0x00000004);
- return 0;
- }
- else {
- printk(KERN_ERR
- "%s(): Unknow command.\n", __FUNCTION__);
- return -EINVAL;
- }
- break;
- }
-
- return 0; /* Should never be here */
-}
-
void cx23885_gpio_setup(struct cx23885_dev *dev)
{
switch(dev->board) {
@@ -279,23 +204,6 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
/* GPIO-0 cx24227 demodulator reset */
cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */
break;
- case CX23885_BOARD_HAUPPAUGE_HVR1500:
- /* GPIO-0 cx24227 demodulator */
- /* GPIO-2 xc3028 tuner */
-
- /* Put the parts into reset */
- cx_set(GP0_IO, 0x00050000);
- cx_clear(GP0_IO, 0x00000005);
- msleep(5);
-
- /* Bring the parts out of reset */
- cx_set(GP0_IO, 0x00050005);
- break;
- case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
- /* GPIO-0 cx24227 demodulator reset */
- /* GPIO-2 xc5000 tuner reset */
- cx_set(GP0_IO, 0x00050005); /* Bring the part out of reset */
- break;
case CX23885_BOARD_HAUPPAUGE_HVR1800:
/* GPIO-0 656_CLK */
/* GPIO-1 656_D0 */
@@ -304,14 +212,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
/* GPIO-11-14 cx23417 addr0-3 */
/* GPIO-15-18 cx23417 READY, CS, RD, WR */
/* GPIO-19 IR_RX */
-
- /* Force the TDA8295A into reset and back */
- cx_set(GP0_IO, 0x00040004);
- mdelay(20);
- cx_clear(GP0_IO, 0x00000004);
- mdelay(20);
- cx_set(GP0_IO, 0x00040004);
- mdelay(20);
+ // FIXME: Analog requires the tuner is brought out of reset
break;
}
}
@@ -320,8 +221,6 @@ int cx23885_ir_init(struct cx23885_dev *dev)
{
switch (dev->board) {
case CX23885_BOARD_HAUPPAUGE_HVR1250:
- case CX23885_BOARD_HAUPPAUGE_HVR1500:
- case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
case CX23885_BOARD_HAUPPAUGE_HVR1800:
/* FIXME: Implement me */
break;
@@ -345,8 +244,6 @@ void cx23885_card_setup(struct cx23885_dev *dev)
switch (dev->board) {
case CX23885_BOARD_HAUPPAUGE_HVR1250:
- case CX23885_BOARD_HAUPPAUGE_HVR1500:
- case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
case CX23885_BOARD_HAUPPAUGE_HVR1800:
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
if (dev->i2c_bus[0].i2c_rc == 0)
@@ -361,8 +258,6 @@ void cx23885_card_setup(struct cx23885_dev *dev)
ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
break;
case CX23885_BOARD_HAUPPAUGE_HVR1250:
- case CX23885_BOARD_HAUPPAUGE_HVR1500:
- case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
case CX23885_BOARD_HAUPPAUGE_HVR1800:
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
default:
@@ -375,6 +270,8 @@ void cx23885_card_setup(struct cx23885_dev *dev)
/* ------------------------------------------------------------------ */
+EXPORT_SYMBOL(cx23885_boards);
+
/*
* Local variables:
* c-basic-offset: 8
diff --git a/trunk/drivers/media/video/cx23885/cx23885-core.c b/trunk/drivers/media/video/cx23885/cx23885-core.c
index 8e40c7bcc06d..3cdd136477e5 100644
--- a/trunk/drivers/media/video/cx23885/cx23885-core.c
+++ b/trunk/drivers/media/video/cx23885/cx23885-core.c
@@ -36,7 +36,7 @@ MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
MODULE_AUTHOR("Steven Toth ");
MODULE_LICENSE("GPL");
-static unsigned int debug;
+static unsigned int debug = 0;
module_param(debug,int,0644);
MODULE_PARM_DESC(debug,"enable debug messages");
@@ -44,15 +44,13 @@ static unsigned int card[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(card,"card type");
-#define dprintk(level, fmt, arg...)\
- do { if (debug >= level)\
- printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
- } while (0)
+#define dprintk(level,fmt, arg...) if (debug >= level) \
+ printk(KERN_DEBUG "%s/0: " fmt, dev->name , ## arg)
static unsigned int cx23885_devcount;
static DEFINE_MUTEX(devlist);
-LIST_HEAD(cx23885_devlist);
+static LIST_HEAD(cx23885_devlist);
#define NO_SYNC_LINE (-1U)
@@ -75,14 +73,14 @@ LIST_HEAD(cx23885_devlist);
* 0x00010ea0 0x00010xxx Free
*/
-static struct sram_channel cx23885_sram_channels[] = {
+struct sram_channel cx23885_sram_channels[] = {
[SRAM_CH01] = {
- .name = "VID A",
+ .name = "test ch1",
.cmds_start = 0x10000,
- .ctrl_start = 0x105b0,
- .cdt = 0x107b0,
- .fifo_start = 0x40,
- .fifo_size = 0x2800,
+ .ctrl_start = 0x10500,
+ .cdt = 0x10900,
+ .fifo_start = 0x3000,
+ .fifo_size = 0x1000,
.ptr1_reg = DMA1_PTR1,
.ptr2_reg = DMA1_PTR2,
.cnt1_reg = DMA1_CNT1,
@@ -104,8 +102,8 @@ static struct sram_channel cx23885_sram_channels[] = {
[SRAM_CH03] = {
.name = "TS1 B",
.cmds_start = 0x100A0,
- .ctrl_start = 0x10630,
- .cdt = 0x10870,
+ .ctrl_start = 0x10780,
+ .cdt = 0x10400,
.fifo_start = 0x5000,
.fifo_size = 0x1000,
.ptr1_reg = DMA3_PTR1,
@@ -141,7 +139,7 @@ static struct sram_channel cx23885_sram_channels[] = {
.name = "TS2 C",
.cmds_start = 0x10140,
.ctrl_start = 0x10680,
- .cdt = 0x108d0,
+ .cdt = 0x10480,
.fifo_start = 0x6000,
.fifo_size = 0x1000,
.ptr1_reg = DMA5_PTR1,
@@ -207,14 +205,14 @@ static struct sram_channel cx23885_sram_channels[] = {
* 0x00010ea0 0x00010xxx Free
*/
-static struct sram_channel cx23887_sram_channels[] = {
+struct sram_channel cx23887_sram_channels[] = {
[SRAM_CH01] = {
- .name = "VID A",
- .cmds_start = 0x10000,
- .ctrl_start = 0x105b0,
- .cdt = 0x107b0,
- .fifo_start = 0x40,
- .fifo_size = 0x2800,
+ .name = "test ch1",
+ .cmds_start = 0x0,
+ .ctrl_start = 0x0,
+ .cdt = 0x0,
+ .fifo_start = 0x0,
+ .fifo_size = 0x0,
.ptr1_reg = DMA1_PTR1,
.ptr2_reg = DMA1_PTR2,
.cnt1_reg = DMA1_CNT1,
@@ -233,12 +231,12 @@ static struct sram_channel cx23887_sram_channels[] = {
.cnt2_reg = DMA2_CNT2,
},
[SRAM_CH03] = {
- .name = "TS1 B",
- .cmds_start = 0x100A0,
- .ctrl_start = 0x10780,
- .cdt = 0x10400,
- .fifo_start = 0x5000,
- .fifo_size = 0x1000,
+ .name = "ch3",
+ .cmds_start = 0x0,
+ .ctrl_start = 0x0,
+ .cdt = 0x0,
+ .fifo_start = 0x0,
+ .fifo_size = 0x0,
.ptr1_reg = DMA3_PTR1,
.ptr2_reg = DMA3_PTR2,
.cnt1_reg = DMA3_CNT1,
@@ -359,7 +357,7 @@ static int cx23885_risc_decode(u32 risc)
}
void cx23885_wakeup(struct cx23885_tsport *port,
- struct cx23885_dmaqueue *q, u32 count)
+ struct cx23885_dmaqueue *q, u32 count)
{
struct cx23885_dev *dev = port->dev;
struct cx23885_buffer *buf;
@@ -380,7 +378,7 @@ void cx23885_wakeup(struct cx23885_tsport *port,
do_gettimeofday(&buf->vb.ts);
dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i,
count, buf->count);
- buf->vb.state = VIDEOBUF_DONE;
+ buf->vb.state = STATE_DONE;
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
}
@@ -393,10 +391,12 @@ void cx23885_wakeup(struct cx23885_tsport *port,
printk("%s: %d buffers handled (should be 1)\n",
__FUNCTION__, bc);
}
+void cx23885_sram_channel_dump(struct cx23885_dev *dev,
+ struct sram_channel *ch);
int cx23885_sram_channel_setup(struct cx23885_dev *dev,
- struct sram_channel *ch,
- unsigned int bpl, u32 risc)
+ struct sram_channel *ch,
+ unsigned int bpl, u32 risc)
{
unsigned int i, lines;
u32 cdt;
@@ -468,7 +468,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
}
void cx23885_sram_channel_dump(struct cx23885_dev *dev,
- struct sram_channel *ch)
+ struct sram_channel *ch)
{
static char *name[] = {
"init risc lo",
@@ -529,8 +529,8 @@ void cx23885_sram_channel_dump(struct cx23885_dev *dev,
dev->name, cx_read(ch->cnt2_reg));
}
-static void cx23885_risc_disasm(struct cx23885_tsport *port,
- struct btcx_riscmem *risc)
+void cx23885_risc_disasm(struct cx23885_tsport *port,
+ struct btcx_riscmem *risc)
{
struct cx23885_dev *dev = port->dev;
unsigned int i, j, n;
@@ -548,7 +548,7 @@ static void cx23885_risc_disasm(struct cx23885_tsport *port,
}
}
-static void cx23885_shutdown(struct cx23885_dev *dev)
+void cx23885_shutdown(struct cx23885_dev *dev)
{
/* disable RISC controller */
cx_write(DEV_CNTRL2, 0);
@@ -578,7 +578,7 @@ static void cx23885_shutdown(struct cx23885_dev *dev)
}
-static void cx23885_reset(struct cx23885_dev *dev)
+void cx23885_reset(struct cx23885_dev *dev)
{
dprintk(1, "%s()\n", __FUNCTION__);
@@ -594,18 +594,15 @@ static void cx23885_reset(struct cx23885_dev *dev)
mdelay(100);
- cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
- 720*4, 0);
- cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02], 128, 0);
- cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH03],
- 188*4, 0);
- cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH04], 128, 0);
- cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH05], 128, 0);
- cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH06],
- 188*4, 0);
- cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH07], 128, 0);
- cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH08], 128, 0);
- cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH09], 128, 0);
+ cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH01 ], 188*4, 0);
+ cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH02 ], 128, 0);
+ cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH03 ], 188*4, 0);
+ cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH04 ], 128, 0);
+ cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH05 ], 128, 0);
+ cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH06 ], 188*4, 0);
+ cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH07 ], 128, 0);
+ cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH08 ], 128, 0);
+ cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH09 ], 128, 0);
cx23885_gpio_setup(dev);
}
@@ -640,7 +637,7 @@ static int get_resources(struct cx23885_dev *dev)
static void cx23885_timeout(unsigned long data);
int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
- u32 reg, u32 mask, u32 value);
+ u32 reg, u32 mask, u32 value);
static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno)
{
@@ -707,44 +704,6 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p
return 0;
}
-static void cx23885_dev_checkrevision(struct cx23885_dev *dev)
-{
- switch (cx_read(RDR_CFG2) & 0xff) {
- case 0x00:
- /* cx23885 */
- dev->hwrevision = 0xa0;
- break;
- case 0x01:
- /* CX23885-12Z */
- dev->hwrevision = 0xa1;
- break;
- case 0x02:
- /* CX23885-13Z */
- dev->hwrevision = 0xb0;
- break;
- case 0x03:
- /* CX23888-22Z */
- dev->hwrevision = 0xc0;
- break;
- case 0x0e:
- /* CX23887-15Z */
- dev->hwrevision = 0xc0;
- case 0x0f:
- /* CX23887-14Z */
- dev->hwrevision = 0xb1;
- break;
- default:
- printk(KERN_ERR "%s() New hardware revision found 0x%x\n",
- __FUNCTION__, dev->hwrevision);
- }
- if (dev->hwrevision)
- printk(KERN_INFO "%s() Hardware revision = 0x%02x\n",
- __FUNCTION__, dev->hwrevision);
- else
- printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n",
- __FUNCTION__, dev->hwrevision);
-}
-
static int cx23885_dev_setup(struct cx23885_dev *dev)
{
int i;
@@ -764,14 +723,10 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
if(dev->pci->device == 0x8880) {
dev->bridge = CX23885_BRIDGE_887;
dev->sram_channels = cx23887_sram_channels;
- /* Apply a sensible clock frequency for the PCIe bridge */
- dev->clk_freq = 25000000;
} else
if(dev->pci->device == 0x8852) {
dev->bridge = CX23885_BRIDGE_885;
dev->sram_channels = cx23885_sram_channels;
- /* Apply a sensible clock frequency for the PCIe bridge */
- dev->clk_freq = 28000000;
} else
BUG();
@@ -791,10 +746,6 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
cx23885_card_list(dev);
}
- /* If the user specific a clk freq override, apply it */
- if (cx23885_boards[dev->board].clk_freq > 0)
- dev->clk_freq = cx23885_boards[dev->board].clk_freq;
-
dev->pci_bus = dev->pci->bus->number;
dev->pci_slot = PCI_SLOT(dev->pci->devfn);
dev->pci_irqmask = 0x001f00;
@@ -859,17 +810,6 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
cx23885_pci_quirks(dev);
- /* Assume some sensible defaults */
- dev->tuner_type = cx23885_boards[dev->board].tuner_type;
- dev->tuner_addr = cx23885_boards[dev->board].tuner_addr;
- dev->radio_type = cx23885_boards[dev->board].radio_type;
- dev->radio_addr = cx23885_boards[dev->board].radio_addr;
-
- dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x\n",
- __FUNCTION__, dev->tuner_type, dev->tuner_addr);
- dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n",
- __FUNCTION__, dev->radio_type, dev->radio_addr);
-
/* init hardware */
cx23885_reset(dev);
@@ -880,33 +820,24 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
cx23885_card_setup(dev);
cx23885_ir_init(dev);
- if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
- if (cx23885_video_register(dev) < 0) {
- printk(KERN_ERR "%s() Failed to register analog "
- "video adapters on VID_A\n", __FUNCTION__);
- }
- }
-
- if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
+ if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
if (cx23885_dvb_register(&dev->ts1) < 0) {
printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
__FUNCTION__);
}
}
- if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
+ if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
if (cx23885_dvb_register(&dev->ts2) < 0) {
printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n",
__FUNCTION__);
}
}
- cx23885_dev_checkrevision(dev);
-
return 0;
}
-static void cx23885_dev_unregister(struct cx23885_dev *dev)
+void cx23885_dev_unregister(struct cx23885_dev *dev)
{
release_mem_region(pci_resource_start(dev->pci,0),
pci_resource_len(dev->pci,0));
@@ -914,9 +845,6 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
if (!atomic_dec_and_test(&dev->refcount))
return;
- if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO)
- cx23885_video_unregister(dev);
-
if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
cx23885_dvb_unregister(&dev->ts1);
@@ -1024,11 +952,9 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
return 0;
}
-static int cx23885_risc_databuffer(struct pci_dev *pci,
- struct btcx_riscmem *risc,
- struct scatterlist *sglist,
- unsigned int bpl,
- unsigned int lines)
+int cx23885_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+ struct scatterlist *sglist, unsigned int bpl,
+ unsigned int lines)
{
u32 instructions;
u32 *rp;
@@ -1056,7 +982,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
}
int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
- u32 reg, u32 mask, u32 value)
+ u32 reg, u32 mask, u32 value)
{
u32 *rp;
int rc;
@@ -1085,58 +1011,7 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf)
videobuf_dma_unmap(q, dma);
videobuf_dma_free(dma);
btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
- buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
-{
- struct cx23885_dev *dev = port->dev;
-
- dprintk(1, "%s() Register Dump\n", __FUNCTION__);
- dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __FUNCTION__,
- cx_read(DEV_CNTRL2));
- dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __FUNCTION__,
- cx_read(PCI_INT_MSK));
- dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __FUNCTION__,
- cx_read(AUDIO_INT_INT_MSK));
- dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __FUNCTION__,
- cx_read(AUD_INT_DMA_CTL));
- dprintk(1, "%s() AUD_EXT_INT_MSK 0x%08X\n", __FUNCTION__,
- cx_read(AUDIO_EXT_INT_MSK));
- dprintk(1, "%s() AUD_EXT_DMA_CTL 0x%08X\n", __FUNCTION__,
- cx_read(AUD_EXT_DMA_CTL));
- dprintk(1, "%s() PAD_CTRL 0x%08X\n", __FUNCTION__,
- cx_read(PAD_CTRL));
- dprintk(1, "%s() ALT_PIN_OUT_SEL 0x%08X\n", __FUNCTION__,
- cx_read(ALT_PIN_OUT_SEL));
- dprintk(1, "%s() GPIO2 0x%08X\n", __FUNCTION__,
- cx_read(GPIO2));
- dprintk(1, "%s() gpcnt(0x%08X) 0x%08X\n", __FUNCTION__,
- port->reg_gpcnt, cx_read(port->reg_gpcnt));
- dprintk(1, "%s() gpcnt_ctl(0x%08X) 0x%08x\n", __FUNCTION__,
- port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl));
- dprintk(1, "%s() dma_ctl(0x%08X) 0x%08x\n", __FUNCTION__,
- port->reg_dma_ctl, cx_read(port->reg_dma_ctl));
- dprintk(1, "%s() src_sel(0x%08X) 0x%08x\n", __FUNCTION__,
- port->reg_src_sel, cx_read(port->reg_src_sel));
- dprintk(1, "%s() lngth(0x%08X) 0x%08x\n", __FUNCTION__,
- port->reg_lngth, cx_read(port->reg_lngth));
- dprintk(1, "%s() hw_sop_ctrl(0x%08X) 0x%08x\n", __FUNCTION__,
- port->reg_hw_sop_ctrl, cx_read(port->reg_hw_sop_ctrl));
- dprintk(1, "%s() gen_ctrl(0x%08X) 0x%08x\n", __FUNCTION__,
- port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl));
- dprintk(1, "%s() bd_pkt_status(0x%08X) 0x%08x\n", __FUNCTION__,
- port->reg_bd_pkt_status, cx_read(port->reg_bd_pkt_status));
- dprintk(1, "%s() sop_status(0x%08X) 0x%08x\n", __FUNCTION__,
- port->reg_sop_status, cx_read(port->reg_sop_status));
- dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __FUNCTION__,
- port->reg_fifo_ovfl_stat, cx_read(port->reg_fifo_ovfl_stat));
- dprintk(1, "%s() vld_misc(0x%08X) 0x%08x\n", __FUNCTION__,
- port->reg_vld_misc, cx_read(port->reg_vld_misc));
- dprintk(1, "%s() ts_clk_en(0x%08X) 0x%08x\n", __FUNCTION__,
- port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en));
- dprintk(1, "%s() ts_int_msk(0x%08X) 0x%08x\n", __FUNCTION__,
- port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk));
+ buf->vb.state = STATE_NEEDS_INIT;
}
static int cx23885_start_dma(struct cx23885_tsport *port,
@@ -1201,9 +1076,6 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */
- if (debug > 4)
- cx23885_tsport_reg_dump(port);
-
return 0;
}
@@ -1219,7 +1091,7 @@ static int cx23885_stop_dma(struct cx23885_tsport *port)
return 0;
}
-int cx23885_restart_queue(struct cx23885_tsport *port,
+static int cx23885_restart_queue(struct cx23885_tsport *port,
struct cx23885_dmaqueue *q)
{
struct cx23885_dev *dev = port->dev;
@@ -1242,7 +1114,7 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
list_del(&buf->vb.queue);
list_add_tail(&buf->vb.queue, &q->active);
cx23885_start_dma(port, q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(5, "[%p/%d] restart_queue - first active\n",
@@ -1253,7 +1125,7 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
prev->fmt == buf->fmt) {
list_del(&buf->vb.queue);
list_add_tail(&buf->vb.queue, &q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
@@ -1290,7 +1162,7 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
if (0 != buf->vb.baddr && buf->vb.bsize < size)
return -EINVAL;
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ if (STATE_NEEDS_INIT == buf->vb.state) {
buf->vb.width = port->ts_packet_size;
buf->vb.height = port->ts_packet_count;
buf->vb.size = size;
@@ -1302,7 +1174,7 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
videobuf_to_dma(&buf->vb)->sglist,
buf->vb.width, buf->vb.height);
}
- buf->vb.state = VIDEOBUF_PREPARED;
+ buf->vb.state = STATE_PREPARED;
return 0;
fail:
@@ -1325,7 +1197,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
dprintk( 1, "queue is empty - first active\n" );
list_add_tail(&buf->vb.queue, &cx88q->active);
cx23885_start_dma(port, cx88q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = cx88q->count++;
mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT);
dprintk(1, "[%p/%d] %s - first active\n",
@@ -1335,7 +1207,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
vb.queue);
list_add_tail(&buf->vb.queue, &cx88q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = cx88q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
@@ -1359,7 +1231,7 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
buf = list_entry(q->active.next, struct cx23885_buffer,
vb.queue);
list_del(&buf->vb.queue);
- buf->vb.state = VIDEOBUF_ERROR;
+ buf->vb.state = STATE_ERROR;
wake_up(&buf->vb.done);
dprintk(1, "[%p/%d] %s - dma=0x%08lx\n",
buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
@@ -1371,6 +1243,16 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
spin_unlock_irqrestore(&port->slock, flags);
}
+void cx23885_cancel_buffers(struct cx23885_tsport *port)
+{
+ struct cx23885_dev *dev = port->dev;
+ struct cx23885_dmaqueue *q = &port->mpegq;
+
+ dprintk(1, "%s()\n", __FUNCTION__);
+ del_timer_sync(&q->timeout);
+ cx23885_stop_dma(port);
+ do_cancel_buffers(port, "cancel", 0);
+}
static void cx23885_timeout(unsigned long data)
{
@@ -1443,15 +1325,12 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
struct cx23885_tsport *ts1 = &dev->ts1;
struct cx23885_tsport *ts2 = &dev->ts2;
u32 pci_status, pci_mask;
- u32 vida_status, vida_mask;
u32 ts1_status, ts1_mask;
u32 ts2_status, ts2_mask;
- int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
+ int ts1_count = 0, ts2_count = 0, handled = 0;
pci_status = cx_read(PCI_INT_STAT);
pci_mask = cx_read(PCI_INT_MSK);
- vida_status = cx_read(VID_A_INT_STAT);
- vida_mask = cx_read(VID_A_INT_MSK);
ts1_status = cx_read(VID_B_INT_STAT);
ts1_mask = cx_read(VID_B_INT_MSK);
ts2_status = cx_read(VID_C_INT_STAT);
@@ -1460,17 +1339,11 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
if ( (pci_status == 0) && (ts2_status == 0) && (ts1_status == 0) )
goto out;
- vida_count = cx_read(VID_A_GPCNT);
ts1_count = cx_read(ts1->reg_gpcnt);
ts2_count = cx_read(ts2->reg_gpcnt);
- dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n",
- pci_status, pci_mask);
- dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n",
- vida_status, vida_mask, vida_count);
- dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n",
- ts1_status, ts1_mask, ts1_count);
- dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n",
- ts2_status, ts2_mask, ts2_count);
+ dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n", pci_status, pci_mask );
+ dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n", ts1_status, ts1_mask, ts1_count );
+ dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", ts2_status, ts2_mask, ts2_count );
if ( (pci_status & PCI_MSK_RISC_RD) ||
(pci_status & PCI_MSK_RISC_WR) ||
@@ -1507,18 +1380,11 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
}
- if (ts1_status) {
- if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
- handled += cx23885_irq_ts(ts1, ts1_status);
- }
-
- if (ts2_status) {
- if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
- handled += cx23885_irq_ts(ts2, ts2_status);
- }
+ if (ts1_status)
+ handled += cx23885_irq_ts(ts1, ts1_status);
- if (vida_status)
- handled += cx23885_video_irq(dev, vida_status);
+ if (ts2_status)
+ handled += cx23885_irq_ts(ts2, ts2_status);
if (handled)
cx_write(PCI_INT_STAT, pci_status);
diff --git a/trunk/drivers/media/video/cx23885/cx23885-dvb.c b/trunk/drivers/media/video/cx23885/cx23885-dvb.c
index ed465c007cea..eda8c05d0931 100644
--- a/trunk/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/trunk/drivers/media/video/cx23885/cx23885-dvb.c
@@ -32,26 +32,13 @@
#include "s5h1409.h"
#include "mt2131.h"
-#include "tda8290.h"
-#include "tda18271.h"
#include "lgdt330x.h"
-#include "xc5000.h"
#include "dvb-pll.h"
-#include "tuner-xc2028.h"
-#include "tuner-xc2028-types.h"
-static unsigned int debug;
+static unsigned int debug = 0;
-#define dprintk(level, fmt, arg...)\
- do { if (debug >= level)\
- printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
- } while (0)
-
-/* ------------------------------------------------------------------ */
-
-static unsigned int alt_tuner;
-module_param(alt_tuner, int, 0644);
-MODULE_PARM_DESC(alt_tuner, "Enable alternate tuner configuration");
+#define dprintk(level,fmt, arg...) if (debug >= level) \
+ printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg)
/* ------------------------------------------------------------------ */
@@ -98,39 +85,18 @@ static struct s5h1409_config hauppauge_generic_config = {
.demod_address = 0x32 >> 1,
.output_mode = S5H1409_SERIAL_OUTPUT,
.gpio = S5H1409_GPIO_ON,
- .qam_if = 44000,
+ .if_freq = 44000,
.inversion = S5H1409_INVERSION_OFF,
- .status_mode = S5H1409_DEMODLOCKING,
- .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-static struct s5h1409_config hauppauge_ezqam_config = {
- .demod_address = 0x32 >> 1,
- .output_mode = S5H1409_SERIAL_OUTPUT,
- .gpio = S5H1409_GPIO_OFF,
- .qam_if = 4000,
- .inversion = S5H1409_INVERSION_ON,
- .status_mode = S5H1409_DEMODLOCKING,
- .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+ .status_mode = S5H1409_DEMODLOCKING
};
static struct s5h1409_config hauppauge_hvr1800lp_config = {
.demod_address = 0x32 >> 1,
.output_mode = S5H1409_SERIAL_OUTPUT,
.gpio = S5H1409_GPIO_OFF,
- .qam_if = 44000,
- .inversion = S5H1409_INVERSION_OFF,
- .status_mode = S5H1409_DEMODLOCKING,
- .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-static struct s5h1409_config hauppauge_hvr1500_config = {
- .demod_address = 0x32 >> 1,
- .output_mode = S5H1409_SERIAL_OUTPUT,
- .gpio = S5H1409_GPIO_OFF,
+ .if_freq = 44000,
.inversion = S5H1409_INVERSION_OFF,
- .status_mode = S5H1409_DEMODLOCKING,
- .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+ .status_mode = S5H1409_DEMODLOCKING
};
static struct mt2131_config hauppauge_generic_tunerconfig = {
@@ -143,66 +109,6 @@ static struct lgdt330x_config fusionhdtv_5_express = {
.serial_mpeg = 0x40,
};
-static struct s5h1409_config hauppauge_hvr1500q_config = {
- .demod_address = 0x32 >> 1,
- .output_mode = S5H1409_SERIAL_OUTPUT,
- .gpio = S5H1409_GPIO_ON,
- .qam_if = 44000,
- .inversion = S5H1409_INVERSION_OFF,
- .status_mode = S5H1409_DEMODLOCKING,
- .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-static struct xc5000_config hauppauge_hvr1500q_tunerconfig = {
- .i2c_address = 0x61,
- .if_khz = 5380,
- .tuner_callback = cx23885_tuner_callback
-};
-
-static struct tda829x_config tda829x_no_probe = {
- .probe_tuner = TDA829X_DONT_PROBE,
-};
-
-static struct tda18271_std_map hauppauge_tda18271_std_map = {
- .atsc_6 = { .if_freq = 5380, .std_bits = 0x1b },
- .qam_6 = { .if_freq = 4000, .std_bits = 0x18 },
-};
-
-static struct tda18271_config hauppauge_tda18271_config = {
- .std_map = &hauppauge_tda18271_std_map,
- .gate = TDA18271_GATE_ANALOG,
-};
-
-static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
-{
- struct cx23885_tsport *port = ptr;
- struct cx23885_dev *dev = port->dev;
-
- switch (command) {
- case XC2028_TUNER_RESET:
- /* Send the tuner in then out of reset */
- /* GPIO-2 xc3028 tuner */
- dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
-
- cx_set(GP0_IO, 0x00040000);
- cx_clear(GP0_IO, 0x00000004);
- msleep(5);
-
- cx_set(GP0_IO, 0x00040004);
- msleep(5);
- break;
- case XC2028_RESET_CLK:
- dprintk(1, "%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
- break;
- default:
- dprintk(1, "%s: unknown command %d, arg %d\n", __FUNCTION__,
- command, arg);
- return -EINVAL;
- }
-
- return 0;
-}
-
static int dvb_register(struct cx23885_tsport *port)
{
struct cx23885_dev *dev = port->dev;
@@ -214,6 +120,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* init frontend */
switch (dev->board) {
case CX23885_BOARD_HAUPPAUGE_HVR1250:
+ case CX23885_BOARD_HAUPPAUGE_HVR1800:
i2c_bus = &dev->i2c_bus[0];
port->dvb.frontend = dvb_attach(s5h1409_attach,
&hauppauge_generic_config,
@@ -224,36 +131,6 @@ static int dvb_register(struct cx23885_tsport *port)
&hauppauge_generic_tunerconfig, 0);
}
break;
- case CX23885_BOARD_HAUPPAUGE_HVR1800:
- i2c_bus = &dev->i2c_bus[0];
- switch (alt_tuner) {
- case 1:
- port->dvb.frontend =
- dvb_attach(s5h1409_attach,
- &hauppauge_ezqam_config,
- &i2c_bus->i2c_adap);
- if (port->dvb.frontend != NULL) {
- dvb_attach(tda829x_attach, port->dvb.frontend,
- &dev->i2c_bus[1].i2c_adap, 0x42,
- &tda829x_no_probe);
- dvb_attach(tda18271_attach, port->dvb.frontend,
- 0x60, &dev->i2c_bus[1].i2c_adap,
- &hauppauge_tda18271_config);
- }
- break;
- case 0:
- default:
- port->dvb.frontend =
- dvb_attach(s5h1409_attach,
- &hauppauge_generic_config,
- &i2c_bus->i2c_adap);
- if (port->dvb.frontend != NULL)
- dvb_attach(mt2131_attach, port->dvb.frontend,
- &i2c_bus->i2c_adap,
- &hauppauge_generic_tunerconfig, 0);
- break;
- }
- break;
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
i2c_bus = &dev->i2c_bus[0];
port->dvb.frontend = dvb_attach(s5h1409_attach,
@@ -275,43 +152,6 @@ static int dvb_register(struct cx23885_tsport *port)
&i2c_bus->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
}
break;
- case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
- i2c_bus = &dev->i2c_bus[1];
- port->dvb.frontend = dvb_attach(s5h1409_attach,
- &hauppauge_hvr1500q_config,
- &dev->i2c_bus[0].i2c_adap);
- if (port->dvb.frontend != NULL) {
- hauppauge_hvr1500q_tunerconfig.priv = i2c_bus;
- dvb_attach(xc5000_attach, port->dvb.frontend,
- &i2c_bus->i2c_adap,
- &hauppauge_hvr1500q_tunerconfig);
- }
- break;
- case CX23885_BOARD_HAUPPAUGE_HVR1500:
- i2c_bus = &dev->i2c_bus[1];
- port->dvb.frontend = dvb_attach(s5h1409_attach,
- &hauppauge_hvr1500_config,
- &dev->i2c_bus[0].i2c_adap);
- if (port->dvb.frontend != NULL) {
- struct dvb_frontend *fe;
- struct xc2028_config cfg = {
- .i2c_adap = &i2c_bus->i2c_adap,
- .i2c_addr = 0x61,
- .video_dev = port,
- .callback = cx23885_hvr1500_xc3028_callback,
- };
- static struct xc2028_ctrl ctl = {
- .fname = "xc3028-v27.fw",
- .max_len = 64,
- .scode_table = OREN538,
- };
-
- fe = dvb_attach(xc2028_attach,
- port->dvb.frontend, &cfg);
- if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
- fe->ops.tuner_ops.set_config(fe, &ctl);
- }
- break;
default:
printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
dev->name);
@@ -325,9 +165,6 @@ static int dvb_register(struct cx23885_tsport *port)
/* Put the analog decoder in standby to keep it quiet */
cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL);
- if (port->dvb.frontend->ops.analog_ops.standby)
- port->dvb.frontend->ops.analog_ops.standby(port->dvb.frontend);
-
/* register everything */
return videobuf_dvb_register(&port->dvb, THIS_MODULE, port,
&dev->pci->dev);
diff --git a/trunk/drivers/media/video/cx23885/cx23885-i2c.c b/trunk/drivers/media/video/cx23885/cx23885-i2c.c
index 92fe0bd37c84..71da528932df 100644
--- a/trunk/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/trunk/drivers/media/video/cx23885/cx23885-i2c.c
@@ -29,7 +29,7 @@
#include
-static unsigned int i2c_debug;
+static unsigned int i2c_debug = 0;
module_param(i2c_debug, int, 0644);
MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
@@ -37,10 +37,8 @@ static unsigned int i2c_scan = 0;
module_param(i2c_scan, int, 0444);
MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
-#define dprintk(level, fmt, arg...)\
- do { if (i2c_debug >= level)\
- printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
- } while (0)
+#define dprintk(level,fmt, arg...) if (i2c_debug >= level) \
+ printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg)
#define I2C_WAIT_DELAY 32
#define I2C_WAIT_RETRY 64
@@ -79,19 +77,14 @@ static int i2c_wait_done(struct i2c_adapter *i2c_adap)
}
static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
- const struct i2c_msg *msg, int joined_rlen)
+ const struct i2c_msg *msg, int last)
{
struct cx23885_i2c *bus = i2c_adap->algo_data;
struct cx23885_dev *dev = bus->dev;
u32 wdata, addr, ctrl;
int retval, cnt;
- if (joined_rlen)
- dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __FUNCTION__,
- msg->len, joined_rlen);
- else
- dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
-
+ dprintk(1, "%s()\n", __FUNCTION__);
/* Deal with i2c probe functions with zero payload */
if (msg->len == 0) {
cx_write(bus->reg_addr, msg->addr << 25);
@@ -113,8 +106,6 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
if (msg->len > 1)
ctrl |= I2C_NOSTOP | I2C_EXTEND;
- else if (joined_rlen)
- ctrl |= I2C_NOSTOP;
cx_write(bus->reg_addr, addr);
cx_write(bus->reg_wdata, wdata);
@@ -136,10 +127,8 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
wdata = msg->buf[cnt];
ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
- if (cnt < msg->len - 1)
+ if (cnt < msg->len-1 || !last)
ctrl |= I2C_NOSTOP | I2C_EXTEND;
- else if (joined_rlen)
- ctrl |= I2C_NOSTOP;
cx_write(bus->reg_addr, addr);
cx_write(bus->reg_wdata, wdata);
@@ -161,22 +150,19 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
eio:
retval = -EIO;
err:
- if (i2c_debug)
- printk(" ERR: %d\n", retval);
+ printk(" ERR: %d\n", retval);
return retval;
}
static int i2c_readbytes(struct i2c_adapter *i2c_adap,
- const struct i2c_msg *msg, int joined)
+ const struct i2c_msg *msg, int last)
{
struct cx23885_i2c *bus = i2c_adap->algo_data;
struct cx23885_dev *dev = bus->dev;
u32 ctrl, cnt;
int retval;
-
- if (i2c_debug && !joined)
- dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
+ dprintk(1, "%s()\n", __FUNCTION__);
/* Deal with i2c probe functions with zero payload */
if (msg->len == 0) {
@@ -192,18 +178,11 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
return 0;
}
- if (i2c_debug) {
- if (joined)
- printk(" R");
- else
- printk(" addr << 1) + 1);
- }
-
for(cnt = 0; cnt < msg->len; cnt++) {
ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
- if (cnt < msg->len - 1)
+ if (cnt < msg->len-1 || !last)
ctrl |= I2C_NOSTOP | I2C_EXTEND;
cx_write(bus->reg_addr, msg->addr << 25);
@@ -216,7 +195,9 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
goto eio;
msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
if (i2c_debug) {
- printk(" %02x", msg->buf[cnt]);
+ if (!(ctrl & I2C_NOSTOP))
+ printk(" addr << 1) +1);
+ printk(" =%02x", msg->buf[cnt]);
if (!(ctrl & I2C_NOSTOP))
printk(" >\n");
}
@@ -226,8 +207,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
eio:
retval = -EIO;
err:
- if (i2c_debug)
- printk(" ERR: %d\n", retval);
+ printk(" ERR: %d\n", retval);
return retval;
}
@@ -245,22 +225,15 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap,
__FUNCTION__, num, msgs[i].addr, msgs[i].len);
if (msgs[i].flags & I2C_M_RD) {
/* read */
- retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
- } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
- msgs[i].addr == msgs[i + 1].addr) {
- /* write then read from same address */
- retval = i2c_sendbytes(i2c_adap, &msgs[i],
- msgs[i + 1].len);
+ retval = i2c_readbytes(i2c_adap, &msgs[i], i+1 == num);
if (retval < 0)
goto err;
- i++;
- retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
} else {
/* write */
- retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
+ retval = i2c_sendbytes(i2c_adap, &msgs[i], i+1 == num);
+ if (retval < 0)
+ goto err;
}
- if (retval < 0)
- goto err;
}
return num;
@@ -270,9 +243,7 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap,
static int attach_inform(struct i2c_client *client)
{
- struct cx23885_i2c *bus = i2c_get_adapdata(client->adapter);
- struct cx23885_dev *dev = bus->dev;
- struct tuner_setup tun_setup;
+ struct cx23885_dev *dev = i2c_get_adapdata(client->adapter);
dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
client->driver->driver.name, client->addr, client->name);
@@ -280,31 +251,6 @@ static int attach_inform(struct i2c_client *client)
if (!client->driver->command)
return 0;
- if (dev->tuner_type != UNSET) {
-
- dprintk(1, "%s (tuner) i2c attach [addr=0x%x,client=%s]\n",
- client->driver->driver.name, client->addr,
- client->name);
-
- if ((dev->tuner_addr == ADDR_UNSET) ||
- (dev->tuner_addr == client->addr)) {
-
- dprintk(1, "%s (tuner || addr UNSET)\n",
- client->driver->driver.name);
-
- dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
- client->driver->driver.name,
- client->addr, client->name);
-
- tun_setup.mode_mask = T_ANALOG_TV;
- tun_setup.type = dev->tuner_type;
- tun_setup.addr = dev->tuner_addr;
-
- client->driver->command(client, TUNER_SET_TYPE_ADDR,
- &tun_setup);
- }
- }
-
return 0;
}
@@ -343,7 +289,6 @@ static struct i2c_adapter cx23885_i2c_adap_template = {
.owner = THIS_MODULE,
.id = I2C_HW_B_CX23885,
.algo = &cx23885_i2c_algo_template,
- .class = I2C_CLASS_TV_ANALOG,
.client_register = attach_inform,
.client_unregister = detach_inform,
};
@@ -360,7 +305,7 @@ static char *i2c_devs[128] = {
[ 0x84 >> 1 ] = "tda8295",
[ 0xa0 >> 1 ] = "eeprom",
[ 0xc0 >> 1 ] = "tuner/mt2131/tda8275",
- [ 0xc2 >> 1 ] = "tuner/mt2131/tda8275/xc5000",
+ [ 0xc2 >> 1 ] = "tuner/mt2131/tda8275",
};
static void do_i2c_scan(char *name, struct i2c_client *c)
@@ -399,7 +344,6 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
bus->i2c_algo.data = bus;
bus->i2c_adap.algo_data = bus;
- i2c_set_adapdata(&bus->i2c_adap, bus);
i2c_add_adapter(&bus->i2c_adap);
bus->i2c_client.adapter = &bus->i2c_adap;
@@ -422,6 +366,8 @@ int cx23885_i2c_unregister(struct cx23885_i2c *bus)
/* ----------------------------------------------------------------------- */
+EXPORT_SYMBOL(cx23885_call_i2c_clients);
+
/*
* Local variables:
* c-basic-offset: 8
diff --git a/trunk/drivers/media/video/cx23885/cx23885-reg.h b/trunk/drivers/media/video/cx23885/cx23885-reg.h
index bdd11bc513ad..162169f9091b 100644
--- a/trunk/drivers/media/video/cx23885/cx23885-reg.h
+++ b/trunk/drivers/media/video/cx23885/cx23885-reg.h
@@ -233,17 +233,6 @@ Channel manager Data Structure entry = 20 DWORD
#define VID_A_INT_SSTAT 0x0004002C
#define VID_B_INT_MSK 0x00040030
-#define VID_B_MSK_BAD_PKT (1 << 20)
-#define VID_B_MSK_VBI_OPC_ERR (1 << 17)
-#define VID_B_MSK_OPC_ERR (1 << 16)
-#define VID_B_MSK_VBI_SYNC (1 << 13)
-#define VID_B_MSK_SYNC (1 << 12)
-#define VID_B_MSK_VBI_OF (1 << 9)
-#define VID_B_MSK_OF (1 << 8)
-#define VID_B_MSK_VBI_RISCI2 (1 << 5)
-#define VID_B_MSK_RISCI2 (1 << 4)
-#define VID_B_MSK_VBI_RISCI1 (1 << 1)
-#define VID_B_MSK_RISCI1 1
#define VID_B_INT_STAT 0x00040034
#define VID_B_INT_MSTAT 0x00040038
#define VID_B_INT_SSTAT 0x0004003C
@@ -287,7 +276,6 @@ Channel manager Data Structure entry = 20 DWORD
#define RDR_CFG0 0x00050000
#define RDR_CFG1 0x00050004
-#define RDR_CFG2 0x00050008
#define RDR_TLCTL0 0x00050318
/* APB DMAC Current Buffer Pointer */
@@ -347,7 +335,6 @@ Channel manager Data Structure entry = 20 DWORD
/* GPIO (417 Microsoftcontroller) Output Enable, Low Active */
#define MC417_OEN 0x00110024
#define MC417_CTL 0x00110028
-#define ALT_PIN_OUT_SEL 0x0011002C
#define CLK_DELAY 0x00110048
#define PAD_CTRL 0x0011004C
diff --git a/trunk/drivers/media/video/cx23885/cx23885-vbi.c b/trunk/drivers/media/video/cx23885/cx23885-vbi.c
deleted file mode 100644
index e36e3fcae2fb..000000000000
--- a/trunk/drivers/media/video/cx23885/cx23885-vbi.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Driver for the Conexant CX23885 PCIe bridge
- *
- * Copyright (c) 2007 Steven Toth
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include
-#include
-#include
-#include
-#include
-
-#include "cx23885.h"
-
-static unsigned int vbibufs = 4;
-module_param(vbibufs, int, 0644);
-MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32");
-
-static unsigned int vbi_debug;
-module_param(vbi_debug, int, 0644);
-MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]");
-
-#define dprintk(level, fmt, arg...)\
- do { if (vbi_debug >= level)\
- printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
- } while (0)
-
-/* ------------------------------------------------------------------ */
-
-int cx23885_vbi_fmt(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct cx23885_fh *fh = priv;
- struct cx23885_dev *dev = fh->dev;
-
- if (dev->tvnorm & V4L2_STD_525_60) {
- /* ntsc */
- f->fmt.vbi.sampling_rate = 28636363;
- f->fmt.vbi.start[0] = 10;
- f->fmt.vbi.start[1] = 273;
-
- } else if (dev->tvnorm & V4L2_STD_625_50) {
- /* pal */
- f->fmt.vbi.sampling_rate = 35468950;
- f->fmt.vbi.start[0] = 7 - 1;
- f->fmt.vbi.start[1] = 319 - 1;
- }
- return 0;
-}
-
-static int cx23885_start_vbi_dma(struct cx23885_dev *dev,
- struct cx23885_dmaqueue *q,
- struct cx23885_buffer *buf)
-{
- /* setup fifo + format */
- cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02],
- buf->vb.width, buf->risc.dma);
-
- /* reset counter */
- q->count = 1;
-
- /* enable irqs */
- cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | 0x01);
- cx_set(VID_A_INT_MSK, 0x000022);
-
- /* start dma */
- cx_set(DEV_CNTRL2, (1<<5));
- cx_set(VID_A_DMA_CTL, 0x00000022);
-
- return 0;
-}
-
-int cx23885_stop_vbi_dma(struct cx23885_dev *dev)
-{
- /* stop dma */
- cx_clear(VID_A_DMA_CTL, 0x00000022);
-
- /* disable irqs */
- cx_clear(PCI_INT_MSK, 0x000001);
- cx_clear(VID_A_INT_MSK, 0x00000022);
- return 0;
-}
-
-int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
- struct cx23885_dmaqueue *q)
-{
- struct cx23885_buffer *buf;
- struct list_head *item;
-
- if (list_empty(&q->active))
- return 0;
-
- buf = list_entry(q->active.next, struct cx23885_buffer, vb.queue);
- dprintk(2, "restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.i);
- cx23885_start_vbi_dma(dev, q, buf);
- list_for_each(item, &q->active) {
- buf = list_entry(item, struct cx23885_buffer, vb.queue);
- buf->count = q->count++;
- }
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- return 0;
-}
-
-void cx23885_vbi_timeout(unsigned long data)
-{
- struct cx23885_dev *dev = (struct cx23885_dev *)data;
- struct cx23885_dmaqueue *q = &dev->vbiq;
- struct cx23885_buffer *buf;
- unsigned long flags;
-
- cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH02]);
-
- cx_clear(VID_A_DMA_CTL, 0x22);
-
- spin_lock_irqsave(&dev->slock, flags);
- while (!list_empty(&q->active)) {
- buf = list_entry(q->active.next, struct cx23885_buffer,
- vb.queue);
- list_del(&buf->vb.queue);
- buf->vb.state = VIDEOBUF_ERROR;
- wake_up(&buf->vb.done);
- printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->name,
- buf, buf->vb.i, (unsigned long)buf->risc.dma);
- }
- cx23885_restart_vbi_queue(dev, q);
- spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-/* ------------------------------------------------------------------ */
-#define VBI_LINE_LENGTH 2048
-#define VBI_LINE_COUNT 17
-
-static int
-vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
-{
- *size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
- if (0 == *count)
- *count = vbibufs;
- if (*count < 2)
- *count = 2;
- if (*count > 32)
- *count = 32;
- return 0;
-}
-
-static int
-vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
- enum v4l2_field field)
-{
- struct cx23885_fh *fh = q->priv_data;
- struct cx23885_dev *dev = fh->dev;
- struct cx23885_buffer *buf = container_of(vb,
- struct cx23885_buffer, vb);
- struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
- unsigned int size;
- int rc;
-
- size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
- if (0 != buf->vb.baddr && buf->vb.bsize < size)
- return -EINVAL;
-
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
- buf->vb.width = VBI_LINE_LENGTH;
- buf->vb.height = VBI_LINE_COUNT;
- buf->vb.size = size;
- buf->vb.field = V4L2_FIELD_SEQ_TB;
-
- rc = videobuf_iolock(q, &buf->vb, NULL);
- if (0 != rc)
- goto fail;
- cx23885_risc_buffer(dev->pci, &buf->risc,
- dma->sglist,
- 0, buf->vb.width * buf->vb.height,
- buf->vb.width, 0,
- buf->vb.height);
- }
- buf->vb.state = VIDEOBUF_PREPARED;
- return 0;
-
- fail:
- cx23885_free_buffer(q, buf);
- return rc;
-}
-
-static void
-vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
- struct cx23885_buffer *buf =
- container_of(vb, struct cx23885_buffer, vb);
- struct cx23885_buffer *prev;
- struct cx23885_fh *fh = vq->priv_data;
- struct cx23885_dev *dev = fh->dev;
- struct cx23885_dmaqueue *q = &dev->vbiq;
-
- /* add jump to stopper */
- buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
- buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
- buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
-
- if (list_empty(&q->active)) {
- list_add_tail(&buf->vb.queue, &q->active);
- cx23885_start_vbi_dma(dev, q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
- buf->count = q->count++;
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- dprintk(2, "[%p/%d] vbi_queue - first active\n",
- buf, buf->vb.i);
-
- } else {
- prev = list_entry(q->active.prev, struct cx23885_buffer,
- vb.queue);
- list_add_tail(&buf->vb.queue, &q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
- buf->count = q->count++;
- prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
- prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63-32 */
- dprintk(2, "[%p/%d] buffer_queue - append to active\n",
- buf, buf->vb.i);
- }
-}
-
-static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
- struct cx23885_buffer *buf =
- container_of(vb, struct cx23885_buffer, vb);
-
- cx23885_free_buffer(q, buf);
-}
-
-struct videobuf_queue_ops cx23885_vbi_qops = {
- .buf_setup = vbi_setup,
- .buf_prepare = vbi_prepare,
- .buf_queue = vbi_queue,
- .buf_release = vbi_release,
-};
-
-/* ------------------------------------------------------------------ */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/trunk/drivers/media/video/cx23885/cx23885-video.c b/trunk/drivers/media/video/cx23885/cx23885-video.c
deleted file mode 100644
index d3c4d2c5cbe0..000000000000
--- a/trunk/drivers/media/video/cx23885/cx23885-video.c
+++ /dev/null
@@ -1,1557 +0,0 @@
-/*
- * Driver for the Conexant CX23885 PCIe bridge
- *
- * Copyright (c) 2007 Steven Toth
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "cx23885.h"
-#include
-
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-/* Include V4L1 specific functions. Should be removed soon */
-#include
-#endif
-
-MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
-MODULE_AUTHOR("Steven Toth ");
-MODULE_LICENSE("GPL");
-
-/* ------------------------------------------------------------------ */
-
-static unsigned int video_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
-static unsigned int vbi_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
-static unsigned int radio_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
-
-module_param_array(video_nr, int, NULL, 0444);
-module_param_array(vbi_nr, int, NULL, 0444);
-module_param_array(radio_nr, int, NULL, 0444);
-
-MODULE_PARM_DESC(video_nr, "video device numbers");
-MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
-MODULE_PARM_DESC(radio_nr, "radio device numbers");
-
-static unsigned int video_debug;
-module_param(video_debug, int, 0644);
-MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
-
-static unsigned int irq_debug;
-module_param(irq_debug, int, 0644);
-MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");
-
-static unsigned int vid_limit = 16;
-module_param(vid_limit, int, 0644);
-MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
-
-#define dprintk(level, fmt, arg...)\
- do { if (video_debug >= level)\
- printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
- } while (0)
-
-/* ------------------------------------------------------------------- */
-/* static data */
-
-#define FORMAT_FLAGS_PACKED 0x01
-
-static struct cx23885_fmt formats[] = {
- {
- .name = "8 bpp, gray",
- .fourcc = V4L2_PIX_FMT_GREY,
- .depth = 8,
- .flags = FORMAT_FLAGS_PACKED,
- }, {
- .name = "15 bpp RGB, le",
- .fourcc = V4L2_PIX_FMT_RGB555,
- .depth = 16,
- .flags = FORMAT_FLAGS_PACKED,
- }, {
- .name = "15 bpp RGB, be",
- .fourcc = V4L2_PIX_FMT_RGB555X,
- .depth = 16,
- .flags = FORMAT_FLAGS_PACKED,
- }, {
- .name = "16 bpp RGB, le",
- .fourcc = V4L2_PIX_FMT_RGB565,
- .depth = 16,
- .flags = FORMAT_FLAGS_PACKED,
- }, {
- .name = "16 bpp RGB, be",
- .fourcc = V4L2_PIX_FMT_RGB565X,
- .depth = 16,
- .flags = FORMAT_FLAGS_PACKED,
- }, {
- .name = "24 bpp RGB, le",
- .fourcc = V4L2_PIX_FMT_BGR24,
- .depth = 24,
- .flags = FORMAT_FLAGS_PACKED,
- }, {
- .name = "32 bpp RGB, le",
- .fourcc = V4L2_PIX_FMT_BGR32,
- .depth = 32,
- .flags = FORMAT_FLAGS_PACKED,
- }, {
- .name = "32 bpp RGB, be",
- .fourcc = V4L2_PIX_FMT_RGB32,
- .depth = 32,
- .flags = FORMAT_FLAGS_PACKED,
- }, {
- .name = "4:2:2, packed, YUYV",
- .fourcc = V4L2_PIX_FMT_YUYV,
- .depth = 16,
- .flags = FORMAT_FLAGS_PACKED,
- }, {
- .name = "4:2:2, packed, UYVY",
- .fourcc = V4L2_PIX_FMT_UYVY,
- .depth = 16,
- .flags = FORMAT_FLAGS_PACKED,
- },
-};
-
-static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(formats); i++)
- if (formats[i].fourcc == fourcc)
- return formats+i;
-
- printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __FUNCTION__, fourcc);
- return NULL;
-}
-
-/* ------------------------------------------------------------------- */
-
-static const struct v4l2_queryctrl no_ctl = {
- .name = "42",
- .flags = V4L2_CTRL_FLAG_DISABLED,
-};
-
-static struct cx23885_ctrl cx23885_ctls[] = {
- /* --- video --- */
- {
- .v = {
- .id = V4L2_CID_BRIGHTNESS,
- .name = "Brightness",
- .minimum = 0x00,
- .maximum = 0xff,
- .step = 1,
- .default_value = 0x7f,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },
- .off = 128,
- .reg = LUMA_CTRL,
- .mask = 0x00ff,
- .shift = 0,
- }, {
- .v = {
- .id = V4L2_CID_CONTRAST,
- .name = "Contrast",
- .minimum = 0,
- .maximum = 0xff,
- .step = 1,
- .default_value = 0x3f,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },
- .off = 0,
- .reg = LUMA_CTRL,
- .mask = 0xff00,
- .shift = 8,
- }, {
- .v = {
- .id = V4L2_CID_HUE,
- .name = "Hue",
- .minimum = 0,
- .maximum = 0xff,
- .step = 1,
- .default_value = 0x7f,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },
- .off = 128,
- .reg = CHROMA_CTRL,
- .mask = 0xff0000,
- .shift = 16,
- }, {
- /* strictly, this only describes only U saturation.
- * V saturation is handled specially through code.
- */
- .v = {
- .id = V4L2_CID_SATURATION,
- .name = "Saturation",
- .minimum = 0,
- .maximum = 0xff,
- .step = 1,
- .default_value = 0x7f,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },
- .off = 0,
- .reg = CHROMA_CTRL,
- .mask = 0x00ff,
- .shift = 0,
- }, {
- /* --- audio --- */
- .v = {
- .id = V4L2_CID_AUDIO_MUTE,
- .name = "Mute",
- .minimum = 0,
- .maximum = 1,
- .default_value = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },
- .reg = PATH1_CTL1,
- .mask = (0x1f << 24),
- .shift = 24,
- }, {
- .v = {
- .id = V4L2_CID_AUDIO_VOLUME,
- .name = "Volume",
- .minimum = 0,
- .maximum = 0x3f,
- .step = 1,
- .default_value = 0x3f,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },
- .reg = PATH1_VOL_CTL,
- .mask = 0xff,
- .shift = 0,
- }
-};
-static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls);
-
-const u32 cx23885_user_ctrls[] = {
- V4L2_CID_USER_CLASS,
- V4L2_CID_BRIGHTNESS,
- V4L2_CID_CONTRAST,
- V4L2_CID_SATURATION,
- V4L2_CID_HUE,
- V4L2_CID_AUDIO_VOLUME,
- V4L2_CID_AUDIO_MUTE,
- 0
-};
-EXPORT_SYMBOL(cx23885_user_ctrls);
-
-static const u32 *ctrl_classes[] = {
- cx23885_user_ctrls,
- NULL
-};
-
-void cx23885_video_wakeup(struct cx23885_dev *dev,
- struct cx23885_dmaqueue *q, u32 count)
-{
- struct cx23885_buffer *buf;
- int bc;
-
- for (bc = 0;; bc++) {
- if (list_empty(&q->active))
- break;
- buf = list_entry(q->active.next,
- struct cx23885_buffer, vb.queue);
-
- /* count comes from the hw and is is 16bit wide --
- * this trick handles wrap-arounds correctly for
- * up to 32767 buffers in flight... */
- if ((s16) (count - buf->count) < 0)
- break;
-
- do_gettimeofday(&buf->vb.ts);
- dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i,
- count, buf->count);
- buf->vb.state = VIDEOBUF_DONE;
- list_del(&buf->vb.queue);
- wake_up(&buf->vb.done);
- }
- if (list_empty(&q->active)) {
- del_timer(&q->timeout);
- } else {
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- }
- if (bc != 1)
- printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
- __FUNCTION__, bc);
-}
-
-int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
-{
- dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
- __FUNCTION__,
- (unsigned int)norm,
- v4l2_norm_to_name(norm));
-
- dev->tvnorm = norm;
-
- /* Tell the analog tuner/demods */
- cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_STD, &norm);
-
- /* Tell the internal A/V decoder */
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_STD, &norm);
-
- return 0;
-}
-
-struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
- struct pci_dev *pci,
- struct video_device *template,
- char *type)
-{
- struct video_device *vfd;
- dprintk(1, "%s()\n", __FUNCTION__);
-
- vfd = video_device_alloc();
- if (NULL == vfd)
- return NULL;
- *vfd = *template;
- vfd->minor = -1;
- vfd->dev = &pci->dev;
- vfd->release = video_device_release;
- snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
- dev->name, type, cx23885_boards[dev->board].name);
- return vfd;
-}
-
-int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl)
-{
- int i;
-
- if (qctrl->id < V4L2_CID_BASE ||
- qctrl->id >= V4L2_CID_LASTP1)
- return -EINVAL;
- for (i = 0; i < CX23885_CTLS; i++)
- if (cx23885_ctls[i].v.id == qctrl->id)
- break;
- if (i == CX23885_CTLS) {
- *qctrl = no_ctl;
- return 0;
- }
- *qctrl = cx23885_ctls[i].v;
- return 0;
-}
-EXPORT_SYMBOL(cx23885_ctrl_query);
-
-/* ------------------------------------------------------------------- */
-/* resource management */
-
-static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh,
- unsigned int bit)
-{
- dprintk(1, "%s()\n", __FUNCTION__);
- if (fh->resources & bit)
- /* have it already allocated */
- return 1;
-
- /* is it free? */
- mutex_lock(&dev->lock);
- if (dev->resources & bit) {
- /* no, someone else uses it */
- mutex_unlock(&dev->lock);
- return 0;
- }
- /* it's free, grab it */
- fh->resources |= bit;
- dev->resources |= bit;
- dprintk(1, "res: get %d\n", bit);
- mutex_unlock(&dev->lock);
- return 1;
-}
-
-static int res_check(struct cx23885_fh *fh, unsigned int bit)
-{
- return (fh->resources & bit);
-}
-
-static int res_locked(struct cx23885_dev *dev, unsigned int bit)
-{
- return (dev->resources & bit);
-}
-
-static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
- unsigned int bits)
-{
- BUG_ON((fh->resources & bits) != bits);
- dprintk(1, "%s()\n", __FUNCTION__);
-
- mutex_lock(&dev->lock);
- fh->resources &= ~bits;
- dev->resources &= ~bits;
- dprintk(1, "res: put %d\n", bits);
- mutex_unlock(&dev->lock);
-}
-
-int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
-{
- struct v4l2_routing route;
- memset(&route, 0, sizeof(route));
-
- dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
- __FUNCTION__,
- input, INPUT(input)->vmux,
- INPUT(input)->gpio0, INPUT(input)->gpio1,
- INPUT(input)->gpio2, INPUT(input)->gpio3);
- dev->input = input;
-
- route.input = INPUT(input)->vmux;
-
- /* Tell the internal A/V decoder */
- cx23885_call_i2c_clients(&dev->i2c_bus[2],
- VIDIOC_INT_S_VIDEO_ROUTING, &route);
-
- return 0;
-}
-EXPORT_SYMBOL(cx23885_video_mux);
-
-/* ------------------------------------------------------------------ */
-int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
- unsigned int height, enum v4l2_field field)
-{
- dprintk(1, "%s()\n", __FUNCTION__);
- return 0;
-}
-
-static int cx23885_start_video_dma(struct cx23885_dev *dev,
- struct cx23885_dmaqueue *q,
- struct cx23885_buffer *buf)
-{
- dprintk(1, "%s()\n", __FUNCTION__);
-
- /* setup fifo + format */
- cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
- buf->bpl, buf->risc.dma);
- cx23885_set_scale(dev, buf->vb.width, buf->vb.height, buf->vb.field);
-
- /* reset counter */
- cx_write(VID_A_GPCNT_CTL, 3);
- q->count = 1;
-
- /* enable irq */
- cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | 0x01);
- cx_set(VID_A_INT_MSK, 0x000011);
-
- /* start dma */
- cx_set(DEV_CNTRL2, (1<<5));
- cx_set(VID_A_DMA_CTL, 0x11); /* FIFO and RISC enable */
-
- return 0;
-}
-
-
-static int cx23885_restart_video_queue(struct cx23885_dev *dev,
- struct cx23885_dmaqueue *q)
-{
- struct cx23885_buffer *buf, *prev;
- struct list_head *item;
- dprintk(1, "%s()\n", __FUNCTION__);
-
- if (!list_empty(&q->active)) {
- buf = list_entry(q->active.next, struct cx23885_buffer,
- vb.queue);
- dprintk(2, "restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.i);
- cx23885_start_video_dma(dev, q, buf);
- list_for_each(item, &q->active) {
- buf = list_entry(item, struct cx23885_buffer,
- vb.queue);
- buf->count = q->count++;
- }
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- return 0;
- }
-
- prev = NULL;
- for (;;) {
- if (list_empty(&q->queued))
- return 0;
- buf = list_entry(q->queued.next, struct cx23885_buffer,
- vb.queue);
- if (NULL == prev) {
- list_move_tail(&buf->vb.queue, &q->active);
- cx23885_start_video_dma(dev, q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
- buf->count = q->count++;
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- dprintk(2, "[%p/%d] restart_queue - first active\n",
- buf, buf->vb.i);
-
- } else if (prev->vb.width == buf->vb.width &&
- prev->vb.height == buf->vb.height &&
- prev->fmt == buf->fmt) {
- list_move_tail(&buf->vb.queue, &q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
- buf->count = q->count++;
- prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
- prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */
- dprintk(2, "[%p/%d] restart_queue - move to active\n",
- buf, buf->vb.i);
- } else {
- return 0;
- }
- prev = buf;
- }
-}
-
-static int buffer_setup(struct videobuf_queue *q, unsigned int *count,
- unsigned int *size)
-{
- struct cx23885_fh *fh = q->priv_data;
-
- *size = fh->fmt->depth*fh->width*fh->height >> 3;
- if (0 == *count)
- *count = 32;
- while (*size * *count > vid_limit * 1024 * 1024)
- (*count)--;
- return 0;
-}
-
-static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
- enum v4l2_field field)
-{
- struct cx23885_fh *fh = q->priv_data;
- struct cx23885_dev *dev = fh->dev;
- struct cx23885_buffer *buf =
- container_of(vb, struct cx23885_buffer, vb);
- int rc, init_buffer = 0;
- u32 line0_offset, line1_offset;
- struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
-
- BUG_ON(NULL == fh->fmt);
- if (fh->width < 48 || fh->width > norm_maxw(dev->tvnorm) ||
- fh->height < 32 || fh->height > norm_maxh(dev->tvnorm))
- return -EINVAL;
- buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
- if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
- return -EINVAL;
-
- if (buf->fmt != fh->fmt ||
- buf->vb.width != fh->width ||
- buf->vb.height != fh->height ||
- buf->vb.field != field) {
- buf->fmt = fh->fmt;
- buf->vb.width = fh->width;
- buf->vb.height = fh->height;
- buf->vb.field = field;
- init_buffer = 1;
- }
-
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
- init_buffer = 1;
- rc = videobuf_iolock(q, &buf->vb, NULL);
- if (0 != rc)
- goto fail;
- }
-
- if (init_buffer) {
- buf->bpl = buf->vb.width * buf->fmt->depth >> 3;
- switch (buf->vb.field) {
- case V4L2_FIELD_TOP:
- cx23885_risc_buffer(dev->pci, &buf->risc,
- dma->sglist, 0, UNSET,
- buf->bpl, 0, buf->vb.height);
- break;
- case V4L2_FIELD_BOTTOM:
- cx23885_risc_buffer(dev->pci, &buf->risc,
- dma->sglist, UNSET, 0,
- buf->bpl, 0, buf->vb.height);
- break;
- case V4L2_FIELD_INTERLACED:
- if (dev->tvnorm & V4L2_STD_NTSC) {
- /* cx25840 transmits NTSC bottom field first */
- dprintk(1, "%s() Creating NTSC risc\n",
- __FUNCTION__);
- line0_offset = buf->bpl;
- line1_offset = 0;
- } else {
- /* All other formats are top field first */
- dprintk(1, "%s() Creating PAL/SECAM risc\n",
- __FUNCTION__);
- line0_offset = 0;
- line1_offset = buf->bpl;
- }
- cx23885_risc_buffer(dev->pci, &buf->risc,
- dma->sglist, line0_offset,
- line1_offset,
- buf->bpl, buf->bpl,
- buf->vb.height >> 1);
- break;
- case V4L2_FIELD_SEQ_TB:
- cx23885_risc_buffer(dev->pci, &buf->risc,
- dma->sglist,
- 0, buf->bpl * (buf->vb.height >> 1),
- buf->bpl, 0,
- buf->vb.height >> 1);
- break;
- case V4L2_FIELD_SEQ_BT:
- cx23885_risc_buffer(dev->pci, &buf->risc,
- dma->sglist,
- buf->bpl * (buf->vb.height >> 1), 0,
- buf->bpl, 0,
- buf->vb.height >> 1);
- break;
- default:
- BUG();
- }
- }
- dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
- buf, buf->vb.i,
- fh->width, fh->height, fh->fmt->depth, fh->fmt->name,
- (unsigned long)buf->risc.dma);
-
- buf->vb.state = VIDEOBUF_PREPARED;
- return 0;
-
- fail:
- cx23885_free_buffer(q, buf);
- return rc;
-}
-
-static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
- struct cx23885_buffer *buf = container_of(vb,
- struct cx23885_buffer, vb);
- struct cx23885_buffer *prev;
- struct cx23885_fh *fh = vq->priv_data;
- struct cx23885_dev *dev = fh->dev;
- struct cx23885_dmaqueue *q = &dev->vidq;
-
- /* add jump to stopper */
- buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
- buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
- buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
-
- if (!list_empty(&q->queued)) {
- list_add_tail(&buf->vb.queue, &q->queued);
- buf->vb.state = VIDEOBUF_QUEUED;
- dprintk(2, "[%p/%d] buffer_queue - append to queued\n",
- buf, buf->vb.i);
-
- } else if (list_empty(&q->active)) {
- list_add_tail(&buf->vb.queue, &q->active);
- cx23885_start_video_dma(dev, q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
- buf->count = q->count++;
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- dprintk(2, "[%p/%d] buffer_queue - first active\n",
- buf, buf->vb.i);
-
- } else {
- prev = list_entry(q->active.prev, struct cx23885_buffer,
- vb.queue);
- if (prev->vb.width == buf->vb.width &&
- prev->vb.height == buf->vb.height &&
- prev->fmt == buf->fmt) {
- list_add_tail(&buf->vb.queue, &q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
- buf->count = q->count++;
- prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
- /* 64 bit bits 63-32 */
- prev->risc.jmp[2] = cpu_to_le32(0);
- dprintk(2, "[%p/%d] buffer_queue - append to active\n",
- buf, buf->vb.i);
-
- } else {
- list_add_tail(&buf->vb.queue, &q->queued);
- buf->vb.state = VIDEOBUF_QUEUED;
- dprintk(2, "[%p/%d] buffer_queue - first queued\n",
- buf, buf->vb.i);
- }
- }
-}
-
-static void buffer_release(struct videobuf_queue *q,
- struct videobuf_buffer *vb)
-{
- struct cx23885_buffer *buf = container_of(vb,
- struct cx23885_buffer, vb);
-
- cx23885_free_buffer(q, buf);
-}
-
-static struct videobuf_queue_ops cx23885_video_qops = {
- .buf_setup = buffer_setup,
- .buf_prepare = buffer_prepare,
- .buf_queue = buffer_queue,
- .buf_release = buffer_release,
-};
-
-static struct videobuf_queue *get_queue(struct cx23885_fh *fh)
-{
- switch (fh->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- return &fh->vidq;
- case V4L2_BUF_TYPE_VBI_CAPTURE:
- return &fh->vbiq;
- default:
- BUG();
- return NULL;
- }
-}
-
-static int get_resource(struct cx23885_fh *fh)
-{
- switch (fh->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- return RESOURCE_VIDEO;
- case V4L2_BUF_TYPE_VBI_CAPTURE:
- return RESOURCE_VBI;
- default:
- BUG();
- return 0;
- }
-}
-
-static int video_open(struct inode *inode, struct file *file)
-{
- int minor = iminor(inode);
- struct cx23885_dev *h, *dev = NULL;
- struct cx23885_fh *fh;
- struct list_head *list;
- enum v4l2_buf_type type = 0;
- int radio = 0;
-
- list_for_each(list, &cx23885_devlist) {
- h = list_entry(list, struct cx23885_dev, devlist);
- if (h->video_dev->minor == minor) {
- dev = h;
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- }
- if (h->vbi_dev &&
- h->vbi_dev->minor == minor) {
- dev = h;
- type = V4L2_BUF_TYPE_VBI_CAPTURE;
- }
- if (h->radio_dev &&
- h->radio_dev->minor == minor) {
- radio = 1;
- dev = h;
- }
- }
- if (NULL == dev)
- return -ENODEV;
-
- dprintk(1, "open minor=%d radio=%d type=%s\n",
- minor, radio, v4l2_type_names[type]);
-
- /* allocate + initialize per filehandle data */
- fh = kzalloc(sizeof(*fh), GFP_KERNEL);
- if (NULL == fh)
- return -ENOMEM;
- file->private_data = fh;
- fh->dev = dev;
- fh->radio = radio;
- fh->type = type;
- fh->width = 320;
- fh->height = 240;
- fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
-
- videobuf_queue_pci_init(&fh->vidq, &cx23885_video_qops,
- dev->pci, &dev->slock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_INTERLACED,
- sizeof(struct cx23885_buffer),
- fh);
-
- dprintk(1, "post videobuf_queue_init()\n");
-
-
- return 0;
-}
-
-static ssize_t video_read(struct file *file, char __user *data,
- size_t count, loff_t *ppos)
-{
- struct cx23885_fh *fh = file->private_data;
-
- switch (fh->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (res_locked(fh->dev, RESOURCE_VIDEO))
- return -EBUSY;
- return videobuf_read_one(&fh->vidq, data, count, ppos,
- file->f_flags & O_NONBLOCK);
- case V4L2_BUF_TYPE_VBI_CAPTURE:
- if (!res_get(fh->dev, fh, RESOURCE_VBI))
- return -EBUSY;
- return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1,
- file->f_flags & O_NONBLOCK);
- default:
- BUG();
- return 0;
- }
-}
-
-static unsigned int video_poll(struct file *file,
- struct poll_table_struct *wait)
-{
- struct cx23885_fh *fh = file->private_data;
- struct cx23885_buffer *buf;
-
- if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
- if (!res_get(fh->dev, fh, RESOURCE_VBI))
- return POLLERR;
- return videobuf_poll_stream(file, &fh->vbiq, wait);
- }
-
- if (res_check(fh, RESOURCE_VIDEO)) {
- /* streaming capture */
- if (list_empty(&fh->vidq.stream))
- return POLLERR;
- buf = list_entry(fh->vidq.stream.next,
- struct cx23885_buffer, vb.stream);
- } else {
- /* read() capture */
- buf = (struct cx23885_buffer *)fh->vidq.read_buf;
- if (NULL == buf)
- return POLLERR;
- }
- poll_wait(file, &buf->vb.done, wait);
- if (buf->vb.state == VIDEOBUF_DONE ||
- buf->vb.state == VIDEOBUF_ERROR)
- return POLLIN|POLLRDNORM;
- return 0;
-}
-
-static int video_release(struct inode *inode, struct file *file)
-{
- struct cx23885_fh *fh = file->private_data;
- struct cx23885_dev *dev = fh->dev;
-
- /* turn off overlay */
- if (res_check(fh, RESOURCE_OVERLAY)) {
- /* FIXME */
- res_free(dev, fh, RESOURCE_OVERLAY);
- }
-
- /* stop video capture */
- if (res_check(fh, RESOURCE_VIDEO)) {
- videobuf_queue_cancel(&fh->vidq);
- res_free(dev, fh, RESOURCE_VIDEO);
- }
- if (fh->vidq.read_buf) {
- buffer_release(&fh->vidq, fh->vidq.read_buf);
- kfree(fh->vidq.read_buf);
- }
-
- /* stop vbi capture */
- if (res_check(fh, RESOURCE_VBI)) {
- if (fh->vbiq.streaming)
- videobuf_streamoff(&fh->vbiq);
- if (fh->vbiq.reading)
- videobuf_read_stop(&fh->vbiq);
- res_free(dev, fh, RESOURCE_VBI);
- }
-
- videobuf_mmap_free(&fh->vidq);
- file->private_data = NULL;
- kfree(fh);
-
- /* We are not putting the tuner to sleep here on exit, because
- * we want to use the mpeg encoder in another session to capture
- * tuner video. Closing this will result in no video to the encoder.
- */
-
- return 0;
-}
-
-static int video_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct cx23885_fh *fh = file->private_data;
-
- return videobuf_mmap_mapper(get_queue(fh), vma);
-}
-
-/* ------------------------------------------------------------------ */
-/* VIDEO CTRL IOCTLS */
-
-int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
-{
- dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __FUNCTION__);
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl);
- return 0;
-}
-EXPORT_SYMBOL(cx23885_get_control);
-
-int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
-{
- dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
- " (disabled - no action)\n", __FUNCTION__);
- return 0;
-}
-EXPORT_SYMBOL(cx23885_set_control);
-
-static void init_controls(struct cx23885_dev *dev)
-{
- struct v4l2_control ctrl;
- int i;
-
- for (i = 0; i < CX23885_CTLS; i++) {
- ctrl.id = cx23885_ctls[i].v.id;
- ctrl.value = cx23885_ctls[i].v.default_value;
-
- cx23885_set_control(dev, &ctrl);
- }
-}
-
-/* ------------------------------------------------------------------ */
-/* VIDEO IOCTLS */
-
-static int vidioc_g_fmt_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct cx23885_fh *fh = priv;
-
- f->fmt.pix.width = fh->width;
- f->fmt.pix.height = fh->height;
- f->fmt.pix.field = fh->vidq.field;
- f->fmt.pix.pixelformat = fh->fmt->fourcc;
- f->fmt.pix.bytesperline =
- (f->fmt.pix.width * fh->fmt->depth) >> 3;
- f->fmt.pix.sizeimage =
- f->fmt.pix.height * f->fmt.pix.bytesperline;
-
- return 0;
-}
-
-static int vidioc_try_fmt_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
- struct cx23885_fmt *fmt;
- enum v4l2_field field;
- unsigned int maxw, maxh;
-
- fmt = format_by_fourcc(f->fmt.pix.pixelformat);
- if (NULL == fmt)
- return -EINVAL;
-
- field = f->fmt.pix.field;
- maxw = norm_maxw(dev->tvnorm);
- maxh = norm_maxh(dev->tvnorm);
-
- if (V4L2_FIELD_ANY == field) {
- field = (f->fmt.pix.height > maxh/2)
- ? V4L2_FIELD_INTERLACED
- : V4L2_FIELD_BOTTOM;
- }
-
- switch (field) {
- case V4L2_FIELD_TOP:
- case V4L2_FIELD_BOTTOM:
- maxh = maxh / 2;
- break;
- case V4L2_FIELD_INTERLACED:
- break;
- default:
- return -EINVAL;
- }
-
- f->fmt.pix.field = field;
- if (f->fmt.pix.height < 32)
- f->fmt.pix.height = 32;
- if (f->fmt.pix.height > maxh)
- f->fmt.pix.height = maxh;
- if (f->fmt.pix.width < 48)
- f->fmt.pix.width = 48;
- if (f->fmt.pix.width > maxw)
- f->fmt.pix.width = maxw;
- f->fmt.pix.width &= ~0x03;
- f->fmt.pix.bytesperline =
- (f->fmt.pix.width * fmt->depth) >> 3;
- f->fmt.pix.sizeimage =
- f->fmt.pix.height * f->fmt.pix.bytesperline;
-
- return 0;
-}
-
-static int vidioc_s_fmt_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct cx23885_fh *fh = priv;
- struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
- int err;
-
- dprintk(2, "%s()\n", __FUNCTION__);
- err = vidioc_try_fmt_cap(file, priv, f);
-
- if (0 != err)
- return err;
- fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
- fh->width = f->fmt.pix.width;
- fh->height = f->fmt.pix.height;
- fh->vidq.field = f->fmt.pix.field;
- dprintk(2, "%s() width=%d height=%d field=%d\n", __FUNCTION__,
- fh->width, fh->height, fh->vidq.field);
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f);
- return 0;
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
- strcpy(cap->driver, "cx23885");
- strlcpy(cap->card, cx23885_boards[dev->board].name,
- sizeof(cap->card));
- sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
- cap->version = CX23885_VERSION_CODE;
- cap->capabilities =
- V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_READWRITE |
- V4L2_CAP_STREAMING |
- V4L2_CAP_VBI_CAPTURE;
- if (UNSET != dev->tuner_type)
- cap->capabilities |= V4L2_CAP_TUNER;
- return 0;
-}
-
-static int vidioc_enum_fmt_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- if (unlikely(f->index >= ARRAY_SIZE(formats)))
- return -EINVAL;
-
- strlcpy(f->description, formats[f->index].name,
- sizeof(f->description));
- f->pixelformat = formats[f->index].fourcc;
-
- return 0;
-}
-
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf(struct file *file, void *priv,
- struct video_mbuf *mbuf)
-{
- struct cx23885_fh *fh = priv;
- struct videobuf_queue *q;
- struct v4l2_requestbuffers req;
- unsigned int i;
- int err;
-
- q = get_queue(fh);
- memset(&req, 0, sizeof(req));
- req.type = q->type;
- req.count = 8;
- req.memory = V4L2_MEMORY_MMAP;
- err = videobuf_reqbufs(q, &req);
- if (err < 0)
- return err;
-
- mbuf->frames = req.count;
- mbuf->size = 0;
- for (i = 0; i < mbuf->frames; i++) {
- mbuf->offsets[i] = q->bufs[i]->boff;
- mbuf->size += q->bufs[i]->bsize;
- }
- return 0;
-}
-#endif
-
-static int vidioc_reqbufs(struct file *file, void *priv,
- struct v4l2_requestbuffers *p)
-{
- struct cx23885_fh *fh = priv;
- return (videobuf_reqbufs(get_queue(fh), p));
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
- struct v4l2_buffer *p)
-{
- struct cx23885_fh *fh = priv;
- return (videobuf_querybuf(get_queue(fh), p));
-}
-
-static int vidioc_qbuf(struct file *file, void *priv,
- struct v4l2_buffer *p)
-{
- struct cx23885_fh *fh = priv;
- return (videobuf_qbuf(get_queue(fh), p));
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv,
- struct v4l2_buffer *p)
-{
- struct cx23885_fh *fh = priv;
- return (videobuf_dqbuf(get_queue(fh), p,
- file->f_flags & O_NONBLOCK));
-}
-
-static int vidioc_streamon(struct file *file, void *priv,
- enum v4l2_buf_type i)
-{
- struct cx23885_fh *fh = priv;
- struct cx23885_dev *dev = fh->dev;
- dprintk(1, "%s()\n", __FUNCTION__);
-
- if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
- return -EINVAL;
- if (unlikely(i != fh->type))
- return -EINVAL;
-
- if (unlikely(!res_get(dev, fh, get_resource(fh))))
- return -EBUSY;
- return videobuf_streamon(get_queue(fh));
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
- struct cx23885_fh *fh = priv;
- struct cx23885_dev *dev = fh->dev;
- int err, res;
- dprintk(1, "%s()\n", __FUNCTION__);
-
- if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- if (i != fh->type)
- return -EINVAL;
-
- res = get_resource(fh);
- err = videobuf_streamoff(get_queue(fh));
- if (err < 0)
- return err;
- res_free(dev, fh, res);
- return 0;
-}
-
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
-{
- struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
- dprintk(1, "%s()\n", __FUNCTION__);
-
- mutex_lock(&dev->lock);
- cx23885_set_tvnorm(dev, *tvnorms);
- mutex_unlock(&dev->lock);
-
- return 0;
-}
-
-int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
-{
- static const char *iname[] = {
- [CX23885_VMUX_COMPOSITE1] = "Composite1",
- [CX23885_VMUX_COMPOSITE2] = "Composite2",
- [CX23885_VMUX_COMPOSITE3] = "Composite3",
- [CX23885_VMUX_COMPOSITE4] = "Composite4",
- [CX23885_VMUX_SVIDEO] = "S-Video",
- [CX23885_VMUX_TELEVISION] = "Television",
- [CX23885_VMUX_CABLE] = "Cable TV",
- [CX23885_VMUX_DVB] = "DVB",
- [CX23885_VMUX_DEBUG] = "for debug only",
- };
- unsigned int n;
- dprintk(1, "%s()\n", __FUNCTION__);
-
- n = i->index;
- if (n >= 4)
- return -EINVAL;
-
- if (0 == INPUT(n)->type)
- return -EINVAL;
-
- memset(i, 0, sizeof(*i));
- i->index = n;
- i->type = V4L2_INPUT_TYPE_CAMERA;
- strcpy(i->name, iname[INPUT(n)->type]);
- if ((CX23885_VMUX_TELEVISION == INPUT(n)->type) ||
- (CX23885_VMUX_CABLE == INPUT(n)->type))
- i->type = V4L2_INPUT_TYPE_TUNER;
- i->std = CX23885_NORMS;
- return 0;
-}
-EXPORT_SYMBOL(cx23885_enum_input);
-
-static int vidioc_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
-{
- struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
- dprintk(1, "%s()\n", __FUNCTION__);
- return cx23885_enum_input(dev, i);
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
- struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
- *i = dev->input;
- dprintk(1, "%s() returns %d\n", __FUNCTION__, *i);
- return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
- struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
- dprintk(1, "%s(%d)\n", __FUNCTION__, i);
-
- if (i >= 4) {
- dprintk(1, "%s() -EINVAL\n", __FUNCTION__);
- return -EINVAL;
- }
-
- mutex_lock(&dev->lock);
- cx23885_video_mux(dev, i);
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qctrl)
-{
- qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
- if (unlikely(qctrl->id == 0))
- return -EINVAL;
- return cx23885_ctrl_query(qctrl);
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctl)
-{
- struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
- return cx23885_get_control(dev, ctl);
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctl)
-{
- struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
- return cx23885_set_control(dev, ctl);
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
-{
- struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
- if (unlikely(UNSET == dev->tuner_type))
- return -EINVAL;
- if (0 != t->index)
- return -EINVAL;
-
- strcpy(t->name, "Television");
- t->type = V4L2_TUNER_ANALOG_TV;
- t->capability = V4L2_TUNER_CAP_NORM;
- t->rangehigh = 0xffffffffUL;
- t->signal = 0xffff ; /* LOCKED */
- return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
-{
- struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
- if (UNSET == dev->tuner_type)
- return -EINVAL;
- if (0 != t->index)
- return -EINVAL;
- return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct cx23885_fh *fh = priv;
- struct cx23885_dev *dev = fh->dev;
-
- if (unlikely(UNSET == dev->tuner_type))
- return -EINVAL;
-
- /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
- f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
- f->frequency = dev->freq;
-
- cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f);
-
- return 0;
-}
-
-int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
-{
- if (unlikely(UNSET == dev->tuner_type))
- return -EINVAL;
- if (unlikely(f->tuner != 0))
- return -EINVAL;
-
- mutex_lock(&dev->lock);
- dev->freq = f->frequency;
-
- cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f);
-
- /* When changing channels it is required to reset TVAUDIO */
- msleep(10);
-
- mutex_unlock(&dev->lock);
-
- return 0;
-}
-EXPORT_SYMBOL(cx23885_set_freq);
-
-static int vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct cx23885_fh *fh = priv;
- struct cx23885_dev *dev = fh->dev;
-
- if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
- return -EINVAL;
- if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
- return -EINVAL;
-
- return
- cx23885_set_freq(dev, f);
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int vidioc_g_register(struct file *file, void *fh,
- struct v4l2_register *reg)
-{
- struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
-
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
- return -EINVAL;
-
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_G_REGISTER, reg);
-
- return 0;
-}
-
-static int vidioc_s_register(struct file *file, void *fh,
- struct v4l2_register *reg)
-{
- struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
-
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
- return -EINVAL;
-
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_S_REGISTER, reg);
-
- return 0;
-}
-#endif
-
-/* ----------------------------------------------------------- */
-
-static void cx23885_vid_timeout(unsigned long data)
-{
- struct cx23885_dev *dev = (struct cx23885_dev *)data;
- struct cx23885_dmaqueue *q = &dev->vidq;
- struct cx23885_buffer *buf;
- unsigned long flags;
-
- cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]);
-
- cx_clear(VID_A_DMA_CTL, 0x11);
-
- spin_lock_irqsave(&dev->slock, flags);
- while (!list_empty(&q->active)) {
- buf = list_entry(q->active.next,
- struct cx23885_buffer, vb.queue);
- list_del(&buf->vb.queue);
- buf->vb.state = VIDEOBUF_ERROR;
- wake_up(&buf->vb.done);
- printk(KERN_ERR "%s/0: [%p/%d] timeout - dma=0x%08lx\n",
- dev->name, buf, buf->vb.i,
- (unsigned long)buf->risc.dma);
- }
- cx23885_restart_video_queue(dev, q);
- spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
-{
- u32 mask, count;
- int handled = 0;
-
- mask = cx_read(VID_A_INT_MSK);
- if (0 == (status & mask))
- return handled;
- cx_write(VID_A_INT_STAT, status);
-
- dprintk(2, "%s() status = 0x%08x\n", __FUNCTION__, status);
- /* risc op code error */
- if (status & (1 << 16)) {
- printk(KERN_WARNING "%s/0: video risc op code error\n",
- dev->name);
- cx_clear(VID_A_DMA_CTL, 0x11);
- cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]);
- }
-
- /* risc1 y */
- if (status & 0x01) {
- spin_lock(&dev->slock);
- count = cx_read(VID_A_GPCNT);
- cx23885_video_wakeup(dev, &dev->vidq, count);
- spin_unlock(&dev->slock);
- handled++;
- }
- /* risc2 y */
- if (status & 0x10) {
- dprintk(2, "stopper video\n");
- spin_lock(&dev->slock);
- cx23885_restart_video_queue(dev, &dev->vidq);
- spin_unlock(&dev->slock);
- handled++;
- }
-
- return handled;
-}
-
-/* ----------------------------------------------------------- */
-/* exported stuff */
-
-static const struct file_operations video_fops = {
- .owner = THIS_MODULE,
- .open = video_open,
- .release = video_release,
- .read = video_read,
- .poll = video_poll,
- .mmap = video_mmap,
- .ioctl = video_ioctl2,
- .compat_ioctl = v4l_compat_ioctl32,
- .llseek = no_llseek,
-};
-
-static struct video_device cx23885_vbi_template;
-static struct video_device cx23885_video_template = {
- .name = "cx23885-video",
- .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES,
- .fops = &video_fops,
- .minor = -1,
- .vidioc_querycap = vidioc_querycap,
- .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap,
- .vidioc_g_fmt_cap = vidioc_g_fmt_cap,
- .vidioc_try_fmt_cap = vidioc_try_fmt_cap,
- .vidioc_s_fmt_cap = vidioc_s_fmt_cap,
- .vidioc_g_fmt_vbi = cx23885_vbi_fmt,
- .vidioc_try_fmt_vbi = cx23885_vbi_fmt,
- .vidioc_s_fmt_vbi = cx23885_vbi_fmt,
- .vidioc_reqbufs = vidioc_reqbufs,
- .vidioc_querybuf = vidioc_querybuf,
- .vidioc_qbuf = vidioc_qbuf,
- .vidioc_dqbuf = vidioc_dqbuf,
- .vidioc_s_std = vidioc_s_std,
- .vidioc_enum_input = vidioc_enum_input,
- .vidioc_g_input = vidioc_g_input,
- .vidioc_s_input = vidioc_s_input,
- .vidioc_queryctrl = vidioc_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
- .vidioc_streamon = vidioc_streamon,
- .vidioc_streamoff = vidioc_streamoff,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
- .vidiocgmbuf = vidiocgmbuf,
-#endif
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_tuner = vidioc_s_tuner,
- .vidioc_g_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
- .vidioc_g_register = vidioc_g_register,
- .vidioc_s_register = vidioc_s_register,
-#endif
- .tvnorms = CX23885_NORMS,
- .current_norm = V4L2_STD_NTSC_M,
-};
-
-static const struct file_operations radio_fops = {
- .owner = THIS_MODULE,
- .open = video_open,
- .release = video_release,
- .ioctl = video_ioctl2,
- .compat_ioctl = v4l_compat_ioctl32,
- .llseek = no_llseek,
-};
-
-
-void cx23885_video_unregister(struct cx23885_dev *dev)
-{
- dprintk(1, "%s()\n", __FUNCTION__);
- cx_clear(PCI_INT_MSK, 1);
-
- if (dev->video_dev) {
- if (-1 != dev->video_dev->minor)
- video_unregister_device(dev->video_dev);
- else
- video_device_release(dev->video_dev);
- dev->video_dev = NULL;
-
- btcx_riscmem_free(dev->pci, &dev->vidq.stopper);
- }
-}
-
-int cx23885_video_register(struct cx23885_dev *dev)
-{
- int err;
-
- dprintk(1, "%s()\n", __FUNCTION__);
- spin_lock_init(&dev->slock);
-
- /* Initialize VBI template */
- memcpy(&cx23885_vbi_template, &cx23885_video_template,
- sizeof(cx23885_vbi_template));
- strcpy(cx23885_vbi_template.name, "cx23885-vbi");
- cx23885_vbi_template.type = VID_TYPE_TELETEXT|VID_TYPE_TUNER;
-
- dev->tvnorm = cx23885_video_template.current_norm;
-
- /* init video dma queues */
- INIT_LIST_HEAD(&dev->vidq.active);
- INIT_LIST_HEAD(&dev->vidq.queued);
- dev->vidq.timeout.function = cx23885_vid_timeout;
- dev->vidq.timeout.data = (unsigned long)dev;
- init_timer(&dev->vidq.timeout);
- cx23885_risc_stopper(dev->pci, &dev->vidq.stopper,
- VID_A_DMA_CTL, 0x11, 0x00);
-
- /* Don't enable VBI yet */
- cx_set(PCI_INT_MSK, 1);
-
-
- /* register v4l devices */
- dev->video_dev = cx23885_vdev_init(dev, dev->pci,
- &cx23885_video_template, "video");
- err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER,
- video_nr[dev->nr]);
- if (err < 0) {
- printk(KERN_INFO "%s: can't register video device\n",
- dev->name);
- goto fail_unreg;
- }
- printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n",
- dev->name, dev->video_dev->minor & 0x1f);
- /* initial device configuration */
- mutex_lock(&dev->lock);
- cx23885_set_tvnorm(dev, dev->tvnorm);
- init_controls(dev);
- cx23885_video_mux(dev, 0);
- mutex_unlock(&dev->lock);
-
- return 0;
-
-fail_unreg:
- cx23885_video_unregister(dev);
- return err;
-}
-
diff --git a/trunk/drivers/media/video/cx23885/cx23885.h b/trunk/drivers/media/video/cx23885/cx23885.h
index 7cb2179f2622..dec4dc2fcbb4 100644
--- a/trunk/drivers/media/video/cx23885/cx23885.h
+++ b/trunk/drivers/media/video/cx23885/cx23885.h
@@ -44,10 +44,6 @@
/* Max number of inputs by card */
#define MAX_CX23885_INPUT 8
-#define INPUT(nr) (&cx23885_boards[dev->board].input[nr])
-#define RESOURCE_OVERLAY 1
-#define RESOURCE_VIDEO 2
-#define RESOURCE_VBI 4
#define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */
@@ -57,62 +53,6 @@
#define CX23885_BOARD_HAUPPAUGE_HVR1800 2
#define CX23885_BOARD_HAUPPAUGE_HVR1250 3
#define CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP 4
-#define CX23885_BOARD_HAUPPAUGE_HVR1500Q 5
-#define CX23885_BOARD_HAUPPAUGE_HVR1500 6
-
-/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
-#define CX23885_NORMS (\
- V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443 | \
- V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \
- V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | \
- V4L2_STD_PAL_60 | V4L2_STD_SECAM_L | V4L2_STD_SECAM_DK)
-
-struct cx23885_fmt {
- char *name;
- u32 fourcc; /* v4l2 format id */
- int depth;
- int flags;
- u32 cxformat;
-};
-
-struct cx23885_ctrl {
- struct v4l2_queryctrl v;
- u32 off;
- u32 reg;
- u32 mask;
- u32 shift;
-};
-
-struct cx23885_tvnorm {
- char *name;
- v4l2_std_id id;
- u32 cxiformat;
- u32 cxoformat;
-};
-
-struct cx23885_fh {
- struct cx23885_dev *dev;
- enum v4l2_buf_type type;
- int radio;
- u32 resources;
-
- /* video overlay */
- struct v4l2_window win;
- struct v4l2_clip *clips;
- unsigned int nclips;
-
- /* video capture */
- struct cx23885_fmt *fmt;
- unsigned int width, height;
-
- /* vbi capture */
- struct videobuf_queue vidq;
- struct videobuf_queue vbiq;
-
- /* MPEG Encoder specifics ONLY */
- struct videobuf_queue mpegq;
- atomic_t v4l_reading;
-};
enum cx23885_itype {
CX23885_VMUX_COMPOSITE1 = 1,
@@ -152,28 +92,12 @@ struct cx23885_input {
typedef enum {
CX23885_MPEG_UNDEFINED = 0,
- CX23885_MPEG_DVB,
- CX23885_ANALOG_VIDEO,
+ CX23885_MPEG_DVB
} port_t;
struct cx23885_board {
char *name;
- port_t porta, portb, portc;
- unsigned int tuner_type;
- unsigned int radio_type;
- unsigned char tuner_addr;
- unsigned char radio_addr;
-
- /* Vendors can and do run the PCIe bridge at different
- * clock rates, driven physically by crystals on the PCBs.
- * The core has to accomodate this. This allows the user
- * to add new boards with new frequencys. The value is
- * expressed in Hz.
- *
- * The core framework will default this value based on
- * current designs, but it can vary.
- */
- u32 clk_freq;
+ port_t portb, portc;
struct cx23885_input input[MAX_CX23885_INPUT];
};
@@ -265,11 +189,6 @@ struct cx23885_dev {
u32 __iomem *lmmio;
u8 __iomem *bmmio;
int pci_irqmask;
- int hwrevision;
-
- /* This valud is board specific and is used to configure the
- * AV core so we see nice clean and stable video and audio. */
- u32 clk_freq;
/* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
struct cx23885_i2c i2c_bus[3];
@@ -291,31 +210,8 @@ struct cx23885_dev {
CX23885_BRIDGE_885 = 885,
CX23885_BRIDGE_887 = 887,
} bridge;
-
- /* Analog video */
- u32 resources;
- unsigned int input;
- u32 tvaudio;
- v4l2_std_id tvnorm;
- unsigned int tuner_type;
- unsigned char tuner_addr;
- unsigned int radio_type;
- unsigned char radio_addr;
- unsigned int has_radio;
-
- /* V4l */
- u32 freq;
- struct video_device *video_dev;
- struct video_device *vbi_dev;
- struct video_device *radio_dev;
-
- struct cx23885_dmaqueue vidq;
- struct cx23885_dmaqueue vbiq;
- spinlock_t slock;
};
-extern struct list_head cx23885_devlist;
-
#define SRAM_CH01 0 /* Video A */
#define SRAM_CH02 1 /* VBI A */
#define SRAM_CH03 2 /* Video B */
@@ -358,42 +254,19 @@ struct sram_channel {
#define cx_set(reg,bit) cx_andor((reg),(bit),(bit))
#define cx_clear(reg,bit) cx_andor((reg),(bit),0)
-/* ----------------------------------------------------------- */
-/* cx23885-core.c */
-
extern int cx23885_sram_channel_setup(struct cx23885_dev *dev,
struct sram_channel *ch,
unsigned int bpl, u32 risc);
-extern void cx23885_sram_channel_dump(struct cx23885_dev *dev,
- struct sram_channel *ch);
-
-extern int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
- u32 reg, u32 mask, u32 value);
-
-extern int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
- struct scatterlist *sglist,
- unsigned int top_offset, unsigned int bottom_offset,
- unsigned int bpl, unsigned int padding, unsigned int lines);
-
-void cx23885_cancel_buffers(struct cx23885_tsport *port);
-
-extern int cx23885_restart_queue(struct cx23885_tsport *port,
- struct cx23885_dmaqueue *q);
-
-extern void cx23885_wakeup(struct cx23885_tsport *port,
- struct cx23885_dmaqueue *q, u32 count);
-
-
/* ----------------------------------------------------------- */
-/* cx23885-cards.c */
+/* cx23885-cards.c */
+
extern struct cx23885_board cx23885_boards[];
extern const unsigned int cx23885_bcount;
extern struct cx23885_subid cx23885_subids[];
extern const unsigned int cx23885_idcount;
-extern int cx23885_tuner_callback(void *priv, int command, int arg);
extern void cx23885_card_list(struct cx23885_dev *dev);
extern int cx23885_ir_init(struct cx23885_dev *dev);
extern void cx23885_gpio_setup(struct cx23885_dev *dev);
@@ -407,50 +280,19 @@ extern int cx23885_buf_prepare(struct videobuf_queue *q,
struct cx23885_tsport *port,
struct cx23885_buffer *buf,
enum v4l2_field field);
+
extern void cx23885_buf_queue(struct cx23885_tsport *port,
struct cx23885_buffer *buf);
extern void cx23885_free_buffer(struct videobuf_queue *q,
struct cx23885_buffer *buf);
/* ----------------------------------------------------------- */
-/* cx23885-video.c */
-/* Video */
-extern int cx23885_video_register(struct cx23885_dev *dev);
-extern void cx23885_video_unregister(struct cx23885_dev *dev);
-extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status);
-
-/* ----------------------------------------------------------- */
-/* cx23885-vbi.c */
-extern int cx23885_vbi_fmt(struct file *file, void *priv,
- struct v4l2_format *f);
-extern void cx23885_vbi_timeout(unsigned long data);
-extern struct videobuf_queue_ops cx23885_vbi_qops;
-
/* cx23885-i2c.c */
extern int cx23885_i2c_register(struct cx23885_i2c *bus);
extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd,
void *arg);
-/* ----------------------------------------------------------- */
-/* tv norms */
-
-static inline unsigned int norm_maxw(v4l2_std_id norm)
-{
- return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
-}
-
-static inline unsigned int norm_maxh(v4l2_std_id norm)
-{
- return (norm & V4L2_STD_625_50) ? 576 : 480;
-}
-
-static inline unsigned int norm_swidth(v4l2_std_id norm)
-{
- return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
-}
-
-
/*
* Local variables:
* c-basic-offset: 8
diff --git a/trunk/drivers/media/video/cx25840/cx25840-audio.c b/trunk/drivers/media/video/cx25840/cx25840-audio.c
index d6421e1e8f6a..3d46a776df36 100644
--- a/trunk/drivers/media/video/cx25840/cx25840-audio.c
+++ b/trunk/drivers/media/video/cx25840/cx25840-audio.c
@@ -32,156 +32,118 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
/* common for all inputs and rates */
/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
- if (!state->is_cx23885)
- cx25840_write(client, 0x127, 0x50);
+ cx25840_write(client, 0x127, 0x50);
if (state->aud_input != CX25840_AUDIO_SERIAL) {
switch (freq) {
case 32000:
- if (state->is_cx23885) {
- /* We don't have register values
- * so avoid destroying registers. */
- break;
- }
/* VID_PLL and AUX_PLL */
- cx25840_write4(client, 0x108, 0x1006040f);
+ cx25840_write4(client, 0x108, 0x0f040610);
/* AUX_PLL_FRAC */
- cx25840_write4(client, 0x110, 0x01bb39ee);
+ cx25840_write4(client, 0x110, 0xee39bb01);
if (state->is_cx25836)
break;
/* src3/4/6_ctl = 0x0801f77f */
- cx25840_write4(client, 0x900, 0x0801f77f);
- cx25840_write4(client, 0x904, 0x0801f77f);
- cx25840_write4(client, 0x90c, 0x0801f77f);
+ cx25840_write4(client, 0x900, 0x7ff70108);
+ cx25840_write4(client, 0x904, 0x7ff70108);
+ cx25840_write4(client, 0x90c, 0x7ff70108);
break;
case 44100:
- if (state->is_cx23885) {
- /* We don't have register values
- * so avoid destroying registers. */
- break;
- }
/* VID_PLL and AUX_PLL */
- cx25840_write4(client, 0x108, 0x1009040f);
+ cx25840_write4(client, 0x108, 0x0f040910);
/* AUX_PLL_FRAC */
- cx25840_write4(client, 0x110, 0x00ec6bd6);
+ cx25840_write4(client, 0x110, 0xd66bec00);
if (state->is_cx25836)
break;
/* src3/4/6_ctl = 0x08016d59 */
- cx25840_write4(client, 0x900, 0x08016d59);
- cx25840_write4(client, 0x904, 0x08016d59);
- cx25840_write4(client, 0x90c, 0x08016d59);
+ cx25840_write4(client, 0x900, 0x596d0108);
+ cx25840_write4(client, 0x904, 0x596d0108);
+ cx25840_write4(client, 0x90c, 0x596d0108);
break;
case 48000:
- if (state->is_cx23885) {
- /* We don't have register values
- * so avoid destroying registers. */
- break;
- }
/* VID_PLL and AUX_PLL */
- cx25840_write4(client, 0x108, 0x100a040f);
+ cx25840_write4(client, 0x108, 0x0f040a10);
/* AUX_PLL_FRAC */
- cx25840_write4(client, 0x110, 0x0098d6e5);
+ cx25840_write4(client, 0x110, 0xe5d69800);
if (state->is_cx25836)
break;
/* src3/4/6_ctl = 0x08014faa */
- cx25840_write4(client, 0x900, 0x08014faa);
- cx25840_write4(client, 0x904, 0x08014faa);
- cx25840_write4(client, 0x90c, 0x08014faa);
+ cx25840_write4(client, 0x900, 0xaa4f0108);
+ cx25840_write4(client, 0x904, 0xaa4f0108);
+ cx25840_write4(client, 0x90c, 0xaa4f0108);
break;
}
} else {
switch (freq) {
case 32000:
- if (state->is_cx23885) {
- /* We don't have register values
- * so avoid destroying registers. */
- break;
- }
/* VID_PLL and AUX_PLL */
- cx25840_write4(client, 0x108, 0x1e08040f);
+ cx25840_write4(client, 0x108, 0x0f04081e);
/* AUX_PLL_FRAC */
- cx25840_write4(client, 0x110, 0x012a0869);
+ cx25840_write4(client, 0x110, 0x69082a01);
if (state->is_cx25836)
break;
/* src1_ctl = 0x08010000 */
- cx25840_write4(client, 0x8f8, 0x08010000);
+ cx25840_write4(client, 0x8f8, 0x00000108);
/* src3/4/6_ctl = 0x08020000 */
- cx25840_write4(client, 0x900, 0x08020000);
- cx25840_write4(client, 0x904, 0x08020000);
- cx25840_write4(client, 0x90c, 0x08020000);
+ cx25840_write4(client, 0x900, 0x00000208);
+ cx25840_write4(client, 0x904, 0x00000208);
+ cx25840_write4(client, 0x90c, 0x00000208);
/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
cx25840_write(client, 0x127, 0x54);
break;
case 44100:
- if (state->is_cx23885) {
- /* We don't have register values
- * so avoid destroying registers. */
- break;
- }
-
/* VID_PLL and AUX_PLL */
- cx25840_write4(client, 0x108, 0x1809040f);
+ cx25840_write4(client, 0x108, 0x0f040918);
/* AUX_PLL_FRAC */
- cx25840_write4(client, 0x110, 0x00ec6bd6);
+ cx25840_write4(client, 0x110, 0xd66bec00);
if (state->is_cx25836)
break;
/* src1_ctl = 0x08010000 */
- cx25840_write4(client, 0x8f8, 0x080160cd);
+ cx25840_write4(client, 0x8f8, 0xcd600108);
/* src3/4/6_ctl = 0x08020000 */
- cx25840_write4(client, 0x900, 0x08017385);
- cx25840_write4(client, 0x904, 0x08017385);
- cx25840_write4(client, 0x90c, 0x08017385);
+ cx25840_write4(client, 0x900, 0x85730108);
+ cx25840_write4(client, 0x904, 0x85730108);
+ cx25840_write4(client, 0x90c, 0x85730108);
break;
case 48000:
- if (!state->is_cx23885) {
- /* VID_PLL and AUX_PLL */
- cx25840_write4(client, 0x108, 0x180a040f);
+ /* VID_PLL and AUX_PLL */
+ cx25840_write4(client, 0x108, 0x0f040a18);
- /* AUX_PLL_FRAC */
- cx25840_write4(client, 0x110, 0x0098d6e5);
- }
+ /* AUX_PLL_FRAC */
+ cx25840_write4(client, 0x110, 0xe5d69800);
if (state->is_cx25836)
break;
- if (!state->is_cx23885) {
- /* src1_ctl */
- cx25840_write4(client, 0x8f8, 0x08018000);
-
- /* src3/4/6_ctl */
- cx25840_write4(client, 0x900, 0x08015555);
- cx25840_write4(client, 0x904, 0x08015555);
- cx25840_write4(client, 0x90c, 0x08015555);
- } else {
-
- cx25840_write4(client, 0x8f8, 0x0801867c);
+ /* src1_ctl = 0x08010000 */
+ cx25840_write4(client, 0x8f8, 0x00800108);
- cx25840_write4(client, 0x900, 0x08014faa);
- cx25840_write4(client, 0x904, 0x08014faa);
- cx25840_write4(client, 0x90c, 0x08014faa);
- }
+ /* src3/4/6_ctl = 0x08020000 */
+ cx25840_write4(client, 0x900, 0x55550108);
+ cx25840_write4(client, 0x904, 0x55550108);
+ cx25840_write4(client, 0x90c, 0x55550108);
break;
}
}
@@ -206,14 +168,14 @@ void cx25840_audio_set_path(struct i2c_client *client)
if (state->aud_input == CX25840_AUDIO_SERIAL) {
/* Set Path1 to Serial Audio Input */
- cx25840_write4(client, 0x8d0, 0x01011012);
+ cx25840_write4(client, 0x8d0, 0x12100101);
/* The microcontroller should not be started for the
* non-tuner inputs: autodetection is specific for
* TV audio. */
} else {
/* Set Path1 to Analog Demod Main Channel */
- cx25840_write4(client, 0x8d0, 0x1f063870);
+ cx25840_write4(client, 0x8d0, 0x7038061f);
}
set_audclk_freq(client, state->audclk_freq);
@@ -226,11 +188,6 @@ void cx25840_audio_set_path(struct i2c_client *client)
/* deassert soft reset */
cx25840_and_or(client, 0x810, ~0x1, 0x00);
-
- if (state->is_cx23885) {
- /* Ensure the controller is running when we exit */
- cx25840_and_or(client, 0x803, ~0x10, 0x10);
- }
}
static int get_volume(struct i2c_client *client)
diff --git a/trunk/drivers/media/video/cx25840/cx25840-core.c b/trunk/drivers/media/video/cx25840/cx25840-core.c
index 756a1eeb274e..15f191e170d2 100644
--- a/trunk/drivers/media/video/cx25840/cx25840-core.c
+++ b/trunk/drivers/media/video/cx25840/cx25840-core.c
@@ -13,8 +13,6 @@
* NTSC sliced VBI support by Christopher Neufeld
* with additional fixes by Hans Verkuil .
*
- * CX23885 support by Steven Toth .
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -39,7 +37,6 @@
#include
#include
#include
-#include
#include
#include "cx25840-core.h"
@@ -75,10 +72,10 @@ int cx25840_write4(struct i2c_client *client, u16 addr, u32 value)
u8 buffer[6];
buffer[0] = addr >> 8;
buffer[1] = addr & 0xff;
- buffer[2] = value & 0xff;
- buffer[3] = (value >> 8) & 0xff;
- buffer[4] = (value >> 16) & 0xff;
- buffer[5] = value >> 24;
+ buffer[2] = value >> 24;
+ buffer[3] = (value >> 16) & 0xff;
+ buffer[4] = (value >> 8) & 0xff;
+ buffer[5] = value & 0xff;
return i2c_master_send(client, buffer, 6);
}
@@ -125,6 +122,8 @@ int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask,
static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
enum cx25840_audio_input aud_input);
+static void log_audio_status(struct i2c_client *client);
+static void log_video_status(struct i2c_client *client);
/* ----------------------------------------------------------------------- */
@@ -257,96 +256,6 @@ static void cx25840_initialize(struct i2c_client *client)
cx25840_and_or(client, 0x803, ~0x10, 0x10);
}
-static void cx23885_initialize(struct i2c_client *client)
-{
- DEFINE_WAIT(wait);
- struct cx25840_state *state = i2c_get_clientdata(client);
- struct workqueue_struct *q;
-
- /* Internal Reset */
- cx25840_and_or(client, 0x102, ~0x01, 0x01);
- cx25840_and_or(client, 0x102, ~0x01, 0x00);
-
- /* Stop microcontroller */
- cx25840_and_or(client, 0x803, ~0x10, 0x00);
-
- /* DIF in reset? */
- cx25840_write(client, 0x398, 0);
-
- /* Trust the default xtal, no division */
- /* This changes for the cx23888 products */
- cx25840_write(client, 0x2, 0x76);
-
- /* Bring down the regulator for AUX clk */
- cx25840_write(client, 0x1, 0x40);
-
- /* Sys PLL frac */
- cx25840_write4(client, 0x11c, 0x01d1744c);
-
- /* Sys PLL int */
- cx25840_write4(client, 0x118, 0x00000416);
-
- /* Disable DIF bypass */
- cx25840_write4(client, 0x33c, 0x00000001);
-
- /* DIF Src phase inc */
- cx25840_write4(client, 0x340, 0x0df7df83);
-
- /* Vid PLL frac */
- cx25840_write4(client, 0x10c, 0x01b6db7b);
-
- /* Vid PLL int */
- cx25840_write4(client, 0x108, 0x00000512);
-
- /* Luma */
- cx25840_write4(client, 0x414, 0x00107d12);
-
- /* Chroma */
- cx25840_write4(client, 0x420, 0x3d008282);
-
- /* Aux PLL frac */
- cx25840_write4(client, 0x114, 0x017dbf48);
-
- /* Aux PLL int */
- cx25840_write4(client, 0x110, 0x000a030e);
-
- /* ADC2 input select */
- cx25840_write(client, 0x102, 0x10);
-
- /* VIN1 & VIN5 */
- cx25840_write(client, 0x103, 0x11);
-
- /* Enable format auto detect */
- cx25840_write(client, 0x400, 0);
- /* Fast subchroma lock */
- /* White crush, Chroma AGC & Chroma Killer enabled */
- cx25840_write(client, 0x401, 0xe8);
-
- /* Select AFE clock pad output source */
- cx25840_write(client, 0x144, 0x05);
-
- /* Do the firmware load in a work handler to prevent.
- Otherwise the kernel is blocked waiting for the
- bit-banging i2c interface to finish uploading the
- firmware. */
- INIT_WORK(&state->fw_work, cx25840_work_handler);
- init_waitqueue_head(&state->fw_wait);
- q = create_singlethread_workqueue("cx25840_fw");
- prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE);
- queue_work(q, &state->fw_work);
- schedule();
- finish_wait(&state->fw_wait, &wait);
- destroy_workqueue(q);
-
- cx25840_vbi_setup(client);
-
- /* (re)set input */
- set_input(client, state->vid_input, state->aud_input);
-
- /* start microcontroller */
- cx25840_and_or(client, 0x803, ~0x10, 0x10);
-}
-
/* ----------------------------------------------------------------------- */
static void input_change(struct i2c_client *client)
@@ -410,22 +319,9 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
vid_input <= CX25840_COMPOSITE8);
u8 reg;
- v4l_dbg(1, cx25840_debug, client,
- "decoder set video input %d, audio input %d\n",
- vid_input, aud_input);
-
- if (vid_input >= CX25840_VIN1_CH1) {
- v4l_dbg(1, cx25840_debug, client, "vid_input 0x%x\n",
- vid_input);
- reg = vid_input & 0xff;
- if ((vid_input & CX25840_SVIDEO_ON) == CX25840_SVIDEO_ON)
- is_composite = 0;
- else
- is_composite = 1;
+ v4l_dbg(1, cx25840_debug, client, "decoder set video input %d, audio input %d\n",
+ vid_input, aud_input);
- v4l_dbg(1, cx25840_debug, client, "mux cfg 0x%x comp=%d\n",
- reg, is_composite);
- } else
if (is_composite) {
reg = 0xf0 + (vid_input - CX25840_COMPOSITE1);
} else {
@@ -435,8 +331,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
if ((vid_input & ~0xff0) ||
luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA4 ||
chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) {
- v4l_err(client, "0x%04x is not a valid video input!\n",
- vid_input);
+ v4l_err(client, "0x%04x is not a valid video input!\n", vid_input);
return -EINVAL;
}
reg = 0xf0 + ((luma - CX25840_SVIDEO_LUMA1) >> 4);
@@ -449,49 +344,31 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
}
}
- /* The caller has previously prepared the correct routing
- * configuration in reg (for the cx23885) so we have no
- * need to attempt to flip bits for earlier av decoders.
- */
- if (!state->is_cx23885) {
- switch (aud_input) {
- case CX25840_AUDIO_SERIAL:
- /* do nothing, use serial audio input */
- break;
- case CX25840_AUDIO4: reg &= ~0x30; break;
- case CX25840_AUDIO5: reg &= ~0x30; reg |= 0x10; break;
- case CX25840_AUDIO6: reg &= ~0x30; reg |= 0x20; break;
- case CX25840_AUDIO7: reg &= ~0xc0; break;
- case CX25840_AUDIO8: reg &= ~0xc0; reg |= 0x40; break;
+ switch (aud_input) {
+ case CX25840_AUDIO_SERIAL:
+ /* do nothing, use serial audio input */
+ break;
+ case CX25840_AUDIO4: reg &= ~0x30; break;
+ case CX25840_AUDIO5: reg &= ~0x30; reg |= 0x10; break;
+ case CX25840_AUDIO6: reg &= ~0x30; reg |= 0x20; break;
+ case CX25840_AUDIO7: reg &= ~0xc0; break;
+ case CX25840_AUDIO8: reg &= ~0xc0; reg |= 0x40; break;
- default:
- v4l_err(client, "0x%04x is not a valid audio input!\n",
- aud_input);
- return -EINVAL;
- }
+ default:
+ v4l_err(client, "0x%04x is not a valid audio input!\n", aud_input);
+ return -EINVAL;
}
cx25840_write(client, 0x103, reg);
-
/* Set INPUT_MODE to Composite (0) or S-Video (1) */
cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02);
-
- if (!state->is_cx23885) {
- /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
- cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
- /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2&CH3 */
- if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
- cx25840_and_or(client, 0x102, ~0x4, 4);
- else
- cx25840_and_or(client, 0x102, ~0x4, 0);
- } else {
- if (is_composite)
- /* ADC2 input select channel 2 */
- cx25840_and_or(client, 0x102, ~0x2, 0);
- else
- /* ADC2 input select channel 3 */
- cx25840_and_or(client, 0x102, ~0x2, 2);
- }
+ /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
+ cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
+ /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
+ if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
+ cx25840_and_or(client, 0x102, ~0x4, 4);
+ else
+ cx25840_and_or(client, 0x102, ~0x4, 0);
state->vid_input = vid_input;
state->aud_input = aud_input;
@@ -499,25 +376,6 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
cx25840_audio_set_path(client);
input_change(client);
}
-
- if (state->is_cx23885) {
- /* Audio channel 1 src : Parallel 1 */
- cx25840_write(client, 0x124, 0x03);
-
- /* Select AFE clock pad output source */
- cx25840_write(client, 0x144, 0x05);
-
- /* I2S_IN_CTL: I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 */
- cx25840_write(client, 0x914, 0xa0);
-
- /* I2S_OUT_CTL:
- * I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1
- * I2S_OUT_MASTER_MODE = Master
- */
- cx25840_write(client, 0x918, 0xa0);
- cx25840_write(client, 0x919, 0x01);
- }
-
return 0;
}
@@ -783,200 +641,6 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
/* ----------------------------------------------------------------------- */
-static void log_video_status(struct i2c_client *client)
-{
- static const char *const fmt_strs[] = {
- "0x0",
- "NTSC-M", "NTSC-J", "NTSC-4.43",
- "PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60",
- "0x9", "0xA", "0xB",
- "SECAM",
- "0xD", "0xE", "0xF"
- };
-
- struct cx25840_state *state = i2c_get_clientdata(client);
- u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf;
- u8 gen_stat1 = cx25840_read(client, 0x40d);
- u8 gen_stat2 = cx25840_read(client, 0x40e);
- int vid_input = state->vid_input;
-
- v4l_info(client, "Video signal: %spresent\n",
- (gen_stat2 & 0x20) ? "" : "not ");
- v4l_info(client, "Detected format: %s\n",
- fmt_strs[gen_stat1 & 0xf]);
-
- v4l_info(client, "Specified standard: %s\n",
- vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
-
- if (vid_input >= CX25840_COMPOSITE1 &&
- vid_input <= CX25840_COMPOSITE8) {
- v4l_info(client, "Specified video input: Composite %d\n",
- vid_input - CX25840_COMPOSITE1 + 1);
- } else {
- v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n",
- (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
- }
-
- v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq);
-}
-
-/* ----------------------------------------------------------------------- */
-
-static void log_audio_status(struct i2c_client *client)
-{
- struct cx25840_state *state = i2c_get_clientdata(client);
- u8 download_ctl = cx25840_read(client, 0x803);
- u8 mod_det_stat0 = cx25840_read(client, 0x804);
- u8 mod_det_stat1 = cx25840_read(client, 0x805);
- u8 audio_config = cx25840_read(client, 0x808);
- u8 pref_mode = cx25840_read(client, 0x809);
- u8 afc0 = cx25840_read(client, 0x80b);
- u8 mute_ctl = cx25840_read(client, 0x8d3);
- int aud_input = state->aud_input;
- char *p;
-
- switch (mod_det_stat0) {
- case 0x00: p = "mono"; break;
- case 0x01: p = "stereo"; break;
- case 0x02: p = "dual"; break;
- case 0x04: p = "tri"; break;
- case 0x10: p = "mono with SAP"; break;
- case 0x11: p = "stereo with SAP"; break;
- case 0x12: p = "dual with SAP"; break;
- case 0x14: p = "tri with SAP"; break;
- case 0xfe: p = "forced mode"; break;
- default: p = "not defined";
- }
- v4l_info(client, "Detected audio mode: %s\n", p);
-
- switch (mod_det_stat1) {
- case 0x00: p = "not defined"; break;
- case 0x01: p = "EIAJ"; break;
- case 0x02: p = "A2-M"; break;
- case 0x03: p = "A2-BG"; break;
- case 0x04: p = "A2-DK1"; break;
- case 0x05: p = "A2-DK2"; break;
- case 0x06: p = "A2-DK3"; break;
- case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;
- case 0x08: p = "AM-L"; break;
- case 0x09: p = "NICAM-BG"; break;
- case 0x0a: p = "NICAM-DK"; break;
- case 0x0b: p = "NICAM-I"; break;
- case 0x0c: p = "NICAM-L"; break;
- case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break;
- case 0x0e: p = "IF FM Radio"; break;
- case 0x0f: p = "BTSC"; break;
- case 0x10: p = "high-deviation FM"; break;
- case 0x11: p = "very high-deviation FM"; break;
- case 0xfd: p = "unknown audio standard"; break;
- case 0xfe: p = "forced audio standard"; break;
- case 0xff: p = "no detected audio standard"; break;
- default: p = "not defined";
- }
- v4l_info(client, "Detected audio standard: %s\n", p);
- v4l_info(client, "Audio muted: %s\n",
- (state->unmute_volume >= 0) ? "yes" : "no");
- v4l_info(client, "Audio microcontroller: %s\n",
- (download_ctl & 0x10) ?
- ((mute_ctl & 0x2) ? "detecting" : "running") : "stopped");
-
- switch (audio_config >> 4) {
- case 0x00: p = "undefined"; break;
- case 0x01: p = "BTSC"; break;
- case 0x02: p = "EIAJ"; break;
- case 0x03: p = "A2-M"; break;
- case 0x04: p = "A2-BG"; break;
- case 0x05: p = "A2-DK1"; break;
- case 0x06: p = "A2-DK2"; break;
- case 0x07: p = "A2-DK3"; break;
- case 0x08: p = "A1 (6.0 MHz FM Mono)"; break;
- case 0x09: p = "AM-L"; break;
- case 0x0a: p = "NICAM-BG"; break;
- case 0x0b: p = "NICAM-DK"; break;
- case 0x0c: p = "NICAM-I"; break;
- case 0x0d: p = "NICAM-L"; break;
- case 0x0e: p = "FM radio"; break;
- case 0x0f: p = "automatic detection"; break;
- default: p = "undefined";
- }
- v4l_info(client, "Configured audio standard: %s\n", p);
-
- if ((audio_config >> 4) < 0xF) {
- switch (audio_config & 0xF) {
- case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break;
- case 0x01: p = "MONO2 (LANGUAGE B)"; break;
- case 0x02: p = "MONO3 (STEREO forced MONO)"; break;
- case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break;
- case 0x04: p = "STEREO"; break;
- case 0x05: p = "DUAL1 (AB)"; break;
- case 0x06: p = "DUAL2 (AC) (FM)"; break;
- case 0x07: p = "DUAL3 (BC) (FM)"; break;
- case 0x08: p = "DUAL4 (AC) (AM)"; break;
- case 0x09: p = "DUAL5 (BC) (AM)"; break;
- case 0x0a: p = "SAP"; break;
- default: p = "undefined";
- }
- v4l_info(client, "Configured audio mode: %s\n", p);
- } else {
- switch (audio_config & 0xF) {
- case 0x00: p = "BG"; break;
- case 0x01: p = "DK1"; break;
- case 0x02: p = "DK2"; break;
- case 0x03: p = "DK3"; break;
- case 0x04: p = "I"; break;
- case 0x05: p = "L"; break;
- case 0x06: p = "BTSC"; break;
- case 0x07: p = "EIAJ"; break;
- case 0x08: p = "A2-M"; break;
- case 0x09: p = "FM Radio"; break;
- case 0x0f: p = "automatic standard and mode detection"; break;
- default: p = "undefined";
- }
- v4l_info(client, "Configured audio system: %s\n", p);
- }
-
- if (aud_input) {
- v4l_info(client, "Specified audio input: Tuner (In%d)\n", aud_input);
- } else {
- v4l_info(client, "Specified audio input: External\n");
- }
-
- switch (pref_mode & 0xf) {
- case 0: p = "mono/language A"; break;
- case 1: p = "language B"; break;
- case 2: p = "language C"; break;
- case 3: p = "analog fallback"; break;
- case 4: p = "stereo"; break;
- case 5: p = "language AC"; break;
- case 6: p = "language BC"; break;
- case 7: p = "language AB"; break;
- default: p = "undefined";
- }
- v4l_info(client, "Preferred audio mode: %s\n", p);
-
- if ((audio_config & 0xf) == 0xf) {
- switch ((afc0 >> 3) & 0x3) {
- case 0: p = "system DK"; break;
- case 1: p = "system L"; break;
- case 2: p = "autodetect"; break;
- default: p = "undefined";
- }
- v4l_info(client, "Selected 65 MHz format: %s\n", p);
-
- switch (afc0 & 0x7) {
- case 0: p = "chroma"; break;
- case 1: p = "BTSC"; break;
- case 2: p = "EIAJ"; break;
- case 3: p = "A2-M"; break;
- case 4: p = "autodetect"; break;
- default: p = "undefined";
- }
- v4l_info(client, "Selected 45 MHz format: %s\n", p);
- }
-}
-
-/* ----------------------------------------------------------------------- */
-
static int cx25840_command(struct i2c_client *client, unsigned int cmd,
void *arg)
{
@@ -996,8 +660,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
state->is_initialized = 1;
if (state->is_cx25836)
cx25836_initialize(client);
- else if (state->is_cx23885)
- cx23885_initialize(client);
else
cx25840_initialize(client);
}
@@ -1015,7 +677,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
-
if (cmd == VIDIOC_DBG_G_REGISTER)
reg->val = cx25840_read(client, reg->reg & 0x0fff);
else
@@ -1032,26 +693,14 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
case VIDIOC_STREAMON:
v4l_dbg(1, cx25840_debug, client, "enable output\n");
- if (state->is_cx23885) {
- u8 v = (cx25840_read(client, 0x421) | 0x0b);
- cx25840_write(client, 0x421, v);
- } else {
- cx25840_write(client, 0x115,
- state->is_cx25836 ? 0x0c : 0x8c);
- cx25840_write(client, 0x116,
- state->is_cx25836 ? 0x04 : 0x07);
- }
+ cx25840_write(client, 0x115, state->is_cx25836 ? 0x0c : 0x8c);
+ cx25840_write(client, 0x116, state->is_cx25836 ? 0x04 : 0x07);
break;
case VIDIOC_STREAMOFF:
v4l_dbg(1, cx25840_debug, client, "disable output\n");
- if (state->is_cx23885) {
- u8 v = cx25840_read(client, 0x421) & ~(0x0b);
- cx25840_write(client, 0x421, v);
- } else {
- cx25840_write(client, 0x115, 0x00);
- cx25840_write(client, 0x116, 0x00);
- }
+ cx25840_write(client, 0x115, 0x00);
+ cx25840_write(client, 0x116, 0x00);
break;
case VIDIOC_LOG_STATUS:
@@ -1214,8 +863,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
case VIDIOC_INT_RESET:
if (state->is_cx25836)
cx25836_initialize(client);
- else if (state->is_cx23885)
- cx23885_initialize(client);
else
cx25840_initialize(client);
break;
@@ -1232,21 +879,35 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
/* ----------------------------------------------------------------------- */
-static int cx25840_probe(struct i2c_client *client)
+static struct i2c_driver i2c_driver_cx25840;
+
+static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
+ int kind)
{
+ struct i2c_client *client;
struct cx25840_state *state;
u32 id;
u16 device_id;
- /* Check if the adapter supports the needed features */
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return -EIO;
+ /* Check if the adapter supports the needed features
+ * Not until kernel version 2.6.11 did the bit-algo
+ * correctly report that it would do an I2C-level xfer */
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
+ return 0;
+
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == 0)
+ return -ENOMEM;
+
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &i2c_driver_cx25840;
+ snprintf(client->name, sizeof(client->name) - 1, "cx25840");
v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", client->addr << 1);
device_id = cx25840_read(client, 0x101) << 8;
device_id |= cx25840_read(client, 0x100);
- v4l_dbg(1, cx25840_debug, client, "device_id = 0x%04x\n", device_id);
/* The high byte of the device ID should be
* 0x83 for the cx2583x and 0x84 for the cx2584x */
@@ -1255,18 +916,16 @@ static int cx25840_probe(struct i2c_client *client)
}
else if ((device_id & 0xff00) == 0x8400) {
id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf);
- } else if (device_id == 0x0000) {
- id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6;
- } else if (device_id == 0x1313) {
- id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6;
}
else {
v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n");
- return -ENODEV;
+ kfree(client);
+ return 0;
}
state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL);
if (state == NULL) {
+ kfree(client);
return -ENOMEM;
}
@@ -1280,7 +939,6 @@ static int cx25840_probe(struct i2c_client *client)
i2c_set_clientdata(client, state);
state->c = client;
state->is_cx25836 = ((device_id & 0xff00) == 0x8300);
- state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313);
state->vid_input = CX25840_COMPOSITE7;
state->aud_input = CX25840_AUDIO8;
state->audclk_freq = 48000;
@@ -1291,19 +949,250 @@ static int cx25840_probe(struct i2c_client *client)
state->id = id;
state->rev = device_id;
+ i2c_attach_client(client);
+
+ return 0;
+}
+
+static int cx25840_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (adapter->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adapter, &addr_data, &cx25840_detect_client);
return 0;
}
-static int cx25840_remove(struct i2c_client *client)
+static int cx25840_detach_client(struct i2c_client *client)
{
- kfree(i2c_get_clientdata(client));
+ struct cx25840_state *state = i2c_get_clientdata(client);
+ int err;
+
+ err = i2c_detach_client(client);
+ if (err) {
+ return err;
+ }
+
+ kfree(state);
+ kfree(client);
+
return 0;
}
-static struct v4l2_i2c_driver_data v4l2_i2c_data = {
- .name = "cx25840",
- .driverid = I2C_DRIVERID_CX25840,
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_driver i2c_driver_cx25840 = {
+ .driver = {
+ .name = "cx25840",
+ },
+ .id = I2C_DRIVERID_CX25840,
+ .attach_adapter = cx25840_attach_adapter,
+ .detach_client = cx25840_detach_client,
.command = cx25840_command,
- .probe = cx25840_probe,
- .remove = cx25840_remove,
};
+
+
+static int __init m__init(void)
+{
+ return i2c_add_driver(&i2c_driver_cx25840);
+}
+
+static void __exit m__exit(void)
+{
+ i2c_del_driver(&i2c_driver_cx25840);
+}
+
+module_init(m__init);
+module_exit(m__exit);
+
+/* ----------------------------------------------------------------------- */
+
+static void log_video_status(struct i2c_client *client)
+{
+ static const char *const fmt_strs[] = {
+ "0x0",
+ "NTSC-M", "NTSC-J", "NTSC-4.43",
+ "PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60",
+ "0x9", "0xA", "0xB",
+ "SECAM",
+ "0xD", "0xE", "0xF"
+ };
+
+ struct cx25840_state *state = i2c_get_clientdata(client);
+ u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf;
+ u8 gen_stat1 = cx25840_read(client, 0x40d);
+ u8 gen_stat2 = cx25840_read(client, 0x40e);
+ int vid_input = state->vid_input;
+
+ v4l_info(client, "Video signal: %spresent\n",
+ (gen_stat2 & 0x20) ? "" : "not ");
+ v4l_info(client, "Detected format: %s\n",
+ fmt_strs[gen_stat1 & 0xf]);
+
+ v4l_info(client, "Specified standard: %s\n",
+ vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
+
+ if (vid_input >= CX25840_COMPOSITE1 &&
+ vid_input <= CX25840_COMPOSITE8) {
+ v4l_info(client, "Specified video input: Composite %d\n",
+ vid_input - CX25840_COMPOSITE1 + 1);
+ } else {
+ v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n",
+ (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
+ }
+
+ v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void log_audio_status(struct i2c_client *client)
+{
+ struct cx25840_state *state = i2c_get_clientdata(client);
+ u8 download_ctl = cx25840_read(client, 0x803);
+ u8 mod_det_stat0 = cx25840_read(client, 0x804);
+ u8 mod_det_stat1 = cx25840_read(client, 0x805);
+ u8 audio_config = cx25840_read(client, 0x808);
+ u8 pref_mode = cx25840_read(client, 0x809);
+ u8 afc0 = cx25840_read(client, 0x80b);
+ u8 mute_ctl = cx25840_read(client, 0x8d3);
+ int aud_input = state->aud_input;
+ char *p;
+
+ switch (mod_det_stat0) {
+ case 0x00: p = "mono"; break;
+ case 0x01: p = "stereo"; break;
+ case 0x02: p = "dual"; break;
+ case 0x04: p = "tri"; break;
+ case 0x10: p = "mono with SAP"; break;
+ case 0x11: p = "stereo with SAP"; break;
+ case 0x12: p = "dual with SAP"; break;
+ case 0x14: p = "tri with SAP"; break;
+ case 0xfe: p = "forced mode"; break;
+ default: p = "not defined";
+ }
+ v4l_info(client, "Detected audio mode: %s\n", p);
+
+ switch (mod_det_stat1) {
+ case 0x00: p = "not defined"; break;
+ case 0x01: p = "EIAJ"; break;
+ case 0x02: p = "A2-M"; break;
+ case 0x03: p = "A2-BG"; break;
+ case 0x04: p = "A2-DK1"; break;
+ case 0x05: p = "A2-DK2"; break;
+ case 0x06: p = "A2-DK3"; break;
+ case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;
+ case 0x08: p = "AM-L"; break;
+ case 0x09: p = "NICAM-BG"; break;
+ case 0x0a: p = "NICAM-DK"; break;
+ case 0x0b: p = "NICAM-I"; break;
+ case 0x0c: p = "NICAM-L"; break;
+ case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break;
+ case 0x0e: p = "IF FM Radio"; break;
+ case 0x0f: p = "BTSC"; break;
+ case 0x10: p = "high-deviation FM"; break;
+ case 0x11: p = "very high-deviation FM"; break;
+ case 0xfd: p = "unknown audio standard"; break;
+ case 0xfe: p = "forced audio standard"; break;
+ case 0xff: p = "no detected audio standard"; break;
+ default: p = "not defined";
+ }
+ v4l_info(client, "Detected audio standard: %s\n", p);
+ v4l_info(client, "Audio muted: %s\n",
+ (state->unmute_volume >= 0) ? "yes" : "no");
+ v4l_info(client, "Audio microcontroller: %s\n",
+ (download_ctl & 0x10) ?
+ ((mute_ctl & 0x2) ? "detecting" : "running") : "stopped");
+
+ switch (audio_config >> 4) {
+ case 0x00: p = "undefined"; break;
+ case 0x01: p = "BTSC"; break;
+ case 0x02: p = "EIAJ"; break;
+ case 0x03: p = "A2-M"; break;
+ case 0x04: p = "A2-BG"; break;
+ case 0x05: p = "A2-DK1"; break;
+ case 0x06: p = "A2-DK2"; break;
+ case 0x07: p = "A2-DK3"; break;
+ case 0x08: p = "A1 (6.0 MHz FM Mono)"; break;
+ case 0x09: p = "AM-L"; break;
+ case 0x0a: p = "NICAM-BG"; break;
+ case 0x0b: p = "NICAM-DK"; break;
+ case 0x0c: p = "NICAM-I"; break;
+ case 0x0d: p = "NICAM-L"; break;
+ case 0x0e: p = "FM radio"; break;
+ case 0x0f: p = "automatic detection"; break;
+ default: p = "undefined";
+ }
+ v4l_info(client, "Configured audio standard: %s\n", p);
+
+ if ((audio_config >> 4) < 0xF) {
+ switch (audio_config & 0xF) {
+ case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break;
+ case 0x01: p = "MONO2 (LANGUAGE B)"; break;
+ case 0x02: p = "MONO3 (STEREO forced MONO)"; break;
+ case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break;
+ case 0x04: p = "STEREO"; break;
+ case 0x05: p = "DUAL1 (AB)"; break;
+ case 0x06: p = "DUAL2 (AC) (FM)"; break;
+ case 0x07: p = "DUAL3 (BC) (FM)"; break;
+ case 0x08: p = "DUAL4 (AC) (AM)"; break;
+ case 0x09: p = "DUAL5 (BC) (AM)"; break;
+ case 0x0a: p = "SAP"; break;
+ default: p = "undefined";
+ }
+ v4l_info(client, "Configured audio mode: %s\n", p);
+ } else {
+ switch (audio_config & 0xF) {
+ case 0x00: p = "BG"; break;
+ case 0x01: p = "DK1"; break;
+ case 0x02: p = "DK2"; break;
+ case 0x03: p = "DK3"; break;
+ case 0x04: p = "I"; break;
+ case 0x05: p = "L"; break;
+ case 0x06: p = "BTSC"; break;
+ case 0x07: p = "EIAJ"; break;
+ case 0x08: p = "A2-M"; break;
+ case 0x09: p = "FM Radio"; break;
+ case 0x0f: p = "automatic standard and mode detection"; break;
+ default: p = "undefined";
+ }
+ v4l_info(client, "Configured audio system: %s\n", p);
+ }
+
+ if (aud_input) {
+ v4l_info(client, "Specified audio input: Tuner (In%d)\n", aud_input);
+ } else {
+ v4l_info(client, "Specified audio input: External\n");
+ }
+
+ switch (pref_mode & 0xf) {
+ case 0: p = "mono/language A"; break;
+ case 1: p = "language B"; break;
+ case 2: p = "language C"; break;
+ case 3: p = "analog fallback"; break;
+ case 4: p = "stereo"; break;
+ case 5: p = "language AC"; break;
+ case 6: p = "language BC"; break;
+ case 7: p = "language AB"; break;
+ default: p = "undefined";
+ }
+ v4l_info(client, "Preferred audio mode: %s\n", p);
+
+ if ((audio_config & 0xf) == 0xf) {
+ switch ((afc0 >> 3) & 0x3) {
+ case 0: p = "system DK"; break;
+ case 1: p = "system L"; break;
+ case 2: p = "autodetect"; break;
+ default: p = "undefined";
+ }
+ v4l_info(client, "Selected 65 MHz format: %s\n", p);
+
+ switch (afc0 & 0x7) {
+ case 0: p = "chroma"; break;
+ case 1: p = "BTSC"; break;
+ case 2: p = "EIAJ"; break;
+ case 3: p = "A2-M"; break;
+ case 4: p = "autodetect"; break;
+ default: p = "undefined";
+ }
+ v4l_info(client, "Selected 45 MHz format: %s\n", p);
+ }
+}
diff --git a/trunk/drivers/media/video/cx25840/cx25840-core.h b/trunk/drivers/media/video/cx25840/cx25840-core.h
index 95093edc9186..ea669b1f084d 100644
--- a/trunk/drivers/media/video/cx25840/cx25840-core.h
+++ b/trunk/drivers/media/video/cx25840/cx25840-core.h
@@ -47,7 +47,6 @@ struct cx25840_state {
u32 id;
u32 rev;
int is_cx25836;
- int is_cx23885;
int is_initialized;
wait_queue_head_t fw_wait; /* wake up when the fw load is finished */
struct work_struct fw_work; /* work entry for fw load */
diff --git a/trunk/drivers/media/video/cx25840/cx25840-firmware.c b/trunk/drivers/media/video/cx25840/cx25840-firmware.c
index 1ddf724a2c74..e852024a5ea3 100644
--- a/trunk/drivers/media/video/cx25840/cx25840-firmware.c
+++ b/trunk/drivers/media/video/cx25840/cx25840-firmware.c
@@ -24,7 +24,6 @@
#include "cx25840-core.h"
#define FWFILE "v4l-cx25840.fw"
-#define FWFILE_CX23885 "v4l-cx23885-avcore-01.fw"
/*
* Mike Isely - The FWSEND parameter controls the
@@ -93,14 +92,10 @@ static int fw_write(struct i2c_client *client, u8 * data, int size)
int cx25840_loadfw(struct i2c_client *client)
{
- struct cx25840_state *state = i2c_get_clientdata(client);
const struct firmware *fw = NULL;
u8 buffer[4], *ptr;
int size, send, retval;
- if (state->is_cx23885)
- firmware = FWFILE_CX23885;
-
if (request_firmware(&fw, firmware, FWDEV(client)) != 0) {
v4l_err(client, "unable to open firmware %s\n", firmware);
return -EINVAL;
diff --git a/trunk/drivers/media/video/cx25840/cx25840-vbi.c b/trunk/drivers/media/video/cx25840/cx25840-vbi.c
index 6828f59b9d83..ced13febed89 100644
--- a/trunk/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/trunk/drivers/media/video/cx25840/cx25840-vbi.c
@@ -180,7 +180,7 @@ void cx25840_vbi_setup(struct i2c_client *client)
fsc/1000000,fsc%1000000);
v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, "
- "vblank %i, vactive %i, vblank656 %i, src_dec %i, "
+ "vblank %i , vactive %i, vblank656 %i, src_dec %i,"
"burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
" sc 0x%06x\n",
hblank, hactive, vblank, vactive, vblank656,
diff --git a/trunk/drivers/media/video/cx88/Kconfig b/trunk/drivers/media/video/cx88/Kconfig
index 49d3813a9b48..ceb31d4a2512 100644
--- a/trunk/drivers/media/video/cx88/Kconfig
+++ b/trunk/drivers/media/video/cx88/Kconfig
@@ -8,7 +8,6 @@ config VIDEO_CX88
select VIDEO_TUNER
select VIDEO_TVEEPROM
select VIDEO_IR
- select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO
---help---
This is a video4linux driver for Conexant 2388x based
TV cards.
diff --git a/trunk/drivers/media/video/cx88/cx88-alsa.c b/trunk/drivers/media/video/cx88/cx88-alsa.c
index 8735227f7e47..40ffd7a5579a 100644
--- a/trunk/drivers/media/video/cx88/cx88-alsa.c
+++ b/trunk/drivers/media/video/cx88/cx88-alsa.c
@@ -417,7 +417,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
- buf->vb.state = VIDEOBUF_PREPARED;
+ buf->vb.state = STATE_PREPARED;
chip->buf = buf;
chip->dma_risc = dma;
diff --git a/trunk/drivers/media/video/cx88/cx88-blackbird.c b/trunk/drivers/media/video/cx88/cx88-blackbird.c
index a99e9d5950aa..f802b5653569 100644
--- a/trunk/drivers/media/video/cx88/cx88-blackbird.c
+++ b/trunk/drivers/media/video/cx88/cx88-blackbird.c
@@ -307,7 +307,7 @@ static int register_read(struct cx88_core *core, u32 address, u32 *value)
/* ------------------------------------------------------------------ */
-static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
+static int blackbird_mbox_func(void *priv, int command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
{
struct cx8802_dev *dev = priv;
unsigned long timeout;
@@ -536,12 +536,11 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
dprintk(1,"Initialize codec\n");
retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
if (retval < 0) {
-
- dev->mpeg_active = 0;
-
/* ping was not successful, reset and upload firmware */
cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
+ msleep(1);
cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */
+ msleep(1);
retval = blackbird_load_firmware(dev);
if (retval < 0)
return retval;
@@ -563,6 +562,7 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
}
dprintk(0, "Firmware version is 0x%08x\n", version);
}
+ msleep(1);
cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */
cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */
@@ -570,68 +570,40 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */
blackbird_codec_settings(dev);
+ msleep(1);
+ /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef);
+ blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0);
+ blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); */
blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
BLACKBIRD_FIELD1_SAA7115,
BLACKBIRD_FIELD2_SAA7115
);
+ /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); */
blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- return 0;
-}
-
-static int blackbird_start_codec(struct file *file, void *priv)
-{
- struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
- struct cx88_core *core = dev->core;
- /* start capturing to the host interface */
- u32 reg;
-
- int i;
- int lastchange = -1;
- int lastval = 0;
-
- for (i = 0; (i < 10) && (i < (lastchange + 4)); i++) {
- reg = cx_read(AUD_STATUS);
-
- dprintk(1, "AUD_STATUS:%dL: 0x%x\n", i, reg);
- if ((reg & 0x0F) != lastval) {
- lastval = reg & 0x0F;
- lastchange = i;
- }
- msleep(100);
- }
-
- /* unmute audio source */
- cx_clear(AUD_VOL_CTL, (1 << 6));
-
- blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0, 0);
-
/* initialize the video input */
blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
- /* start capturing to the host interface */
- blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
- BLACKBIRD_MPEG_CAPTURE,
- BLACKBIRD_RAW_BITS_NONE
- );
+ msleep(1);
- dev->mpeg_active = 1;
- return 0;
-}
+ blackbird_api_cmd(dev, CX2341X_ENC_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE);
+ msleep(1);
+ blackbird_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE);
+ msleep(1);
-static int blackbird_stop_codec(struct cx8802_dev *dev)
-{
- blackbird_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
- BLACKBIRD_END_NOW,
+ /* start capturing to the host interface */
+ /* blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, 0, 0x13); */
+ blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
BLACKBIRD_MPEG_CAPTURE,
BLACKBIRD_RAW_BITS_NONE
);
+ msleep(10);
- dev->mpeg_active = 0;
+ blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0,0);
return 0;
}
@@ -861,10 +833,6 @@ static int vidioc_s_ext_ctrls (struct file *file, void *priv,
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
-
- if (dev->mpeg_active)
- blackbird_stop_codec(dev);
-
p = dev->params;
err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS);
if (!err) {
@@ -896,9 +864,10 @@ static int vidioc_s_frequency (struct file *file, void *priv,
struct cx8802_dev *dev = fh->dev;
struct cx88_core *core = dev->core;
- if (dev->mpeg_active)
- blackbird_stop_codec(dev);
-
+ blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+ BLACKBIRD_END_NOW,
+ BLACKBIRD_MPEG_CAPTURE,
+ BLACKBIRD_RAW_BITS_NONE);
cx88_set_freq (core,f);
blackbird_initialize_codec(dev);
cx88_set_scale(dev->core, dev->width, dev->height,
@@ -1104,11 +1073,15 @@ static int mpeg_open(struct inode *inode, struct file *file)
static int mpeg_release(struct inode *inode, struct file *file)
{
struct cx8802_fh *fh = file->private_data;
- struct cx8802_dev *dev = fh->dev;
+ struct cx8802_dev *dev = NULL;
struct cx8802_driver *drv = NULL;
- if (dev->mpeg_active)
- blackbird_stop_codec(dev);
+ /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */
+ blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+ BLACKBIRD_END_NOW,
+ BLACKBIRD_MPEG_CAPTURE,
+ BLACKBIRD_RAW_BITS_NONE
+ );
cx8802_cancel_buffers(fh->dev);
/* stop mpeg capture */
@@ -1134,10 +1107,6 @@ static ssize_t
mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
{
struct cx8802_fh *fh = file->private_data;
- struct cx8802_dev *dev = fh->dev;
-
- if (!dev->mpeg_active)
- blackbird_start_codec(file, fh);
return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
file->f_flags & O_NONBLOCK);
@@ -1313,7 +1282,6 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
core->name);
host_setup(dev->core);
- blackbird_initialize_codec(dev);
blackbird_register_video(dev);
/* initial device configuration: needed ? */
diff --git a/trunk/drivers/media/video/cx88/cx88-cards.c b/trunk/drivers/media/video/cx88/cx88-cards.c
index e6b7f518c56e..a4eb6a87a761 100644
--- a/trunk/drivers/media/video/cx88/cx88-cards.c
+++ b/trunk/drivers/media/video/cx88/cx88-cards.c
@@ -26,7 +26,6 @@
#include
#include "cx88.h"
-#include "tea5767.h"
static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
@@ -246,10 +245,6 @@ static const struct cx88_board cx88_boards[] = {
}},
.radio = {
.type = CX88_RADIO,
- .vmux = 3,
- .gpio0 = 0x000040bf,
- .gpio1 = 0x000080c0,
- .gpio2 = 0x0000ff20,
},
},
[CX88_BOARD_WINFAST_DV2000] = {
@@ -302,22 +297,22 @@ static const struct cx88_board cx88_boards[] = {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0x0000bde2,
- .audioroute = 1,
+ .extadc = 1,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x0000bde6,
- .audioroute = 1,
+ .extadc = 1,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x0000bde6,
- .audioroute = 1,
+ .extadc = 1,
}},
.radio = {
.type = CX88_RADIO,
.gpio0 = 0x0000bd62,
- .audioroute = 1,
+ .extadc = 1,
},
.mpeg = CX88_MPEG_BLACKBIRD,
},
@@ -378,7 +373,7 @@ static const struct cx88_board cx88_boards[] = {
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in?
- .audioroute = 1,
+ .extadc = 1,
}},
.radio = {
.type = CX88_RADIO,
@@ -549,7 +544,7 @@ static const struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- .audioroute = 1,
+ .extadc = 1,
}},
.mpeg = CX88_MPEG_BLACKBIRD,
},
@@ -672,22 +667,22 @@ static const struct cx88_board cx88_boards[] = {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0x00009d80,
- .audioroute = 1,
+ .extadc = 1,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x00009d76,
- .audioroute = 1,
+ .extadc = 1,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x00009d76,
- .audioroute = 1,
+ .extadc = 1,
}},
.radio = {
.type = CX88_RADIO,
.gpio0 = 0x00009d00,
- .audioroute = 1,
+ .extadc = 1,
},
.mpeg = CX88_MPEG_BLACKBIRD,
},
@@ -826,23 +821,23 @@ static const struct cx88_board cx88_boards[] = {
.type = CX88_VMUX_COMPOSITE1,
.vmux = 0,
.gpio0 = 0x0000cd73,
- .audioroute = 1,
+ .extadc = 1,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 1,
.gpio0 = 0x0000cd73,
- .audioroute = 1,
+ .extadc = 1,
},{
.type = CX88_VMUX_TELEVISION,
.vmux = 3,
.gpio0 = 0x0000cdb3,
- .audioroute = 1,
+ .extadc = 1,
}},
.radio = {
.type = CX88_RADIO,
.vmux = 2,
.gpio0 = 0x0000cdf3,
- .audioroute = 1,
+ .extadc = 1,
},
.mpeg = CX88_MPEG_BLACKBIRD,
},
@@ -1110,12 +1105,12 @@ static const struct cx88_board cx88_boards[] = {
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x3de6,
- .audioroute = 1,
+ .extadc = 1,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x3de6,
- .audioroute = 1,
+ .extadc = 1,
}},
.radio = {
.type = CX88_RADIO,
@@ -1340,17 +1335,17 @@ static const struct cx88_board cx88_boards[] = {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0xe780,
- .audioroute = 1,
+ .extadc = 1,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0xe780,
- .audioroute = 2,
+ .extadc = 1,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0xe780,
- .audioroute = 2,
+ .extadc = 1,
}},
/* fixme: Add radio support */
.mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
@@ -1375,32 +1370,6 @@ static const struct cx88_board cx88_boards[] = {
.gpio0 = 0x07fa,
}},
},
- [CX88_BOARD_PINNACLE_PCTV_HD_800i] = {
- .name = "Pinnacle PCTV HD 800i",
- .tuner_type = TUNER_XC5000,
- .radio_type = UNSET,
- .tuner_addr = ADDR_UNSET,
- .radio_addr = ADDR_UNSET,
- .input = {{
- .type = CX88_VMUX_TELEVISION,
- .vmux = 0,
- .gpio0 = 0x04fb,
- .gpio1 = 0x10ff,
- },{
- .type = CX88_VMUX_COMPOSITE1,
- .vmux = 1,
- .gpio0 = 0x04fb,
- .gpio1 = 0x10ef,
- .audioroute = 1,
- },{
- .type = CX88_VMUX_SVIDEO,
- .vmux = 2,
- .gpio0 = 0x04fb,
- .gpio1 = 0x10ef,
- .audioroute = 1,
- }},
- .mpeg = CX88_MPEG_DVB,
- },
};
/* ------------------------------------------------------------------ */
@@ -1710,10 +1679,6 @@ static const struct cx88_subid cx88_subids[] = {
.subvendor = 0x1421,
.subdevice = 0x0390,
.card = CX88_BOARD_ADSTECH_PTV_390,
- },{
- .subvendor = 0x11bd,
- .subdevice = 0x0051,
- .card = CX88_BOARD_PINNACLE_PCTV_HD_800i,
},
};
@@ -1880,36 +1845,6 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
}
}
-/* ----------------------------------------------------------------------- */
-/* Tuner callback function. Currently only needed for the Pinnacle *
- * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both *
- * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c) */
-
-int cx88_tuner_callback(void *priv, int command, int arg)
-{
- struct i2c_algo_bit_data *i2c_algo = priv;
- struct cx88_core *core = i2c_algo->data;
-
- switch(core->boardnr) {
- case CX88_BOARD_PINNACLE_PCTV_HD_800i:
- if(command == 0) { /* This is the reset command from xc5000 */
- /* Reset XC5000 tuner via SYS_RSTO_pin */
- cx_write(MO_SRST_IO, 0);
- msleep(10);
- cx_write(MO_SRST_IO, 1);
- return 0;
- }
- else {
- printk(KERN_ERR
- "xc5000: unknown tuner callback command.\n");
- return -EINVAL;
- }
- break;
- }
- return 0; /* Should never be here */
-}
-EXPORT_SYMBOL(cx88_tuner_callback);
-
/* ----------------------------------------------------------------------- */
static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
@@ -2044,23 +1979,6 @@ static void cx88_card_setup(struct cx88_core *core)
core->name, i);
}
break;
- case CX88_BOARD_MSI_TVANYWHERE_MASTER:
- {
- struct v4l2_priv_tun_config tea5767_cfg;
- struct tea5767_ctrl ctl;
-
- memset(&ctl, 0, sizeof(ctl));
-
- ctl.high_cut = 1;
- ctl.st_noise = 1;
- ctl.deemph_75 = 1;
- ctl.xtal_freq = TEA5767_HIGH_LO_13MHz;
-
- tea5767_cfg.tuner = TUNER_TEA5767;
- tea5767_cfg.priv = &ctl;
-
- cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg);
- }
}
}
diff --git a/trunk/drivers/media/video/cx88/cx88-core.c b/trunk/drivers/media/video/cx88/cx88-core.c
index 01e2ac98970b..62e8dd24c5f5 100644
--- a/trunk/drivers/media/video/cx88/cx88-core.c
+++ b/trunk/drivers/media/video/cx88/cx88-core.c
@@ -220,7 +220,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
videobuf_dma_unmap(q, dma);
videobuf_dma_free(dma);
btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
- buf->vb.state = VIDEOBUF_NEEDS_INIT;
+ buf->vb.state = STATE_NEEDS_INIT;
}
/* ------------------------------------------------------------------ */
@@ -538,7 +538,7 @@ void cx88_wakeup(struct cx88_core *core,
do_gettimeofday(&buf->vb.ts);
dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
count, buf->count);
- buf->vb.state = VIDEOBUF_DONE;
+ buf->vb.state = STATE_DONE;
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
}
diff --git a/trunk/drivers/media/video/cx88/cx88-dvb.c b/trunk/drivers/media/video/cx88/cx88-dvb.c
index f7b41eb1bb5a..fce19caf9d04 100644
--- a/trunk/drivers/media/video/cx88/cx88-dvb.c
+++ b/trunk/drivers/media/video/cx88/cx88-dvb.c
@@ -40,8 +40,6 @@
#include "cx22702.h"
#include "or51132.h"
#include "lgdt330x.h"
-#include "s5h1409.h"
-#include "xc5000.h"
#include "nxt200x.h"
#include "cx24123.h"
#include "isl6421.h"
@@ -373,22 +371,6 @@ static struct cx24123_config kworld_dvbs_100_config = {
.lnb_polarity = 1,
};
-static struct s5h1409_config pinnacle_pctv_hd_800i_config = {
- .demod_address = 0x32 >> 1,
- .output_mode = S5H1409_PARALLEL_OUTPUT,
- .gpio = S5H1409_GPIO_ON,
- .qam_if = 44000,
- .inversion = S5H1409_INVERSION_OFF,
- .status_mode = S5H1409_DEMODLOCKING,
- .mpeg_timing = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
-};
-
-static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
- .i2c_address = 0x64,
- .if_khz = 5380,
- .tuner_callback = cx88_tuner_callback,
-};
-
static int dvb_register(struct cx8802_dev *dev)
{
/* init struct videobuf_dvb */
@@ -643,21 +625,6 @@ static int dvb_register(struct cx8802_dev *dev)
dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
}
break;
- case CX88_BOARD_PINNACLE_PCTV_HD_800i:
- dev->dvb.frontend = dvb_attach(s5h1409_attach,
- &pinnacle_pctv_hd_800i_config,
- &dev->core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- /* tuner_config.video_dev must point to
- * i2c_adap.algo_data
- */
- pinnacle_pctv_hd_800i_tuner_config.priv =
- dev->core->i2c_adap.algo_data;
- dvb_attach(xc5000_attach, dev->dvb.frontend,
- &dev->core->i2c_adap,
- &pinnacle_pctv_hd_800i_tuner_config);
- }
- break;
default:
printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
dev->core->name);
diff --git a/trunk/drivers/media/video/cx88/cx88-i2c.c b/trunk/drivers/media/video/cx88/cx88-i2c.c
index 566b26af523e..c8b1c50625f4 100644
--- a/trunk/drivers/media/video/cx88/cx88-i2c.c
+++ b/trunk/drivers/media/video/cx88/cx88-i2c.c
@@ -109,32 +109,26 @@ static int attach_inform(struct i2c_client *client)
if (core->board.radio_type != UNSET) {
if ((core->board.radio_addr==ADDR_UNSET)||(core->board.radio_addr==client->addr)) {
- tun_setup.mode_mask = T_RADIO;
- tun_setup.type = core->board.radio_type;
- tun_setup.addr = core->board.radio_addr;
- tun_setup.tuner_callback = cx88_tuner_callback;
+ tun_setup.mode_mask = T_RADIO;
+ tun_setup.type = core->board.radio_type;
+ tun_setup.addr = core->board.radio_addr;
+
client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup);
}
}
if (core->board.tuner_type != UNSET) {
if ((core->board.tuner_addr==ADDR_UNSET)||(core->board.tuner_addr==client->addr)) {
- tun_setup.mode_mask = T_ANALOG_TV;
- tun_setup.type = core->board.tuner_type;
- tun_setup.addr = core->board.tuner_addr;
- tun_setup.tuner_callback = cx88_tuner_callback;
+ tun_setup.mode_mask = T_ANALOG_TV;
+ tun_setup.type = core->board.tuner_type;
+ tun_setup.addr = core->board.tuner_addr;
+
client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup);
}
}
- if (core->board.tda9887_conf) {
- struct v4l2_priv_tun_config tda9887_cfg;
-
- tda9887_cfg.tuner = TUNER_TDA9887;
- tda9887_cfg.priv = &core->board.tda9887_conf;
-
- client->driver->command(client, TUNER_SET_CONFIG, &tda9887_cfg);
- }
+ if (core->board.tda9887_conf)
+ client->driver->command(client, TDA9887_SET_CONFIG, &core->board.tda9887_conf);
return 0;
}
@@ -182,7 +176,6 @@ static char *i2c_devs[128] = {
[ 0xa0 >> 1 ] = "eeprom",
[ 0xc0 >> 1 ] = "tuner (analog)",
[ 0xc2 >> 1 ] = "tuner (analog/dvb)",
- [ 0xc8 >> 1 ] = "xc5000",
};
static void do_i2c_scan(char *name, struct i2c_client *c)
diff --git a/trunk/drivers/media/video/cx88/cx88-input.c b/trunk/drivers/media/video/cx88/cx88-input.c
index bb0911b4d2f6..e52de3968c63 100644
--- a/trunk/drivers/media/video/cx88/cx88-input.c
+++ b/trunk/drivers/media/video/cx88/cx88-input.c
@@ -305,11 +305,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
ir->mask_keycode = 0xfa;
ir->polling = 50; /* ms */
break;
- case CX88_BOARD_PINNACLE_PCTV_HD_800i:
- ir_codes = ir_codes_pinnacle_pctv_hd;
- ir_type = IR_TYPE_RC5;
- ir->sampling = 1;
- break;
}
if (NULL == ir_codes) {
@@ -448,7 +443,6 @@ void cx88_ir_irq(struct cx88_core *core)
case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
case CX88_BOARD_HAUPPAUGE_HVR1100:
case CX88_BOARD_HAUPPAUGE_HVR3000:
- case CX88_BOARD_PINNACLE_PCTV_HD_800i:
ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
ir_dprintk("biphase decoded: %x\n", ircode);
if ((ircode & 0xfffff000) != 0x3000)
diff --git a/trunk/drivers/media/video/cx88/cx88-mpeg.c b/trunk/drivers/media/video/cx88/cx88-mpeg.c
index 0aedbeaf94cd..448c67380945 100644
--- a/trunk/drivers/media/video/cx88/cx88-mpeg.c
+++ b/trunk/drivers/media/video/cx88/cx88-mpeg.c
@@ -102,7 +102,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
udelay(100);
cx_write(MO_PINMUX_IO, 0x00);
- cx_write(TS_HW_SOP_CNTRL, 0x47<<16|188<<4|0x01);
+ cx_write(TS_HW_SOP_CNTRL,0x47<<16|188<<4|0x01);
switch (core->boardnr) {
case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
@@ -117,15 +117,6 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
break;
case CX88_BOARD_HAUPPAUGE_HVR1300:
break;
- case CX88_BOARD_PINNACLE_PCTV_HD_800i:
- /* Enable MPEG parallel IO and video signal pins */
- cx_write(MO_PINMUX_IO, 0x88);
- cx_write(TS_HW_SOP_CNTRL, (0x47 << 16) | (188 << 4));
- dev->ts_gen_cntrl = 5;
- cx_write(TS_SOP_STAT, 0);
- cx_write(TS_VALERR_CNTRL, 0);
- udelay(100);
- break;
default:
cx_write(TS_SOP_STAT, 0x00);
break;
@@ -204,7 +195,7 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
list_del(&buf->vb.queue);
list_add_tail(&buf->vb.queue,&q->active);
cx8802_start_dma(dev, q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(1,"[%p/%d] restart_queue - first active\n",
@@ -215,7 +206,7 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
prev->fmt == buf->fmt) {
list_del(&buf->vb.queue);
list_add_tail(&buf->vb.queue,&q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(1,"[%p/%d] restart_queue - move to active\n",
@@ -251,7 +242,7 @@ int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
if (0 != buf->vb.baddr && buf->vb.bsize < size)
return -EINVAL;
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ if (STATE_NEEDS_INIT == buf->vb.state) {
buf->vb.width = dev->ts_packet_size;
buf->vb.height = dev->ts_packet_count;
buf->vb.size = size;
@@ -263,7 +254,7 @@ int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
dma->sglist,
buf->vb.width, buf->vb.height, 0);
}
- buf->vb.state = VIDEOBUF_PREPARED;
+ buf->vb.state = STATE_PREPARED;
return 0;
fail:
@@ -285,7 +276,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
dprintk( 1, "queue is empty - first active\n" );
list_add_tail(&buf->vb.queue,&cx88q->active);
cx8802_start_dma(dev, cx88q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = cx88q->count++;
mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(1,"[%p/%d] %s - first active\n",
@@ -295,7 +286,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
dprintk( 1, "queue is not empty - append to active\n" );
prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue);
list_add_tail(&buf->vb.queue,&cx88q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = cx88q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk( 1, "[%p/%d] %s - append to active\n",
@@ -315,7 +306,7 @@ static void do_cancel_buffers(struct cx8802_dev *dev, char *reason, int restart)
while (!list_empty(&q->active)) {
buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
list_del(&buf->vb.queue);
- buf->vb.state = VIDEOBUF_ERROR;
+ buf->vb.state = STATE_ERROR;
wake_up(&buf->vb.done);
dprintk(1,"[%p/%d] %s - dma=0x%08lx\n",
buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
@@ -446,7 +437,10 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id)
return IRQ_RETVAL(handled);
}
-static int cx8802_init_common(struct cx8802_dev *dev)
+/* ----------------------------------------------------------- */
+/* exported stuff */
+
+int cx8802_init_common(struct cx8802_dev *dev)
{
struct cx88_core *core = dev->core;
int err;
@@ -494,7 +488,7 @@ static int cx8802_init_common(struct cx8802_dev *dev)
return 0;
}
-static void cx8802_fini_common(struct cx8802_dev *dev)
+void cx8802_fini_common(struct cx8802_dev *dev)
{
dprintk( 2, "cx8802_fini_common\n" );
cx8802_stop_dma(dev);
@@ -510,7 +504,7 @@ static void cx8802_fini_common(struct cx8802_dev *dev)
/* ----------------------------------------------------------- */
-static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
+int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
{
struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
@@ -536,7 +530,7 @@ static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
return 0;
}
-static int cx8802_resume_common(struct pci_dev *pci_dev)
+int cx8802_resume_common(struct pci_dev *pci_dev)
{
struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
@@ -880,6 +874,9 @@ EXPORT_SYMBOL(cx8802_buf_prepare);
EXPORT_SYMBOL(cx8802_buf_queue);
EXPORT_SYMBOL(cx8802_cancel_buffers);
+EXPORT_SYMBOL(cx8802_init_common);
+EXPORT_SYMBOL(cx8802_fini_common);
+
EXPORT_SYMBOL(cx8802_register_driver);
EXPORT_SYMBOL(cx8802_unregister_driver);
EXPORT_SYMBOL(cx8802_get_driver);
diff --git a/trunk/drivers/media/video/cx88/cx88-vbi.c b/trunk/drivers/media/video/cx88/cx88-vbi.c
index d96ecfcf393a..babb08556406 100644
--- a/trunk/drivers/media/video/cx88/cx88-vbi.c
+++ b/trunk/drivers/media/video/cx88/cx88-vbi.c
@@ -130,7 +130,7 @@ void cx8800_vbi_timeout(unsigned long data)
while (!list_empty(&q->active)) {
buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
list_del(&buf->vb.queue);
- buf->vb.state = VIDEOBUF_ERROR;
+ buf->vb.state = STATE_ERROR;
wake_up(&buf->vb.done);
printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name,
buf, buf->vb.i, (unsigned long)buf->risc.dma);
@@ -168,7 +168,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
if (0 != buf->vb.baddr && buf->vb.bsize < size)
return -EINVAL;
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ if (STATE_NEEDS_INIT == buf->vb.state) {
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
buf->vb.width = VBI_LINE_LENGTH;
buf->vb.height = VBI_LINE_COUNT;
@@ -183,7 +183,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
buf->vb.width, 0,
buf->vb.height);
}
- buf->vb.state = VIDEOBUF_PREPARED;
+ buf->vb.state = STATE_PREPARED;
return 0;
fail:
@@ -207,7 +207,7 @@ vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
if (list_empty(&q->active)) {
list_add_tail(&buf->vb.queue,&q->active);
cx8800_start_vbi_dma(dev, q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(2,"[%p/%d] vbi_queue - first active\n",
@@ -216,7 +216,7 @@ vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
} else {
prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
list_add_tail(&buf->vb.queue,&q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2,"[%p/%d] buffer_queue - append to active\n",
diff --git a/trunk/drivers/media/video/cx88/cx88-video.c b/trunk/drivers/media/video/cx88/cx88-video.c
index 7f1931aed207..c84dafbdb991 100644
--- a/trunk/drivers/media/video/cx88/cx88-video.c
+++ b/trunk/drivers/media/video/cx88/cx88-video.c
@@ -392,41 +392,13 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input)
break;
}
- /* if there are audioroutes defined, we have an external
- ADC to deal with audio */
-
- if (INPUT(input).audioroute) {
-
- /* cx2388's C-ADC is connected to the tuner only.
- When used with S-Video, that ADC is busy dealing with
- chroma, so an external must be used for baseband audio */
-
- if (INPUT(input).type != CX88_VMUX_TELEVISION &&
- INPUT(input).type != CX88_RADIO) {
- /* "ADC mode" */
- cx_write(AUD_I2SCNTL, 0x1);
+ if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
+ /* sets sound input from external adc */
+ if (INPUT(input).extadc)
cx_set(AUD_CTL, EN_I2SIN_ENABLE);
- } else {
- /* Normal mode */
- cx_write(AUD_I2SCNTL, 0x0);
+ else
cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
- }
-
- /* The wm8775 module has the "2" route hardwired into
- the initialization. Some boards may use different
- routes for different inputs. HVR-1300 surely does */
- if (core->board.audio_chip &&
- core->board.audio_chip == AUDIO_CHIP_WM8775) {
- struct v4l2_routing route;
-
- route.input = INPUT(input).audioroute;
- cx88_call_i2c_clients(core,
- VIDIOC_INT_S_AUDIO_ROUTING, &route);
-
- }
-
}
-
return 0;
}
EXPORT_SYMBOL(cx88_video_mux);
@@ -514,7 +486,7 @@ static int restart_video_queue(struct cx8800_dev *dev,
if (NULL == prev) {
list_move_tail(&buf->vb.queue, &q->active);
start_video_dma(dev, q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(2,"[%p/%d] restart_queue - first active\n",
@@ -524,7 +496,7 @@ static int restart_video_queue(struct cx8800_dev *dev,
prev->vb.height == buf->vb.height &&
prev->fmt == buf->fmt) {
list_move_tail(&buf->vb.queue, &q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2,"[%p/%d] restart_queue - move to active\n",
@@ -581,7 +553,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
init_buffer = 1;
}
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ if (STATE_NEEDS_INIT == buf->vb.state) {
init_buffer = 1;
if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
goto fail;
@@ -629,7 +601,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
fh->width, fh->height, fh->fmt->depth, fh->fmt->name,
(unsigned long)buf->risc.dma);
- buf->vb.state = VIDEOBUF_PREPARED;
+ buf->vb.state = STATE_PREPARED;
return 0;
fail:
@@ -653,14 +625,14 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
if (!list_empty(&q->queued)) {
list_add_tail(&buf->vb.queue,&q->queued);
- buf->vb.state = VIDEOBUF_QUEUED;
+ buf->vb.state = STATE_QUEUED;
dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
buf, buf->vb.i);
} else if (list_empty(&q->active)) {
list_add_tail(&buf->vb.queue,&q->active);
start_video_dma(dev, q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(2,"[%p/%d] buffer_queue - first active\n",
@@ -672,7 +644,7 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
prev->vb.height == buf->vb.height &&
prev->fmt == buf->fmt) {
list_add_tail(&buf->vb.queue,&q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2,"[%p/%d] buffer_queue - append to active\n",
@@ -680,7 +652,7 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
} else {
list_add_tail(&buf->vb.queue,&q->queued);
- buf->vb.state = VIDEOBUF_QUEUED;
+ buf->vb.state = STATE_QUEUED;
dprintk(2,"[%p/%d] buffer_queue - first queued\n",
buf, buf->vb.i);
}
@@ -850,8 +822,8 @@ video_poll(struct file *file, struct poll_table_struct *wait)
return POLLERR;
}
poll_wait(file, &buf->vb.done, wait);
- if (buf->vb.state == VIDEOBUF_DONE ||
- buf->vb.state == VIDEOBUF_ERROR)
+ if (buf->vb.state == STATE_DONE ||
+ buf->vb.state == STATE_ERROR)
return POLLIN|POLLRDNORM;
return 0;
}
@@ -1524,7 +1496,7 @@ static void cx8800_vid_timeout(unsigned long data)
while (!list_empty(&q->active)) {
buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
list_del(&buf->vb.queue);
- buf->vb.state = VIDEOBUF_ERROR;
+ buf->vb.state = STATE_ERROR;
wake_up(&buf->vb.done);
printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name,
buf, buf->vb.i, (unsigned long)buf->risc.dma);
diff --git a/trunk/drivers/media/video/cx88/cx88.h b/trunk/drivers/media/video/cx88/cx88.h
index 4e823f2a539a..eb296bdecb1e 100644
--- a/trunk/drivers/media/video/cx88/cx88.h
+++ b/trunk/drivers/media/video/cx88/cx88.h
@@ -210,7 +210,6 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_TE_DTV_250_OEM_SWANN 55
#define CX88_BOARD_HAUPPAUGE_HVR1300 56
#define CX88_BOARD_ADSTECH_PTV_390 57
-#define CX88_BOARD_PINNACLE_PCTV_HD_800i 58
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
@@ -229,7 +228,7 @@ struct cx88_input {
enum cx88_itype type;
u32 gpio0, gpio1, gpio2, gpio3;
unsigned int vmux:2;
- unsigned int audioroute:2;
+ unsigned int extadc:1;
};
struct cx88_board {
@@ -462,7 +461,6 @@ struct cx8802_dev {
u32 mailbox;
int width;
int height;
- unsigned char mpeg_active; /* nonzero if mpeg encoder is active */
/* mpeg params */
struct cx2341x_mpeg_params params;
@@ -590,7 +588,6 @@ extern void cx88_call_i2c_clients(struct cx88_core *core,
/* ----------------------------------------------------------- */
/* cx88-cards.c */
-extern int cx88_tuner_callback(void *dev, int command, int arg);
extern int cx88_get_resources(const struct cx88_core *core,
struct pci_dev *pci);
extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr);
@@ -636,6 +633,12 @@ int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev,
void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
void cx8802_cancel_buffers(struct cx8802_dev *dev);
+int cx8802_init_common(struct cx8802_dev *dev);
+void cx8802_fini_common(struct cx8802_dev *dev);
+
+int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state);
+int cx8802_resume_common(struct pci_dev *pci_dev);
+
/* ----------------------------------------------------------- */
/* cx88-video.c*/
extern const u32 cx88_user_ctrls[];
diff --git a/trunk/drivers/media/video/em28xx/Kconfig b/trunk/drivers/media/video/em28xx/Kconfig
index abbd38c1ebba..c1127802ad9c 100644
--- a/trunk/drivers/media/video/em28xx/Kconfig
+++ b/trunk/drivers/media/video/em28xx/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_EM28XX
tristate "Empia EM2800/2820/2840 USB video capture support"
- depends on VIDEO_DEV && I2C && INPUT
+ depends on VIDEO_V4L1 && I2C && INPUT
select VIDEO_TUNER
select VIDEO_TVEEPROM
select VIDEO_IR
@@ -11,18 +11,3 @@ config VIDEO_EM28XX
To compile this driver as a module, choose M here: the
module will be called em28xx
-
-config VIDEO_EM28XX_ALSA
- depends on VIDEO_EM28XX
- tristate "Empia EM28xx ALSA audio module"
- ---help---
- This is an ALSA driver for some Empia 28xx based TV cards.
-
- This is not required for em2800/em2820/em2821 boards. However,
- newer em28xx devices uses Vendor Class for audio, instead of
- implementing the USB Audio Class. For those chips, this module
- will enable digital audio.
-
- To compile this driver as a module, choose M here: the
- module will be called em28xx-alsa
-
diff --git a/trunk/drivers/media/video/em28xx/Makefile b/trunk/drivers/media/video/em28xx/Makefile
index 0924550992d0..826d0e340753 100644
--- a/trunk/drivers/media/video/em28xx/Makefile
+++ b/trunk/drivers/media/video/em28xx/Makefile
@@ -1,12 +1,6 @@
em28xx-objs := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-core.o \
em28xx-input.o
-em28xx-alsa-objs := em28xx-audio.o
-
obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
-obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-
diff --git a/trunk/drivers/media/video/em28xx/em28xx-audio.c b/trunk/drivers/media/video/em28xx/em28xx-audio.c
deleted file mode 100644
index 941357c4f3f5..000000000000
--- a/trunk/drivers/media/video/em28xx/em28xx-audio.c
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Empiatech em28x1 audio extension
- *
- * Copyright (C) 2006 Markus Rechberger
- *
- * Copyright (C) 2007 Mauro Carvalho Chehab
- * - Port to work with the in-kernel driver
- * - Several cleanups
- *
- * This driver is based on my previous au600 usb pstn audio driver
- * and inherits all the copyrights
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "em28xx.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "activates debug info");
-
-#define dprintk(fmt, arg...) do { \
- if (debug) \
- printk(KERN_INFO "em28xx-audio %s: " fmt, \
- __FUNCTION__, ##arg); \
- } while (0)
-
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
-
-static int em28xx_isoc_audio_deinit(struct em28xx *dev)
-{
- int i;
-
- dprintk("Stopping isoc\n");
- for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
- usb_kill_urb(dev->adev->urb[i]);
- usb_free_urb(dev->adev->urb[i]);
- dev->adev->urb[i] = NULL;
- }
-
- return 0;
-}
-
-static void em28xx_audio_isocirq(struct urb *urb)
-{
- struct em28xx *dev = urb->context;
- int i;
- unsigned int oldptr;
- unsigned long flags;
- int period_elapsed = 0;
- int status;
- unsigned char *cp;
- unsigned int stride;
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- if (dev->adev->capture_pcm_substream) {
- substream = dev->adev->capture_pcm_substream;
- runtime = substream->runtime;
- stride = runtime->frame_bits >> 3;
-
- for (i = 0; i < urb->number_of_packets; i++) {
- int length =
- urb->iso_frame_desc[i].actual_length / stride;
- cp = (unsigned char *)urb->transfer_buffer +
- urb->iso_frame_desc[i].offset;
-
- if (!length)
- continue;
-
- spin_lock_irqsave(&dev->adev->slock, flags);
-
- oldptr = dev->adev->hwptr_done_capture;
- dev->adev->hwptr_done_capture += length;
- if (dev->adev->hwptr_done_capture >=
- runtime->buffer_size)
- dev->adev->hwptr_done_capture -=
- runtime->buffer_size;
-
- dev->adev->capture_transfer_done += length;
- if (dev->adev->capture_transfer_done >=
- runtime->period_size) {
- dev->adev->capture_transfer_done -=
- runtime->period_size;
- period_elapsed = 1;
- }
-
- spin_unlock_irqrestore(&dev->adev->slock, flags);
-
- if (oldptr + length >= runtime->buffer_size) {
- unsigned int cnt =
- runtime->buffer_size - oldptr - 1;
- memcpy(runtime->dma_area + oldptr * stride, cp,
- cnt * stride);
- memcpy(runtime->dma_area, cp + cnt,
- length * stride - cnt * stride);
- } else {
- memcpy(runtime->dma_area + oldptr * stride, cp,
- length * stride);
- }
- }
- if (period_elapsed)
- snd_pcm_period_elapsed(substream);
- }
- urb->status = 0;
-
- if (dev->adev->shutdown)
- return;
-
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status < 0) {
- em28xx_errdev("resubmit of audio urb failed (error=%i)\n",
- status);
- }
- return;
-}
-
-static int em28xx_init_audio_isoc(struct em28xx *dev)
-{
- int i, errCode;
- const int sb_size = EM28XX_NUM_AUDIO_PACKETS *
- EM28XX_AUDIO_MAX_PACKET_SIZE;
-
- dprintk("Starting isoc transfers\n");
-
- for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
- struct urb *urb;
- int j, k;
-
- dev->adev->transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
- if (!dev->adev->transfer_buffer[i])
- return -ENOMEM;
-
- memset(dev->adev->transfer_buffer[i], 0x80, sb_size);
- urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
- if (!urb)
- return -ENOMEM;
-
- urb->dev = dev->udev;
- urb->context = dev;
- urb->pipe = usb_rcvisocpipe(dev->udev, 0x83);
- urb->transfer_flags = URB_ISO_ASAP;
- urb->transfer_buffer = dev->adev->transfer_buffer[i];
- urb->interval = 1;
- urb->complete = em28xx_audio_isocirq;
- urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS;
- urb->transfer_buffer_length = sb_size;
-
- for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS;
- j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) {
- urb->iso_frame_desc[j].offset = k;
- urb->iso_frame_desc[j].length =
- EM28XX_AUDIO_MAX_PACKET_SIZE;
- }
- dev->adev->urb[i] = urb;
- }
-
- for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
- errCode = usb_submit_urb(dev->adev->urb[i], GFP_ATOMIC);
- if (errCode) {
- em28xx_isoc_audio_deinit(dev);
-
- return errCode;
- }
- }
-
- return 0;
-}
-
-static int em28xx_cmd(struct em28xx *dev, int cmd, int arg)
-{
- dprintk("%s transfer\n", (dev->adev->capture_stream == STREAM_ON)?
- "stop" : "start");
-
- switch (cmd) {
- case EM28XX_CAPTURE_STREAM_EN:
- if (dev->adev->capture_stream == STREAM_OFF && arg == 1) {
- dev->adev->capture_stream = STREAM_ON;
- em28xx_init_audio_isoc(dev);
- } else if (dev->adev->capture_stream == STREAM_ON && arg == 0) {
- dev->adev->capture_stream = STREAM_OFF;
- em28xx_isoc_audio_deinit(dev);
- } else {
- printk(KERN_ERR "An underrun very likely occurred. "
- "Ignoring it.\n");
- }
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
- size_t size)
-{
- struct snd_pcm_runtime *runtime = subs->runtime;
-
- dprintk("Alocating vbuffer\n");
- if (runtime->dma_area) {
- if (runtime->dma_bytes > size)
- return 0;
-
- vfree(runtime->dma_area);
- }
- runtime->dma_area = vmalloc(size);
- if (!runtime->dma_area)
- return -ENOMEM;
-
- runtime->dma_bytes = size;
-
- return 0;
-}
-
-static struct snd_pcm_hardware snd_em28xx_hw_capture = {
- .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID,
-
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
-
- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
-
- .rate_min = 48000,
- .rate_max = 48000,
- .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */
- .period_bytes_min = 64, /* 12544/2, */
- .period_bytes_max = 12544,
- .periods_min = 2,
- .periods_max = 98, /* 12544, */
-};
-
-static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
-{
- struct em28xx *dev = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- int ret = 0;
-
- dprintk("opening device and trying to acquire exclusive lock\n");
-
- /* Sets volume, mute, etc */
- dev->mute = 0;
- ret = em28xx_audio_analog_set(dev);
- if (ret < 0)
- goto err;
-
- runtime->hw = snd_em28xx_hw_capture;
- if (dev->alt == 0 && dev->adev->users == 0) {
- int errCode;
- dev->alt = 7;
- errCode = usb_set_interface(dev->udev, 0, 7);
- dprintk("changing alternate number to 7\n");
- }
-
- dev->adev->users++;
-
- snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
- dev->adev->capture_pcm_substream = substream;
- runtime->private_data = dev;
-
- return 0;
-err:
- printk(KERN_ERR "Error while configuring em28xx mixer\n");
- return ret;
-}
-
-static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
-{
- struct em28xx *dev = snd_pcm_substream_chip(substream);
- dev->adev->users--;
-
- dprintk("closing device\n");
-
- dev->mute = 1;
- em28xx_audio_analog_set(dev);
-
- if (dev->adev->users == 0 && dev->adev->shutdown == 1) {
- dprintk("audio users: %d\n", dev->adev->users);
- dprintk("disabling audio stream!\n");
- dev->adev->shutdown = 0;
- dprintk("released lock\n");
- em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0);
- }
- return 0;
-}
-
-static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- unsigned int channels, rate, format;
- int ret;
-
- dprintk("Setting capture parameters\n");
-
- ret = snd_pcm_alloc_vmalloc_buffer(substream,
- params_buffer_bytes(hw_params));
- format = params_format(hw_params);
- rate = params_rate(hw_params);
- channels = params_channels(hw_params);
-
- /* TODO: set up em28xx audio chip to deliver the correct audio format,
- current default is 48000hz multiplexed => 96000hz mono
- which shouldn't matter since analogue TV only supports mono */
- return 0;
-}
-
-static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream)
-{
- struct em28xx *dev = snd_pcm_substream_chip(substream);
-
- dprintk("Stop capture, if needed\n");
-
- if (dev->adev->capture_stream == STREAM_ON)
- em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0);
-
- return 0;
-}
-
-static int snd_em28xx_prepare(struct snd_pcm_substream *substream)
-{
- return 0;
-}
-
-static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream,
- int cmd)
-{
- struct em28xx *dev = snd_pcm_substream_chip(substream);
-
- dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START)?
- "start": "stop");
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1);
- return 0;
- case SNDRV_PCM_TRIGGER_STOP:
- dev->adev->shutdown = 1;
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream
- *substream)
-{
- struct em28xx *dev;
-
- snd_pcm_uframes_t hwptr_done;
- dev = snd_pcm_substream_chip(substream);
- hwptr_done = dev->adev->hwptr_done_capture;
-
- return hwptr_done;
-}
-
-static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
- unsigned long offset)
-{
- void *pageptr = subs->runtime->dma_area + offset;
-
- return vmalloc_to_page(pageptr);
-}
-
-static struct snd_pcm_ops snd_em28xx_pcm_capture = {
- .open = snd_em28xx_capture_open,
- .close = snd_em28xx_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_em28xx_hw_capture_params,
- .hw_free = snd_em28xx_hw_capture_free,
- .prepare = snd_em28xx_prepare,
- .trigger = snd_em28xx_capture_trigger,
- .pointer = snd_em28xx_capture_pointer,
- .page = snd_pcm_get_vmalloc_page,
-};
-
-static int em28xx_audio_init(struct em28xx *dev)
-{
- struct em28xx_audio *adev;
- struct snd_pcm *pcm;
- struct snd_card *card;
- static int devnr;
- int ret, err;
-
- printk(KERN_INFO "em28xx-audio.c: probing for em28x1 "
- "non standard usbaudio\n");
- printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
- "Rechberger\n");
-
- adev = kzalloc(sizeof(*adev), GFP_KERNEL);
- if (!adev) {
- printk(KERN_ERR "em28xx-audio.c: out of memory\n");
- return -1;
- }
- card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0);
- if (card == NULL) {
- kfree(adev);
- return -ENOMEM;
- }
-
- spin_lock_init(&adev->slock);
- ret = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_em28xx_pcm_capture);
- pcm->info_flags = 0;
- pcm->private_data = dev;
- strcpy(pcm->name, "Empia 28xx Capture");
- strcpy(card->driver, "Empia Em28xx Audio");
- strcpy(card->shortname, "Em28xx Audio");
- strcpy(card->longname, "Empia Em28xx Audio");
-
- err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
- return -ENOMEM;
- }
- adev->sndcard = card;
- adev->udev = dev->udev;
- dev->adev = adev;
-
- return 0;
-}
-
-static int em28xx_audio_fini(struct em28xx *dev)
-{
- if (dev == NULL)
- return 0;
-
- if (dev->adev) {
- snd_card_free(dev->adev->sndcard);
- kfree(dev->adev);
- dev->adev = NULL;
- }
-
- return 0;
-}
-
-static struct em28xx_ops audio_ops = {
- .id = EM28XX_AUDIO,
- .name = "Em28xx Audio Extension",
- .init = em28xx_audio_init,
- .fini = em28xx_audio_fini,
-};
-
-static int __init em28xx_alsa_register(void)
-{
- return em28xx_register_extension(&audio_ops);
-}
-
-static void __exit em28xx_alsa_unregister(void)
-{
- em28xx_unregister_extension(&audio_ops);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Markus Rechberger ");
-MODULE_AUTHOR("Mauro Carvalho Chehab ");
-MODULE_DESCRIPTION("Em28xx Audio driver");
-
-module_init(em28xx_alsa_register);
-module_exit(em28xx_alsa_unregister);
diff --git a/trunk/drivers/media/video/em28xx/em28xx-cards.c b/trunk/drivers/media/video/em28xx/em28xx-cards.c
index 2159d0160df2..418ea8b7f85a 100644
--- a/trunk/drivers/media/video/em28xx/em28xx-cards.c
+++ b/trunk/drivers/media/video/em28xx/em28xx-cards.c
@@ -1,6 +1,5 @@
/*
- em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB
- video capture devices
+ em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
Copyright (C) 2005 Ludovico Cavedon
Markus Rechberger
@@ -36,735 +35,294 @@
#include
#include "em28xx.h"
-#include "tuner-xc2028.h"
-
-static int tuner = -1;
-module_param(tuner, int, 0444);
-MODULE_PARM_DESC(tuner, "tuner type");
-
-static unsigned int disable_ir;
-module_param(disable_ir, int, 0444);
-MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
-
-struct em28xx_hash_table {
- unsigned long hash;
- unsigned int model;
- unsigned int tuner;
-};
-
-/* Boards supported by driver */
-
-#define EM2800_BOARD_UNKNOWN 0
-#define EM2820_BOARD_UNKNOWN 1
-#define EM2820_BOARD_TERRATEC_CINERGY_250 2
-#define EM2820_BOARD_PINNACLE_USB_2 3
-#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4
-#define EM2820_BOARD_MSI_VOX_USB_2 5
-#define EM2800_BOARD_TERRATEC_CINERGY_200 6
-#define EM2800_BOARD_LEADTEK_WINFAST_USBII 7
-#define EM2800_BOARD_KWORLD_USB2800 8
-#define EM2820_BOARD_PINNACLE_DVC_90 9
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 10
-#define EM2880_BOARD_TERRATEC_HYBRID_XS 11
-#define EM2820_BOARD_KWORLD_PVRTV2800RF 12
-#define EM2880_BOARD_TERRATEC_PRODIGY_XS 13
-#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14
-#define EM2800_BOARD_VGEAR_POCKETTV 15
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16
struct em28xx_board em28xx_boards[] = {
[EM2800_BOARD_UNKNOWN] = {
.name = "Unknown EM2800 video grabber",
.is_em2800 = 1,
.vchannels = 2,
+ .norm = VIDEO_MODE_PAL,
.tda9887_conf = TDA9887_PRESENT,
+ .has_tuner = 1,
.decoder = EM28XX_SAA7113,
- .input = { {
+ .input = {{
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = SAA7115_COMPOSITE0,
.amux = 1,
- }, {
+ },{
.type = EM28XX_VMUX_SVIDEO,
.vmux = SAA7115_SVIDEO3,
.amux = 1,
- } },
+ }},
},
[EM2820_BOARD_UNKNOWN] = {
- .name = "Unknown EM2750/28xx video grabber",
+ .name = "Unknown EM2820/2840 video grabber",
.is_em2800 = 0,
- .tuner_type = TUNER_ABSENT,
+ .vchannels = 2,
+ .norm = VIDEO_MODE_PAL,
+ .tda9887_conf = TDA9887_PRESENT,
+ .has_tuner = 1,
+ .decoder = EM28XX_SAA7113,
+ .input = {{
+ .type = EM28XX_VMUX_COMPOSITE1,
+ .vmux = SAA7115_COMPOSITE0,
+ .amux = 1,
+ },{
+ .type = EM28XX_VMUX_SVIDEO,
+ .vmux = SAA7115_SVIDEO3,
+ .amux = 1,
+ }},
},
[EM2820_BOARD_KWORLD_PVRTV2800RF] = {
.name = "Kworld PVR TV 2800 RF",
.is_em2800 = 0,
.vchannels = 2,
- .tuner_type = TUNER_TEMIC_PAL,
+ .norm = VIDEO_MODE_PAL,
.tda9887_conf = TDA9887_PRESENT,
+ .has_tuner = 1,
.decoder = EM28XX_SAA7113,
- .input = { {
+ .input = {{
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = SAA7115_COMPOSITE0,
.amux = 1,
- }, {
+ },{
.type = EM28XX_VMUX_SVIDEO,
.vmux = SAA7115_SVIDEO3,
.amux = 1,
- } },
+ }},
},
[EM2820_BOARD_TERRATEC_CINERGY_250] = {
.name = "Terratec Cinergy 250 USB",
.vchannels = 3,
+ .norm = VIDEO_MODE_PAL,
.tuner_type = TUNER_LG_PAL_NEW_TAPC,
.tda9887_conf = TDA9887_PRESENT,
+ .has_tuner = 1,
.decoder = EM28XX_SAA7113,
- .input = { {
+ .input = {{
.type = EM28XX_VMUX_TELEVISION,
.vmux = SAA7115_COMPOSITE2,
.amux = 1,
- }, {
+ },{
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = SAA7115_COMPOSITE0,
.amux = 1,
- }, {
+ },{
.type = EM28XX_VMUX_SVIDEO,
.vmux = SAA7115_SVIDEO3,
.amux = 1,
- } },
+ }},
},
[EM2820_BOARD_PINNACLE_USB_2] = {
.name = "Pinnacle PCTV USB 2",
.vchannels = 3,
+ .norm = VIDEO_MODE_PAL,
.tuner_type = TUNER_LG_PAL_NEW_TAPC,
.tda9887_conf = TDA9887_PRESENT,
+ .has_tuner = 1,
.decoder = EM28XX_SAA7113,
- .input = { {
+ .input = {{
.type = EM28XX_VMUX_TELEVISION,
.vmux = SAA7115_COMPOSITE2,
.amux = 0,
- }, {
+ },{
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = SAA7115_COMPOSITE0,
.amux = 1,
- }, {
+ },{
.type = EM28XX_VMUX_SVIDEO,
.vmux = SAA7115_SVIDEO3,
.amux = 1,
- } },
+ }},
},
[EM2820_BOARD_HAUPPAUGE_WINTV_USB_2] = {
.name = "Hauppauge WinTV USB 2",
.vchannels = 3,
+ .norm = VIDEO_MODE_NTSC,
.tuner_type = TUNER_PHILIPS_FM1236_MK3,
- .tda9887_conf = TDA9887_PRESENT |
- TDA9887_PORT1_ACTIVE|
- TDA9887_PORT2_ACTIVE,
+ .tda9887_conf = TDA9887_PRESENT|TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE,
+ .has_tuner = 1,
.decoder = EM28XX_TVP5150,
.has_msp34xx = 1,
/*FIXME: S-Video not tested */
- .input = { {
+ .input = {{
.type = EM28XX_VMUX_TELEVISION,
.vmux = TVP5150_COMPOSITE0,
.amux = MSP_INPUT_DEFAULT,
- }, {
+ },{
.type = EM28XX_VMUX_SVIDEO,
.vmux = TVP5150_SVIDEO,
.amux = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
MSP_DSP_IN_SCART, MSP_DSP_IN_SCART),
- } },
- },
- [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = {
- .name = "Hauppauge WinTV HVR 900",
- .vchannels = 3,
- .tda9887_conf = TDA9887_PRESENT,
- .tuner_type = TUNER_XC2028,
- .mts_firmware = 1,
- .decoder = EM28XX_TVP5150,
- .input = { {
- .type = EM28XX_VMUX_TELEVISION,
- .vmux = TVP5150_COMPOSITE0,
- .amux = 0,
- }, {
- .type = EM28XX_VMUX_COMPOSITE1,
- .vmux = TVP5150_COMPOSITE1,
- .amux = 1,
- }, {
- .type = EM28XX_VMUX_SVIDEO,
- .vmux = TVP5150_SVIDEO,
- .amux = 1,
- } },
- },
- [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950] = {
- .name = "Hauppauge WinTV HVR 950",
- .vchannels = 3,
- .tda9887_conf = TDA9887_PRESENT,
- .tuner_type = TUNER_XC2028,
- .mts_firmware = 1,
- .has_12mhz_i2s = 1,
- .decoder = EM28XX_TVP5150,
- .input = { {
- .type = EM28XX_VMUX_TELEVISION,
- .vmux = TVP5150_COMPOSITE0,
- .amux = 0,
- }, {
- .type = EM28XX_VMUX_COMPOSITE1,
- .vmux = TVP5150_COMPOSITE1,
- .amux = 1,
- }, {
- .type = EM28XX_VMUX_SVIDEO,
- .vmux = TVP5150_SVIDEO,
- .amux = 1,
- } },
-
- /* gpio's 4, 1, 0 */
- .analog_gpio = 0x003d2d,
+ }},
},
- [EM2880_BOARD_TERRATEC_HYBRID_XS] = {
- .name = "Terratec Hybrid XS",
- .vchannels = 3,
- .tda9887_conf = TDA9887_PRESENT,
- .tuner_type = TUNER_XC2028,
- .decoder = EM28XX_TVP5150,
- .input = { {
- .type = EM28XX_VMUX_TELEVISION,
- .vmux = TVP5150_COMPOSITE0,
- .amux = 0,
- }, {
- .type = EM28XX_VMUX_COMPOSITE1,
- .vmux = TVP5150_COMPOSITE1,
- .amux = 1,
- }, {
- .type = EM28XX_VMUX_SVIDEO,
- .vmux = TVP5150_SVIDEO,
- .amux = 1,
- } },
- },
- /* maybe there's a reason behind it why Terratec sells the Hybrid XS
- as Prodigy XS with a different PID, let's keep it separated for now
- maybe we'll need it lateron */
- [EM2880_BOARD_TERRATEC_PRODIGY_XS] = {
- .name = "Terratec Prodigy XS",
- .vchannels = 3,
- .tda9887_conf = TDA9887_PRESENT,
- .tuner_type = TUNER_XC2028,
- .decoder = EM28XX_TVP5150,
- .input = { {
+ [EM2820_BOARD_MSI_VOX_USB_2] = {
+ .name = "MSI VOX USB 2.0",
+ .vchannels = 3,
+ .norm = VIDEO_MODE_PAL,
+ .tuner_type = TUNER_LG_PAL_NEW_TAPC,
+ .tda9887_conf = TDA9887_PRESENT|TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE,
+ .has_tuner = 1,
+ .decoder = EM28XX_SAA7114,
+ .input = {{
.type = EM28XX_VMUX_TELEVISION,
- .vmux = TVP5150_COMPOSITE0,
+ .vmux = SAA7115_COMPOSITE4,
.amux = 0,
- }, {
+ },{
.type = EM28XX_VMUX_COMPOSITE1,
- .vmux = TVP5150_COMPOSITE1,
+ .vmux = SAA7115_COMPOSITE0,
.amux = 1,
- }, {
+ },{
.type = EM28XX_VMUX_SVIDEO,
- .vmux = TVP5150_SVIDEO,
+ .vmux = SAA7115_SVIDEO3,
.amux = 1,
- } },
- },
- [EM2820_BOARD_MSI_VOX_USB_2] = {
- .name = "MSI VOX USB 2.0",
- .vchannels = 3,
- .tuner_type = TUNER_LG_PAL_NEW_TAPC,
- .tda9887_conf = TDA9887_PRESENT |
- TDA9887_PORT1_ACTIVE |
- TDA9887_PORT2_ACTIVE,
- .max_range_640_480 = 1,
-
- .decoder = EM28XX_SAA7114,
- .input = { {
- .type = EM28XX_VMUX_TELEVISION,
- .vmux = SAA7115_COMPOSITE4,
- .amux = 0,
- }, {
- .type = EM28XX_VMUX_COMPOSITE1,
- .vmux = SAA7115_COMPOSITE0,
- .amux = 1,
- }, {
- .type = EM28XX_VMUX_SVIDEO,
- .vmux = SAA7115_SVIDEO3,
- .amux = 1,
- } },
+ }},
},
[EM2800_BOARD_TERRATEC_CINERGY_200] = {
.name = "Terratec Cinergy 200 USB",
.is_em2800 = 1,
.vchannels = 3,
+ .norm = VIDEO_MODE_PAL,
.tuner_type = TUNER_LG_PAL_NEW_TAPC,
.tda9887_conf = TDA9887_PRESENT,
+ .has_tuner = 1,
.decoder = EM28XX_SAA7113,
- .input = { {
+ .input = {{
.type = EM28XX_VMUX_TELEVISION,
.vmux = SAA7115_COMPOSITE2,
.amux = 0,
- }, {
+ },{
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = SAA7115_COMPOSITE0,
.amux = 1,
- }, {
+ },{
.type = EM28XX_VMUX_SVIDEO,
.vmux = SAA7115_SVIDEO3,
.amux = 1,
- } },
+ }},
},
[EM2800_BOARD_LEADTEK_WINFAST_USBII] = {
.name = "Leadtek Winfast USB II",
.is_em2800 = 1,
.vchannels = 3,
+ .norm = VIDEO_MODE_PAL,
.tuner_type = TUNER_LG_PAL_NEW_TAPC,
.tda9887_conf = TDA9887_PRESENT,
+ .has_tuner = 1,
.decoder = EM28XX_SAA7113,
- .input = { {
+ .input = {{
.type = EM28XX_VMUX_TELEVISION,
.vmux = SAA7115_COMPOSITE2,
.amux = 0,
- }, {
+ },{
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = SAA7115_COMPOSITE0,
.amux = 1,
- }, {
+ },{
.type = EM28XX_VMUX_SVIDEO,
.vmux = SAA7115_SVIDEO3,
.amux = 1,
- } },
+ }},
},
[EM2800_BOARD_KWORLD_USB2800] = {
.name = "Kworld USB2800",
.is_em2800 = 1,
.vchannels = 3,
+ .norm = VIDEO_MODE_PAL,
.tuner_type = TUNER_PHILIPS_ATSC,
.tda9887_conf = TDA9887_PRESENT,
+ .has_tuner = 1,
.decoder = EM28XX_SAA7113,
- .input = { {
+ .input = {{
.type = EM28XX_VMUX_TELEVISION,
.vmux = SAA7115_COMPOSITE2,
.amux = 0,
- }, {
+ },{
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = SAA7115_COMPOSITE0,
.amux = 1,
- }, {
+ },{
.type = EM28XX_VMUX_SVIDEO,
.vmux = SAA7115_SVIDEO3,
.amux = 1,
- } },
+ }},
},
[EM2820_BOARD_PINNACLE_DVC_90] = {
- .name = "Pinnacle Dazzle DVC 90/DVC 100",
- .vchannels = 3,
- .tuner_type = TUNER_ABSENT,
- .decoder = EM28XX_SAA7113,
- .input = { {
- .type = EM28XX_VMUX_COMPOSITE1,
- .vmux = SAA7115_COMPOSITE0,
- .amux = 1,
- }, {
- .type = EM28XX_VMUX_SVIDEO,
- .vmux = SAA7115_SVIDEO3,
- .amux = 1,
- } },
- },
- [EM2800_BOARD_VGEAR_POCKETTV] = {
- .name = "V-Gear PocketTV",
- .is_em2800 = 1,
- .vchannels = 3,
- .tuner_type = TUNER_LG_PAL_NEW_TAPC,
- .tda9887_conf = TDA9887_PRESENT,
- .decoder = EM28XX_SAA7113,
- .input = { {
- .type = EM28XX_VMUX_TELEVISION,
- .vmux = SAA7115_COMPOSITE2,
- .amux = 0,
- }, {
- .type = EM28XX_VMUX_COMPOSITE1,
- .vmux = SAA7115_COMPOSITE0,
- .amux = 1,
- }, {
- .type = EM28XX_VMUX_SVIDEO,
- .vmux = SAA7115_SVIDEO3,
- .amux = 1,
- } },
- },
- [EM2820_BOARD_PROLINK_PLAYTV_USB2] = {
- .name = "Pixelview Prolink PlayTV USB 2.0",
+ .name = "Pinnacle Dazzle DVC 90",
.vchannels = 3,
- .tda9887_conf = TDA9887_PRESENT,
- .tuner_type = TUNER_YMEC_TVF_5533MF,
+ .norm = VIDEO_MODE_PAL,
+ .has_tuner = 0,
.decoder = EM28XX_SAA7113,
- .input = { {
- .type = EM28XX_VMUX_TELEVISION,
- .vmux = SAA7115_COMPOSITE2,
- .amux = 1,
- }, {
+ .input = {{
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = SAA7115_COMPOSITE0,
.amux = 1,
- }, {
+ },{
.type = EM28XX_VMUX_SVIDEO,
.vmux = SAA7115_SVIDEO3,
.amux = 1,
- } },
+ }},
},
};
const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
/* table of devices that work with this driver */
struct usb_device_id em28xx_id_table [] = {
- { USB_DEVICE(0xeb1a, 0x2750),
- .driver_info = EM2820_BOARD_UNKNOWN },
- { USB_DEVICE(0xeb1a, 0x2800),
- .driver_info = EM2800_BOARD_UNKNOWN },
- { USB_DEVICE(0xeb1a, 0x2820),
- .driver_info = EM2820_BOARD_UNKNOWN },
- { USB_DEVICE(0xeb1a, 0x2821),
- .driver_info = EM2820_BOARD_UNKNOWN },
- { USB_DEVICE(0xeb1a, 0x2860),
- .driver_info = EM2820_BOARD_UNKNOWN },
- { USB_DEVICE(0xeb1a, 0x2861),
- .driver_info = EM2820_BOARD_UNKNOWN },
- { USB_DEVICE(0xeb1a, 0x2870),
- .driver_info = EM2820_BOARD_UNKNOWN },
- { USB_DEVICE(0xeb1a, 0x2881),
- .driver_info = EM2820_BOARD_UNKNOWN },
- { USB_DEVICE(0xeb1a, 0x2883),
- .driver_info = EM2820_BOARD_UNKNOWN },
- { USB_DEVICE(0x0ccd, 0x0036),
- .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 },
- { USB_DEVICE(0x2304, 0x0208),
- .driver_info = EM2820_BOARD_PINNACLE_USB_2 },
- { USB_DEVICE(0x2040, 0x4200),
- .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 },
- { USB_DEVICE(0x2040, 0x4201),
- .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 },
- { USB_DEVICE(0x2304, 0x0207),
- .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
- { USB_DEVICE(0x2304, 0x021a),
- .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
- { USB_DEVICE(0x2040, 0x6500),
- .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 },
- { USB_DEVICE(0x2040, 0x6513),
- .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 },
- { USB_DEVICE(0x0ccd, 0x0042),
- .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS },
- { USB_DEVICE(0x0ccd, 0x0047),
- .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS },
+ { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_UNKNOWN },
+ { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_MSI_VOX_USB_2 },
+ { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 },
+ { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 },
+ { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 },
+ { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
{ },
};
-MODULE_DEVICE_TABLE(usb, em28xx_id_table);
-
-/* EEPROM hash table for devices with generic USB IDs */
-static struct em28xx_hash_table em28xx_eeprom_hash [] = {
- /* P/N: SA 60002070465 Tuner: TVF7533-MF */
- {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
-};
-
-/* I2C devicelist hash table for devices with generic USB IDs */
-static struct em28xx_hash_table em28xx_i2c_hash[] = {
- {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC},
- {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
-};
-/* Since em28xx_pre_card_setup() requires a proper dev->model,
- * this won't work for boards with generic PCI IDs
- */
void em28xx_pre_card_setup(struct em28xx *dev)
{
/* request some modules */
- switch (dev->model) {
- case EM2880_BOARD_TERRATEC_PRODIGY_XS:
- case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
- case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
- case EM2880_BOARD_TERRATEC_HYBRID_XS:
- em28xx_write_regs(dev, XCLK_REG, "\x27", 1);
- em28xx_write_regs(dev, I2C_CLK_REG, "\x40", 1);
- em28xx_write_regs(dev, 0x08, "\xff", 1);
- em28xx_write_regs(dev, 0x04, "\x00", 1);
- msleep(100);
- em28xx_write_regs(dev, 0x04, "\x08", 1);
- msleep(100);
- em28xx_write_regs(dev, 0x08, "\xff", 1);
- msleep(50);
- em28xx_write_regs(dev, 0x08, "\x2d", 1);
- msleep(50);
- em28xx_write_regs(dev, 0x08, "\x3d", 1);
- break;
- }
-}
-
-static int em28xx_tuner_callback(void *ptr, int command, int arg)
-{
- int rc = 0;
- struct em28xx *dev = ptr;
-
- if (dev->tuner_type != TUNER_XC2028)
- return 0;
-
- switch (command) {
- case XC2028_TUNER_RESET:
- {
- /* GPIO and initialization codes for analog TV and radio
- This code should be complemented for DTV, since reset
- codes are different.
- */
-
- dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
- dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1);
-
- if (dev->analog_gpio) {
- char gpio0 = dev->analog_gpio & 0xff;
- char gpio1 = (dev->analog_gpio >> 8) & 0xff;
- char gpio4 = dev->analog_gpio >> 24;
-
- if (gpio4) {
- dev->em28xx_write_regs(dev, 0x04, &gpio4, 1);
- msleep(140);
+ switch(dev->model){
+ case EM2880_BOARD_TERRATEC_PRODIGY_XS:
+ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+ case EM2880_BOARD_TERRATEC_HYBRID_XS:
+ {
+ em28xx_write_regs_req(dev, 0x00, 0x08, "\x7d", 1); // reset through GPIO?
+ break;
}
-
- msleep(6);
- dev->em28xx_write_regs(dev, 0x08, &gpio0, 1);
- msleep(10);
- dev->em28xx_write_regs(dev, 0x08, &gpio1, 1);
- msleep(5);
- }
-
- break;
- }
- }
- return rc;
-}
-
-static void em28xx_config_tuner(struct em28xx *dev)
-{
- struct v4l2_priv_tun_config xc2028_cfg;
- struct xc2028_ctrl ctl;
- struct tuner_setup tun_setup;
- struct v4l2_frequency f;
-
- if (dev->tuner_type == TUNER_ABSENT)
- return;
-
- tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
- tun_setup.type = dev->tuner_type;
- tun_setup.addr = dev->tuner_addr;
- tun_setup.tuner_callback = em28xx_tuner_callback;
-
- em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
-
- if (dev->tuner_type == TUNER_XC2028) {
- memset(&ctl, 0, sizeof(ctl));
-
- ctl.fname = XC2028_DEFAULT_FIRMWARE;
- ctl.max_len = 64;
- ctl.mts = em28xx_boards[dev->model].mts_firmware;
-
- xc2028_cfg.tuner = TUNER_XC2028;
- xc2028_cfg.priv = &ctl;
-
- em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
- }
-
- /* configure tuner */
- f.tuner = 0;
- f.type = V4L2_TUNER_ANALOG_TV;
- f.frequency = 9076; /* just a magic number */
- dev->ctl_freq = f.frequency;
- em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f);
-}
-
-static int em28xx_hint_board(struct em28xx *dev)
-{
- int i;
-
- /* HINT method: EEPROM
- *
- * This method works only for boards with eeprom.
- * Uses a hash of all eeprom bytes. The hash should be
- * unique for a vendor/tuner pair.
- * There are a high chance that tuners for different
- * video standards produce different hashes.
- */
- for (i = 0; i < ARRAY_SIZE(em28xx_eeprom_hash); i++) {
- if (dev->hash == em28xx_eeprom_hash[i].hash) {
- dev->model = em28xx_eeprom_hash[i].model;
- dev->tuner_type = em28xx_eeprom_hash[i].tuner;
-
- em28xx_errdev("Your board has no unique USB ID.\n");
- em28xx_errdev("A hint were successfully done, "
- "based on eeprom hash.\n");
- em28xx_errdev("This method is not 100%% failproof.\n");
- em28xx_errdev("If the board were missdetected, "
- "please email this log to:\n");
- em28xx_errdev("\tV4L Mailing List "
- " \n");
- em28xx_errdev("Board detected as %s\n",
- em28xx_boards[dev->model].name);
-
- return 0;
- }
- }
-
- /* HINT method: I2C attached devices
- *
- * This method works for all boards.
- * Uses a hash of i2c scanned devices.
- * Devices with the same i2c attached chips will
- * be considered equal.
- * This method is less precise than the eeprom one.
- */
-
- /* user did not request i2c scanning => do it now */
- if (!dev->i2c_hash)
- em28xx_do_i2c_scan(dev);
-
- for (i = 0; i < ARRAY_SIZE(em28xx_i2c_hash); i++) {
- if (dev->i2c_hash == em28xx_i2c_hash[i].hash) {
- dev->model = em28xx_i2c_hash[i].model;
- dev->tuner_type = em28xx_i2c_hash[i].tuner;
- em28xx_errdev("Your board has no unique USB ID.\n");
- em28xx_errdev("A hint were successfully done, "
- "based on i2c devicelist hash.\n");
- em28xx_errdev("This method is not 100%% failproof.\n");
- em28xx_errdev("If the board were missdetected, "
- "please email this log to:\n");
- em28xx_errdev("\tV4L Mailing List "
- " \n");
- em28xx_errdev("Board detected as %s\n",
- em28xx_boards[dev->model].name);
-
- return 0;
- }
- }
-
- em28xx_errdev("Your board has no unique USB ID and thus need a "
- "hint to be detected.\n");
- em28xx_errdev("You may try to use card= insmod option to "
- "workaround that.\n");
- em28xx_errdev("Please send an email with this log to:\n");
- em28xx_errdev("\tV4L Mailing List \n");
- em28xx_errdev("Board eeprom hash is 0x%08lx\n", dev->hash);
- em28xx_errdev("Board i2c devicelist hash is 0x%08lx\n", dev->i2c_hash);
-
- em28xx_errdev("Here is a list of valid choices for the card="
- " insmod option:\n");
- for (i = 0; i < em28xx_bcount; i++) {
- em28xx_errdev(" card=%d -> %s\n",
- i, em28xx_boards[i].name);
- }
- return -1;
-}
-
-
-static void em28xx_set_model(struct em28xx *dev)
-{
- dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
- dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx;
- dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
- dev->decoder = em28xx_boards[dev->model].decoder;
- dev->video_inputs = em28xx_boards[dev->model].vchannels;
- dev->analog_gpio = em28xx_boards[dev->model].analog_gpio;
- dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
- dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
-}
-
-/* ----------------------------------------------------------------------- */
-void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
-{
- if (disable_ir) {
- ir->get_key = NULL;
- return ;
- }
-
- /* detect & configure */
- switch (dev->model) {
- case (EM2800_BOARD_UNKNOWN):
- break;
- case (EM2820_BOARD_UNKNOWN):
- break;
- case (EM2800_BOARD_TERRATEC_CINERGY_200):
- case (EM2820_BOARD_TERRATEC_CINERGY_250):
- ir->ir_codes = ir_codes_em_terratec;
- ir->get_key = em28xx_get_key_terratec;
- snprintf(ir->c.name, sizeof(ir->c.name),
- "i2c IR (EM28XX Terratec)");
- break;
- case (EM2820_BOARD_PINNACLE_USB_2):
- ir->ir_codes = ir_codes_pinnacle_grey;
- ir->get_key = em28xx_get_key_pinnacle_usb_grey;
- snprintf(ir->c.name, sizeof(ir->c.name),
- "i2c IR (EM28XX Pinnacle PCTV)");
- break;
- case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
- ir->ir_codes = ir_codes_hauppauge_new;
- ir->get_key = em28xx_get_key_em_haup;
- snprintf(ir->c.name, sizeof(ir->c.name),
- "i2c IR (EM2840 Hauppauge)");
- break;
- case (EM2820_BOARD_MSI_VOX_USB_2):
- break;
- case (EM2800_BOARD_LEADTEK_WINFAST_USBII):
- break;
- case (EM2800_BOARD_KWORLD_USB2800):
- break;
}
}
void em28xx_card_setup(struct em28xx *dev)
{
- em28xx_set_model(dev);
-
- dev->tuner_type = em28xx_boards[dev->model].tuner_type;
-
/* request some modules */
- switch (dev->model) {
- case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
- case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
- case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
- {
- struct tveeprom tv;
+ switch(dev->model){
+ case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
+ {
+ struct tveeprom tv;
#ifdef CONFIG_MODULES
- request_module("tveeprom");
+ request_module("tveeprom");
+ request_module("ir-kbd-i2c");
+ request_module("msp3400");
#endif
- /* Call first TVeeprom */
-
- dev->i2c_client.addr = 0xa0 >> 1;
- tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata);
-
- dev->tuner_type = tv.tuner_type;
+ /* Call first TVeeprom */
+
+ dev->i2c_client.addr = 0xa0 >> 1;
+ tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata);
+
+ dev->tuner_type= tv.tuner_type;
+ if (tv.audio_processor == AUDIO_CHIP_MSP34XX) {
+ dev->i2s_speed=2048000;
+ dev->has_msp34xx=1;
+ } else
+ dev->has_msp34xx=0;
+ break;
+ }
+ case EM2820_BOARD_KWORLD_PVRTV2800RF:
+ {
+ em28xx_write_regs_req(dev,0x00,0x08, "\xf9", 1); // GPIO enables sound on KWORLD PVR TV 2800RF
+ break;
+ }
- if (tv.audio_processor == AUDIO_CHIP_MSP34XX) {
- dev->i2s_speed = 2048000;
- dev->has_msp34xx = 1;
- }
-#ifdef CONFIG_MODULES
- if (tv.has_ir)
- request_module("ir-kbd-i2c");
-#endif
- break;
- }
- case EM2820_BOARD_KWORLD_PVRTV2800RF:
- /* GPIO enables sound on KWORLD PVR TV 2800RF */
- em28xx_write_regs_req(dev, 0x00, 0x08, "\xf9", 1);
- break;
- case EM2820_BOARD_UNKNOWN:
- case EM2800_BOARD_UNKNOWN:
- if (!em28xx_hint_board(dev))
- em28xx_set_model(dev);
}
-
- /* Allow override tuner type by a module parameter */
- if (tuner >= 0)
- dev->tuner_type = tuner;
-
-#ifdef CONFIG_MODULES
- /* request some modules */
- if (dev->has_msp34xx)
- request_module("msp3400");
- if (dev->decoder == EM28XX_SAA7113 || dev->decoder == EM28XX_SAA7114)
- request_module("saa7115");
- if (dev->decoder == EM28XX_TVP5150)
- request_module("tvp5150");
- if (dev->tuner_type != TUNER_ABSENT)
- request_module("tuner");
-#endif
-
- em28xx_config_tuner(dev);
}
+
+MODULE_DEVICE_TABLE (usb, em28xx_id_table);
diff --git a/trunk/drivers/media/video/em28xx/em28xx-core.c b/trunk/drivers/media/video/em28xx/em28xx-core.c
index f6b78357f0e5..d56484f20467 100644
--- a/trunk/drivers/media/video/em28xx/em28xx-core.c
+++ b/trunk/drivers/media/video/em28xx/em28xx-core.c
@@ -252,7 +252,7 @@ int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
* em28xx_write_ac97()
* write a 16 bit value to the specified AC97 address (LSB first!)
*/
-static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val)
+int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val)
{
int ret;
u8 addr = reg & 0x7f;
@@ -268,98 +268,16 @@ static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val)
return 0;
}
-int em28xx_set_audio_source(struct em28xx *dev)
-{
- static char *enable = "\x08\x08";
- static char *disable = "\x08\x88";
- char *video = enable, *line = disable;
- int ret, no_ac97;
- u8 input;
-
- if (dev->is_em2800) {
- if (dev->ctl_ainput)
- input = EM2800_AUDIO_SRC_LINE;
- else
- input = EM2800_AUDIO_SRC_TUNER;
-
- ret = em28xx_write_regs(dev, EM2800_AUDIOSRC_REG, &input, 1);
- if (ret < 0)
- return ret;
- }
-
- if (dev->has_msp34xx)
- input = EM28XX_AUDIO_SRC_TUNER;
- else {
- switch (dev->ctl_ainput) {
- case EM28XX_AMUX_VIDEO:
- input = EM28XX_AUDIO_SRC_TUNER;
- no_ac97 = 1;
- break;
- case EM28XX_AMUX_LINE_IN:
- input = EM28XX_AUDIO_SRC_LINE;
- no_ac97 = 1;
- break;
- case EM28XX_AMUX_AC97_VIDEO:
- input = EM28XX_AUDIO_SRC_LINE;
- break;
- case EM28XX_AMUX_AC97_LINE_IN:
- input = EM28XX_AUDIO_SRC_LINE;
- video = disable;
- line = enable;
- break;
- }
- }
-
- ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0);
- if (ret < 0)
- return ret;
-
- if (no_ac97)
- return 0;
-
- /* Sets AC97 mixer registers */
-
- ret = em28xx_write_ac97(dev, VIDEO_AC97, video);
- if (ret < 0)
- return ret;
-
- ret = em28xx_write_ac97(dev, LINE_IN_AC97, line);
-
- return ret;
-}
-
int em28xx_audio_analog_set(struct em28xx *dev)
{
- int ret;
char s[2] = { 0x00, 0x00 };
- u8 xclk = 0x07;
-
s[0] |= 0x1f - dev->volume;
s[1] |= 0x1f - dev->volume;
-
if (dev->mute)
s[1] |= 0x80;
- ret = em28xx_write_ac97(dev, MASTER_AC97, s);
- if (ret < 0)
- return ret;
-
- if (dev->has_12mhz_i2s)
- xclk |= 0x20;
-
- if (!dev->mute)
- xclk |= 0x80;
-
- ret = em28xx_write_reg_bits(dev, XCLK_REG, xclk, 0xa7);
- if (ret < 0)
- return ret;
- msleep(10);
-
- /* Selects the proper audio input */
- ret = em28xx_set_audio_source(dev);
-
- return ret;
+ return em28xx_write_ac97(dev, MASTER_AC97, s);
}
-EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
+
int em28xx_colorlevels_set_default(struct em28xx *dev)
{
diff --git a/trunk/drivers/media/video/em28xx/em28xx-i2c.c b/trunk/drivers/media/video/em28xx/em28xx-i2c.c
index cacd04d46e99..e3a4aa7a9df4 100644
--- a/trunk/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/trunk/drivers/media/video/em28xx/em28xx-i2c.c
@@ -25,9 +25,9 @@
#include
#include
#include
+#include
#include "em28xx.h"
-#include "tuner-xc2028.h"
#include
#include
@@ -291,31 +291,6 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
return rc;
}
-/* based on linux/sunrpc/svcauth.h and linux/hash.h
- * The original hash function returns a different value, if arch is x86_64
- * or i386.
- */
-static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
-{
- unsigned long hash = 0;
- unsigned long l = 0;
- int len = 0;
- unsigned char c;
- do {
- if (len == length) {
- c = (char)len;
- len = -1;
- } else
- c = *buf++;
- l = (l << 8) | c;
- len++;
- if ((len & (32 / 8 - 1)) == 0)
- hash = ((hash^l) * 0x9e370001UL);
- } while (len);
-
- return (hash >> (32 - bits)) & 0xffffffffUL;
-}
-
static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
{
unsigned char buf, *p = eedata;
@@ -359,11 +334,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
printk("\n");
}
- if (em_eeprom->id == 0x9567eb1a)
- dev->hash = em28xx_hash_mem(eedata, len, 32);
-
- printk(KERN_INFO "EEPROM ID= 0x%08x, hash = 0x%08lx\n",
- em_eeprom->id, dev->hash);
+ printk(KERN_INFO "EEPROM ID= 0x%08x\n", em_eeprom->id);
printk(KERN_INFO "Vendor/Product ID= %04x:%04x\n", em_eeprom->vendor_ID,
em_eeprom->product_ID);
@@ -420,6 +391,21 @@ static u32 functionality(struct i2c_adapter *adap)
}
+static int em28xx_set_tuner(int check_eeprom, struct i2c_client *client)
+{
+ struct em28xx *dev = client->adapter->algo_data;
+ struct tuner_setup tun_setup;
+
+ if (dev->has_tuner) {
+ tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+ tun_setup.type = dev->tuner_type;
+ tun_setup.addr = dev->tuner_addr;
+ em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+ }
+
+ return (0);
+}
+
/*
* attach_inform()
* gets called when a device attaches to the i2c bus
@@ -435,8 +421,6 @@ static int attach_inform(struct i2c_client *client)
case 0x96:
case 0x94:
{
- struct v4l2_priv_tun_config tda9887_cfg;
-
struct tuner_setup tun_setup;
tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
@@ -444,11 +428,7 @@ static int attach_inform(struct i2c_client *client)
tun_setup.addr = client->addr;
em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
-
- tda9887_cfg.tuner = TUNER_TDA9887;
- tda9887_cfg.priv = &dev->tda9887_conf;
- em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG,
- &tda9887_cfg);
+ em28xx_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf);
break;
}
case 0x42:
@@ -478,11 +458,9 @@ static int attach_inform(struct i2c_client *client)
break;
default:
- if (!dev->tuner_addr)
- dev->tuner_addr = client->addr;
-
dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1);
-
+ dev->tuner_addr = client->addr;
+ em28xx_set_tuner(-1, client);
}
return 0;
@@ -532,26 +510,19 @@ static char *i2c_devs[128] = {
* do_i2c_scan()
* check i2c address range for devices
*/
-void em28xx_do_i2c_scan(struct em28xx *dev)
+static void do_i2c_scan(char *name, struct i2c_client *c)
{
- u8 i2c_devicelist[128];
unsigned char buf;
int i, rc;
- memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist));
-
for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
- dev->i2c_client.addr = i;
- rc = i2c_master_recv(&dev->i2c_client, &buf, 0);
+ c->addr = i;
+ rc = i2c_master_recv(c, &buf, 0);
if (rc < 0)
continue;
- i2c_devicelist[i] = i;
- printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n",
- dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+ printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n", name,
+ i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
}
-
- dev->i2c_hash = em28xx_hash_mem(i2c_devicelist,
- ARRAY_SIZE(i2c_devicelist), 32);
}
/*
@@ -584,7 +555,7 @@ int em28xx_i2c_register(struct em28xx *dev)
em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
if (i2c_scan)
- em28xx_do_i2c_scan(dev);
+ do_i2c_scan(dev->name, &dev->i2c_client);
return 0;
}
diff --git a/trunk/drivers/media/video/em28xx/em28xx-input.c b/trunk/drivers/media/video/em28xx/em28xx-input.c
index 10da2fd8d987..e3894b68c4ee 100644
--- a/trunk/drivers/media/video/em28xx/em28xx-input.c
+++ b/trunk/drivers/media/video/em28xx/em28xx-input.c
@@ -30,7 +30,11 @@
#include "em28xx.h"
-static unsigned int ir_debug;
+static unsigned int disable_ir = 0;
+module_param(disable_ir, int, 0444);
+MODULE_PARM_DESC(disable_ir,"disable infrared remote support");
+
+static unsigned int ir_debug = 0;
module_param(ir_debug, int, 0644);
MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
@@ -39,7 +43,7 @@ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
/* ----------------------------------------------------------------------- */
-int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
unsigned char b;
@@ -68,7 +72,7 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
}
-int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
unsigned char buf[2];
unsigned char code;
@@ -99,8 +103,7 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return 1;
}
-int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
- u32 *ir_raw)
+static int get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
unsigned char buf[3];
@@ -122,6 +125,45 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
return 1;
}
+/* ----------------------------------------------------------------------- */
+void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir)
+{
+ if (disable_ir) {
+ ir->get_key=NULL;
+ return ;
+ }
+
+ /* detect & configure */
+ switch (dev->model) {
+ case (EM2800_BOARD_UNKNOWN):
+ break;
+ case (EM2820_BOARD_UNKNOWN):
+ break;
+ case (EM2800_BOARD_TERRATEC_CINERGY_200):
+ case (EM2820_BOARD_TERRATEC_CINERGY_250):
+ ir->ir_codes = ir_codes_em_terratec;
+ ir->get_key = get_key_terratec;
+ snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)");
+ break;
+ case (EM2820_BOARD_PINNACLE_USB_2):
+ ir->ir_codes = ir_codes_pinnacle_grey;
+ ir->get_key = get_key_pinnacle_usb_grey;
+ snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Pinnacle PCTV)");
+ break;
+ case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
+ ir->ir_codes = ir_codes_hauppauge_new;
+ ir->get_key = get_key_em_haup;
+ snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM2840 Hauppauge)");
+ break;
+ case (EM2820_BOARD_MSI_VOX_USB_2):
+ break;
+ case (EM2800_BOARD_LEADTEK_WINFAST_USBII):
+ break;
+ case (EM2800_BOARD_KWORLD_USB2800):
+ break;
+ }
+}
+
/* ----------------------------------------------------------------------
* Local variables:
* c-basic-offset: 8
diff --git a/trunk/drivers/media/video/em28xx/em28xx-video.c b/trunk/drivers/media/video/em28xx/em28xx-video.c
index a0c334672488..0906bc5766cc 100644
--- a/trunk/drivers/media/video/em28xx/em28xx-video.c
+++ b/trunk/drivers/media/video/em28xx/em28xx-video.c
@@ -33,12 +33,13 @@
#include
#include
#include
+#include
#include
#include "em28xx.h"
+#include
#include
#include
-#include
#define DRIVER_AUTHOR "Ludovico Cavedon , " \
"Markus Rechberger , " \
@@ -47,7 +48,7 @@
#define DRIVER_NAME "em28xx"
#define DRIVER_DESC "Empia em28xx based USB video device driver"
-#define EM28XX_VERSION_CODE KERNEL_VERSION(0, 1, 0)
+#define EM28XX_VERSION_CODE KERNEL_VERSION(0, 0, 1)
#define em28xx_videodbg(fmt, arg...) do {\
if (video_debug) \
@@ -62,17 +63,17 @@ static LIST_HEAD(em28xx_devlist);
static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
-static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
-static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
-
+static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
module_param_array(card, int, NULL, 0444);
module_param_array(video_nr, int, NULL, 0444);
module_param_array(vbi_nr, int, NULL, 0444);
-module_param_array(radio_nr, int, NULL, 0444);
-MODULE_PARM_DESC(card, "card type");
-MODULE_PARM_DESC(video_nr, "video device numbers");
-MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
-MODULE_PARM_DESC(radio_nr, "radio device numbers");
+MODULE_PARM_DESC(card,"card type");
+MODULE_PARM_DESC(video_nr,"video device numbers");
+MODULE_PARM_DESC(vbi_nr,"vbi device numbers");
+
+static int tuner = -1;
+module_param(tuner, int, 0444);
+MODULE_PARM_DESC(tuner, "tuner type");
static unsigned int video_debug = 0;
module_param(video_debug,int,0644);
@@ -81,6 +82,29 @@ MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
static unsigned long em28xx_devused;
+/* supported tv norms */
+static struct em28xx_tvnorm tvnorms[] = {
+ {
+ .name = "PAL",
+ .id = V4L2_STD_PAL,
+ .mode = VIDEO_MODE_PAL,
+ }, {
+ .name = "NTSC",
+ .id = V4L2_STD_NTSC,
+ .mode = VIDEO_MODE_NTSC,
+ }, {
+ .name = "SECAM",
+ .id = V4L2_STD_SECAM,
+ .mode = VIDEO_MODE_SECAM,
+ }, {
+ .name = "PAL-M",
+ .id = V4L2_STD_PAL_M,
+ .mode = VIDEO_MODE_PAL,
+ }
+};
+
+#define TVNORMS ARRAY_SIZE(tvnorms)
+
/* supported controls */
/* Common to all boards */
static struct v4l2_queryctrl em28xx_qctrl[] = {
@@ -107,6 +131,8 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
static struct usb_driver em28xx_usb_driver;
+static DEFINE_MUTEX(em28xx_sysfs_lock);
+static DECLARE_RWSEM(em28xx_disconnect);
/********************* v4l2 interface ******************************************/
@@ -127,9 +153,11 @@ static int em28xx_config(struct em28xx *dev)
/* em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */
em28xx_write_regs_req(dev,0x00,0x11,"\x51",1);
+ em28xx_audio_usb_mute(dev, 1);
dev->mute = 1; /* maybe not the right place... */
dev->volume = 0x1f;
-
+ em28xx_audio_analog_set(dev);
+ em28xx_audio_analog_setup(dev);
em28xx_outfmt_set_yuv422(dev);
em28xx_colorlevels_set_default(dev);
em28xx_compression_disable(dev);
@@ -143,6 +171,7 @@ static int em28xx_config(struct em28xx *dev)
*/
static void em28xx_config_i2c(struct em28xx *dev)
{
+ struct v4l2_frequency f;
struct v4l2_routing route;
route.input = INPUT(dev->ctl_input)->vmux;
@@ -150,6 +179,18 @@ static void em28xx_config_i2c(struct em28xx *dev)
em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL);
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
+
+ /* configure tuner */
+ f.tuner = 0;
+ f.type = V4L2_TUNER_ANALOG_TV;
+ f.frequency = 9076; /* FIXME:remove magic number */
+ dev->ctl_freq = f.frequency;
+ em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f);
+
+ /* configure tda9887 */
+
+
+/* em28xx_i2c_call_clients(dev,VIDIOC_S_STD,&dev->tvnorm->id); */
}
/*
@@ -171,6 +212,7 @@ static void em28xx_empty_framequeues(struct em28xx *dev)
static void video_mux(struct em28xx *dev, int index)
{
+ int ainput;
struct v4l2_routing route;
route.input = INPUT(index)->vmux;
@@ -180,6 +222,8 @@ static void video_mux(struct em28xx *dev, int index)
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
+ em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,route.input,dev->ctl_ainput);
+
if (dev->has_msp34xx) {
if (dev->i2s_speed)
em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
@@ -187,1693 +231,1314 @@ static void video_mux(struct em28xx *dev, int index)
route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
/* Note: this is msp3400 specific */
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+ ainput = EM28XX_AUDIO_SRC_TUNER;
+ em28xx_audio_source(dev, ainput);
+ } else {
+ switch (dev->ctl_ainput) {
+ case 0:
+ ainput = EM28XX_AUDIO_SRC_TUNER;
+ break;
+ default:
+ ainput = EM28XX_AUDIO_SRC_LINE;
+ }
+ em28xx_audio_source(dev, ainput);
}
-
- em28xx_set_audio_source(dev);
}
-/* Usage lock check functions */
-static int res_get(struct em28xx_fh *fh)
+/*
+ * em28xx_v4l2_open()
+ * inits the device and starts isoc transfer
+ */
+static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
{
- struct em28xx *dev = fh->dev;
- int rc = 0;
+ int minor = iminor(inode);
+ int errCode = 0;
+ struct em28xx *h,*dev = NULL;
+
+ list_for_each_entry(h, &em28xx_devlist, devlist) {
+ if (h->vdev->minor == minor) {
+ dev = h;
+ dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ if (h->vbi_dev->minor == minor) {
+ dev = h;
+ dev->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ }
+ }
+ if (NULL == dev)
+ return -ENODEV;
+
+ em28xx_videodbg("open minor=%d type=%s users=%d\n",
+ minor,v4l2_type_names[dev->type],dev->users);
+
+ if (!down_read_trylock(&em28xx_disconnect))
+ return -ERESTARTSYS;
+
+ if (dev->users) {
+ em28xx_warn("this driver can be opened only once\n");
+ up_read(&em28xx_disconnect);
+ return -EBUSY;
+ }
- /* This instance already has stream_on */
- if (fh->stream_on)
- return rc;
+ mutex_init(&dev->fileop_lock); /* to 1 == available */
+ spin_lock_init(&dev->queue_lock);
+ init_waitqueue_head(&dev->wait_frame);
+ init_waitqueue_head(&dev->wait_stream);
mutex_lock(&dev->lock);
- if (dev->stream_on)
- rc = -EINVAL;
- else {
- dev->stream_on = 1;
- fh->stream_on = 1;
+ if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ em28xx_set_alternate(dev);
+
+ dev->width = norm_maxw(dev);
+ dev->height = norm_maxh(dev);
+ dev->frame_size = dev->width * dev->height * 2;
+ dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */
+ dev->bytesperline = dev->width * 2;
+ dev->hscale = 0;
+ dev->vscale = 0;
+
+ em28xx_capture_start(dev, 1);
+ em28xx_resolution_set(dev);
+
+ /* device needs to be initialized before isoc transfer */
+ video_mux(dev, 0);
+
+ /* start the transfer */
+ errCode = em28xx_init_isoc(dev);
+ if (errCode)
+ goto err;
+
}
- mutex_unlock(&dev->lock);
- return rc;
-}
+ dev->users++;
+ filp->private_data = dev;
+ dev->io = IO_NONE;
+ dev->stream = STREAM_OFF;
+ dev->num_frames = 0;
-static int res_check(struct em28xx_fh *fh)
-{
- return (fh->stream_on);
-}
+ /* prepare queues */
+ em28xx_empty_framequeues(dev);
-static void res_free(struct em28xx_fh *fh)
-{
- struct em28xx *dev = fh->dev;
+ dev->state |= DEV_INITIALIZED;
- mutex_lock(&dev->lock);
- fh->stream_on = 0;
- dev->stream_on = 0;
+err:
mutex_unlock(&dev->lock);
+ up_read(&em28xx_disconnect);
+ return errCode;
}
/*
- * em28xx_vm_open()
- */
-static void em28xx_vm_open(struct vm_area_struct *vma)
+ * em28xx_realease_resources()
+ * unregisters the v4l2,i2c and usb devices
+ * called when the device gets disconected or at module unload
+*/
+static void em28xx_release_resources(struct em28xx *dev)
{
- struct em28xx_frame_t *f = vma->vm_private_data;
- f->vma_use_count++;
+ mutex_lock(&em28xx_sysfs_lock);
+
+ /*FIXME: I2C IR should be disconnected */
+
+ em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n",
+ dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN,
+ dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN);
+ list_del(&dev->devlist);
+ video_unregister_device(dev->vdev);
+ video_unregister_device(dev->vbi_dev);
+ em28xx_i2c_unregister(dev);
+ usb_put_dev(dev->udev);
+ mutex_unlock(&em28xx_sysfs_lock);
+
+
+ /* Mark device as unused */
+ em28xx_devused&=~(1<devno);
}
/*
- * em28xx_vm_close()
+ * em28xx_v4l2_close()
+ * stops streaming and deallocates all resources allocated by the v4l2 calls and ioctls
*/
-static void em28xx_vm_close(struct vm_area_struct *vma)
+static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
{
- /* NOTE: buffers are not freed here */
- struct em28xx_frame_t *f = vma->vm_private_data;
+ int errCode;
+ struct em28xx *dev=filp->private_data;
- if (f->vma_use_count)
- f->vma_use_count--;
-}
+ em28xx_videodbg("users=%d\n", dev->users);
-static struct vm_operations_struct em28xx_vm_ops = {
- .open = em28xx_vm_open,
- .close = em28xx_vm_close,
-};
+ mutex_lock(&dev->lock);
+ em28xx_uninit_isoc(dev);
-/*
- * em28xx_get_ctrl()
- * return the current saturation, brightness or contrast, mute state
- */
-static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
-{
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- ctrl->value = dev->mute;
- return 0;
- case V4L2_CID_AUDIO_VOLUME:
- ctrl->value = dev->volume;
+ em28xx_release_buffers(dev);
+
+ /* the device is already disconnect, free the remaining resources */
+ if (dev->state & DEV_DISCONNECTED) {
+ em28xx_release_resources(dev);
+ mutex_unlock(&dev->lock);
+ kfree(dev);
return 0;
- default:
- return -EINVAL;
}
-}
-/*
- * em28xx_set_ctrl()
- * mute or set new saturation, brightness or contrast
- */
-static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
-{
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- if (ctrl->value != dev->mute) {
- dev->mute = ctrl->value;
- return em28xx_audio_analog_set(dev);
- }
- return 0;
- case V4L2_CID_AUDIO_VOLUME:
- dev->volume = ctrl->value;
- return em28xx_audio_analog_set(dev);
- default:
- return -EINVAL;
+ /* set alternate 0 */
+ dev->alt = 0;
+ em28xx_videodbg("setting alternate 0\n");
+ errCode = usb_set_interface(dev->udev, 0, 0);
+ if (errCode < 0) {
+ em28xx_errdev ("cannot change alternate number to 0 (error=%i)\n",
+ errCode);
}
+
+ dev->users--;
+ wake_up_interruptible_nr(&dev->open, 1);
+ mutex_unlock(&dev->lock);
+ return 0;
}
/*
- * em28xx_stream_interrupt()
- * stops streaming
+ * em28xx_v4l2_read()
+ * will allocate buffers when called for the first time
*/
-static int em28xx_stream_interrupt(struct em28xx *dev)
+static ssize_t
+em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
+ loff_t * f_pos)
{
- int rc = 0;
-
- /* stop reading from the device */
-
- dev->stream = STREAM_INTERRUPT;
- rc = wait_event_timeout(dev->wait_stream,
- (dev->stream == STREAM_OFF) ||
- (dev->state & DEV_DISCONNECTED),
- EM28XX_URB_TIMEOUT);
+ struct em28xx_frame_t *f, *i;
+ unsigned long lock_flags;
+ int ret = 0;
+ struct em28xx *dev = filp->private_data;
- if (rc) {
- dev->state |= DEV_MISCONFIGURED;
- em28xx_videodbg("device is misconfigured; close and "
- "open /dev/video%d again\n",
- dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN);
- return rc;
+ if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ em28xx_videodbg("V4l2_Buf_type_videocapture is set\n");
+ }
+ if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+ em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n");
+ em28xx_videodbg("not supported yet! ...\n");
+ if (copy_to_user(buf, "", 1)) {
+ mutex_unlock(&dev->fileop_lock);
+ return -EFAULT;
+ }
+ return (1);
+ }
+ if (dev->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
+ em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n");
+ em28xx_videodbg("not supported yet! ...\n");
+ if (copy_to_user(buf, "", 1)) {
+ mutex_unlock(&dev->fileop_lock);
+ return -EFAULT;
+ }
+ return (1);
}
- return 0;
-}
-
+ if (mutex_lock_interruptible(&dev->fileop_lock))
+ return -ERESTARTSYS;
-static int check_dev(struct em28xx *dev)
-{
if (dev->state & DEV_DISCONNECTED) {
- em28xx_errdev("v4l2 ioctl: device not present\n");
+ em28xx_videodbg("device not present\n");
+ mutex_unlock(&dev->fileop_lock);
return -ENODEV;
}
if (dev->state & DEV_MISCONFIGURED) {
- em28xx_errdev("v4l2 ioctl: device is misconfigured; "
- "close and open it again\n");
+ em28xx_videodbg("device misconfigured; close and open it again\n");
+ mutex_unlock(&dev->fileop_lock);
return -EIO;
}
- return 0;
-}
-static void get_scale(struct em28xx *dev,
- unsigned int width, unsigned int height,
- unsigned int *hscale, unsigned int *vscale)
-{
- unsigned int maxw = norm_maxw(dev);
- unsigned int maxh = norm_maxh(dev);
+ if (dev->io == IO_MMAP) {
+ em28xx_videodbg ("IO method is set to mmap; close and open"
+ " the device again to choose the read method\n");
+ mutex_unlock(&dev->fileop_lock);
+ return -EINVAL;
+ }
- *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
- if (*hscale >= 0x4000)
- *hscale = 0x3fff;
+ if (dev->io == IO_NONE) {
+ if (!em28xx_request_buffers(dev, EM28XX_NUM_READ_FRAMES)) {
+ em28xx_errdev("read failed, not enough memory\n");
+ mutex_unlock(&dev->fileop_lock);
+ return -ENOMEM;
+ }
+ dev->io = IO_READ;
+ dev->stream = STREAM_ON;
+ em28xx_queue_unusedframes(dev);
+ }
- *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
- if (*vscale >= 0x4000)
- *vscale = 0x3fff;
-}
+ if (!count) {
+ mutex_unlock(&dev->fileop_lock);
+ return 0;
+ }
-/* ------------------------------------------------------------------
- IOCTL vidioc handling
- ------------------------------------------------------------------*/
+ if (list_empty(&dev->outqueue)) {
+ if (filp->f_flags & O_NONBLOCK) {
+ mutex_unlock(&dev->fileop_lock);
+ return -EAGAIN;
+ }
+ ret = wait_event_interruptible
+ (dev->wait_frame,
+ (!list_empty(&dev->outqueue)) ||
+ (dev->state & DEV_DISCONNECTED));
+ if (ret) {
+ mutex_unlock(&dev->fileop_lock);
+ return ret;
+ }
+ if (dev->state & DEV_DISCONNECTED) {
+ mutex_unlock(&dev->fileop_lock);
+ return -ENODEV;
+ }
+ }
-static int vidioc_g_fmt_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ f = list_entry(dev->outqueue.prev, struct em28xx_frame_t, frame);
- mutex_lock(&dev->lock);
+ spin_lock_irqsave(&dev->queue_lock, lock_flags);
+ list_for_each_entry(i, &dev->outqueue, frame)
+ i->state = F_UNUSED;
+ INIT_LIST_HEAD(&dev->outqueue);
+ spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
- f->fmt.pix.width = dev->width;
- f->fmt.pix.height = dev->height;
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- f->fmt.pix.bytesperline = dev->bytesperline;
- f->fmt.pix.sizeimage = dev->frame_size;
- f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ em28xx_queue_unusedframes(dev);
- /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
- f->fmt.pix.field = dev->interlaced ?
- V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
+ if (count > f->buf.length)
+ count = f->buf.length;
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-static int vidioc_try_fmt_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int width = f->fmt.pix.width;
- int height = f->fmt.pix.height;
- unsigned int maxw = norm_maxw(dev);
- unsigned int maxh = norm_maxh(dev);
- unsigned int hscale, vscale;
-
- /* width must even because of the YUYV format
- height must be even because of interlacing */
- height &= 0xfffe;
- width &= 0xfffe;
-
- if (height < 32)
- height = 32;
- if (height > maxh)
- height = maxh;
- if (width < 48)
- width = 48;
- if (width > maxw)
- width = maxw;
-
- mutex_lock(&dev->lock);
-
- if (dev->is_em2800) {
- /* the em2800 can only scale down to 50% */
- if (height % (maxh / 2))
- height = maxh;
- if (width % (maxw / 2))
- width = maxw;
- /* according to empiatech support */
- /* the MaxPacketSize is to small to support */
- /* framesizes larger than 640x480 @ 30 fps */
- /* or 640x576 @ 25 fps. As this would cut */
- /* of a part of the image we prefer */
- /* 360x576 or 360x480 for now */
- if (width == maxw && height == maxh)
- width /= 2;
- }
-
- get_scale(dev, width, height, &hscale, &vscale);
-
- width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
- height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
-
- f->fmt.pix.width = width;
- f->fmt.pix.height = height;
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- f->fmt.pix.bytesperline = width * 2;
- f->fmt.pix.sizeimage = width * 2 * height;
- f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-static int vidioc_s_fmt_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int rc, i;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- vidioc_try_fmt_cap(file, priv, f);
-
- mutex_lock(&dev->lock);
-
- for (i = 0; i < dev->num_frames; i++)
- if (dev->frame[i].vma_use_count) {
- em28xx_videodbg("VIDIOC_S_FMT failed. "
- "Unmap the buffers first.\n");
- rc = -EINVAL;
- goto err;
- }
-
- /* stop io in case it is already in progress */
- if (dev->stream == STREAM_ON) {
- em28xx_videodbg("VIDIOC_SET_FMT: interrupting stream\n");
- rc = em28xx_stream_interrupt(dev);
- if (rc < 0)
- goto err;
- }
-
- em28xx_release_buffers(dev);
- dev->io = IO_NONE;
-
- /* set new image size */
- dev->width = f->fmt.pix.width;
- dev->height = f->fmt.pix.height;
- dev->frame_size = dev->width * dev->height * 2;
- dev->field_size = dev->frame_size >> 1;
- dev->bytesperline = dev->width * 2;
- get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
-
- /* FIXME: This is really weird! Why capture is starting with
- this ioctl ???
- */
- em28xx_uninit_isoc(dev);
- em28xx_set_alternate(dev);
- em28xx_capture_start(dev, 1);
- em28xx_resolution_set(dev);
- em28xx_init_isoc(dev);
- rc = 0;
-
-err:
- mutex_unlock(&dev->lock);
- return rc;
-}
-
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- struct v4l2_format f;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- mutex_lock(&dev->lock);
- dev->norm = *norm;
- mutex_unlock(&dev->lock);
-
- /* Adjusts width/height, if needed */
- f.fmt.pix.width = dev->width;
- f.fmt.pix.height = dev->height;
- vidioc_try_fmt_cap(file, priv, &f);
-
- mutex_lock(&dev->lock);
-
- /* set new image size */
- dev->width = f.fmt.pix.width;
- dev->height = f.fmt.pix.height;
- dev->frame_size = dev->width * dev->height * 2;
- dev->field_size = dev->frame_size >> 1;
- dev->bytesperline = dev->width * 2;
- get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
-
- em28xx_resolution_set(dev);
- em28xx_i2c_call_clients(dev, VIDIOC_S_STD, &dev->norm);
-
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-static const char *iname[] = {
- [EM28XX_VMUX_COMPOSITE1] = "Composite1",
- [EM28XX_VMUX_COMPOSITE2] = "Composite2",
- [EM28XX_VMUX_COMPOSITE3] = "Composite3",
- [EM28XX_VMUX_COMPOSITE4] = "Composite4",
- [EM28XX_VMUX_SVIDEO] = "S-Video",
- [EM28XX_VMUX_TELEVISION] = "Television",
- [EM28XX_VMUX_CABLE] = "Cable TV",
- [EM28XX_VMUX_DVB] = "DVB",
- [EM28XX_VMUX_DEBUG] = "for debug only",
-};
-
-static int vidioc_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- unsigned int n;
-
- n = i->index;
- if (n >= MAX_EM28XX_INPUT)
- return -EINVAL;
- if (0 == INPUT(n)->type)
- return -EINVAL;
-
- i->index = n;
- i->type = V4L2_INPUT_TYPE_CAMERA;
-
- strcpy(i->name, iname[INPUT(n)->type]);
-
- if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
- (EM28XX_VMUX_CABLE == INPUT(n)->type))
- i->type = V4L2_INPUT_TYPE_TUNER;
-
- i->std = dev->vdev->tvnorms;
-
- return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
-
- *i = dev->ctl_input;
-
- return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- if (i >= MAX_EM28XX_INPUT)
- return -EINVAL;
- if (0 == INPUT(i)->type)
- return -EINVAL;
-
- mutex_lock(&dev->lock);
-
- video_mux(dev, i);
-
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- unsigned int index = a->index;
-
- if (a->index > 1)
- return -EINVAL;
-
- index = dev->ctl_ainput;
-
- if (index == 0) {
- strcpy(a->name, "Television");
- } else {
- strcpy(a->name, "Line In");
- }
- a->capability = V4L2_AUDCAP_STEREO;
- a->index = index;
-
- return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
-
- if (a->index != dev->ctl_ainput)
- return -EINVAL;
-
- return 0;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int id = qc->id;
- int i;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- memset(qc, 0, sizeof(*qc));
-
- qc->id = id;
-
- if (!dev->has_msp34xx) {
- for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
- if (qc->id && qc->id == em28xx_qctrl[i].id) {
- memcpy(qc, &(em28xx_qctrl[i]), sizeof(*qc));
- return 0;
- }
- }
- }
- mutex_lock(&dev->lock);
- em28xx_i2c_call_clients(dev, VIDIOC_QUERYCTRL, qc);
- mutex_unlock(&dev->lock);
-
- if (qc->type)
- return 0;
- else
- return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
- mutex_lock(&dev->lock);
-
- if (!dev->has_msp34xx)
- rc = em28xx_get_ctrl(dev, ctrl);
- else
- rc = -EINVAL;
-
- if (rc == -EINVAL) {
- em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl);
- rc = 0;
- }
-
- mutex_unlock(&dev->lock);
- return rc;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- u8 i;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- mutex_lock(&dev->lock);
-
- if (dev->has_msp34xx)
- em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl);
- else {
- rc = 1;
- for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
- if (ctrl->id == em28xx_qctrl[i].id) {
- if (ctrl->value < em28xx_qctrl[i].minimum ||
- ctrl->value > em28xx_qctrl[i].maximum) {
- rc = -ERANGE;
- break;
- }
-
- rc = em28xx_set_ctrl(dev, ctrl);
- break;
- }
- }
- }
-
- /* Control not found - try to send it to the attached devices */
- if (rc == 1) {
- em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl);
- rc = 0;
- }
-
- mutex_unlock(&dev->lock);
- return rc;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- if (0 != t->index)
- return -EINVAL;
-
- strcpy(t->name, "Tuner");
-
- mutex_lock(&dev->lock);
-
- em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
-
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- if (0 != t->index)
- return -EINVAL;
-
- mutex_lock(&dev->lock);
-
- em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t);
-
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
-
- f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
- f->frequency = dev->ctl_freq;
-
- return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- if (0 != f->tuner)
- return -EINVAL;
-
- if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
- return -EINVAL;
- if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
- return -EINVAL;
-
- mutex_lock(&dev->lock);
-
- dev->ctl_freq = f->frequency;
- em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f);
-
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-static int vidioc_cropcap(struct file *file, void *priv,
- struct v4l2_cropcap *cc)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
-
- if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- cc->bounds.left = 0;
- cc->bounds.top = 0;
- cc->bounds.width = dev->width;
- cc->bounds.height = dev->height;
- cc->defrect = cc->bounds;
- cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */
- cc->pixelaspect.denominator = 59;
-
- return 0;
-}
-
-static int vidioc_streamon(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
- return -EINVAL;
-
- if (list_empty(&dev->inqueue))
- return -EINVAL;
-
- mutex_lock(&dev->lock);
-
- if (unlikely(res_get(fh) < 0)) {
- mutex_unlock(&dev->lock);
- return -EBUSY;
- }
-
- dev->stream = STREAM_ON; /* FIXME: Start video capture here? */
-
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-static int vidioc_streamoff(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
- return -EINVAL;
-
- mutex_lock(&dev->lock);
-
- if (dev->stream == STREAM_ON) {
- em28xx_videodbg("VIDIOC_STREAMOFF: interrupting stream\n");
- rc = em28xx_stream_interrupt(dev);
- if (rc < 0) {
- mutex_unlock(&dev->lock);
- return rc;
- }
- }
-
- em28xx_empty_framequeues(dev);
-
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
-
- strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
- strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
- strlcpy(cap->bus_info, dev->udev->dev.bus_id, sizeof(cap->bus_info));
-
- cap->version = EM28XX_VERSION_CODE;
-
- cap->capabilities =
- V4L2_CAP_SLICED_VBI_CAPTURE |
- V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_AUDIO |
- V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
-
- if (dev->tuner_type != TUNER_ABSENT)
- cap->capabilities |= V4L2_CAP_TUNER;
-
- return 0;
-}
-
-static int vidioc_enum_fmt_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *fmtd)
-{
- if (fmtd->index != 0)
- return -EINVAL;
-
- fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- strcpy(fmtd->description, "Packed YUY2");
- fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
- memset(fmtd->reserved, 0, sizeof(fmtd->reserved));
-
- return 0;
-}
-
-/* Sliced VBI ioctls */
-static int vidioc_g_fmt_vbi_capture(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- mutex_lock(&dev->lock);
-
- f->fmt.sliced.service_set = 0;
-
- em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f);
-
- if (f->fmt.sliced.service_set == 0)
- rc = -EINVAL;
-
- mutex_unlock(&dev->lock);
- return rc;
-}
-
-static int vidioc_try_set_vbi_capture(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- mutex_lock(&dev->lock);
- em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f);
- mutex_unlock(&dev->lock);
-
- if (f->fmt.sliced.service_set == 0)
- return -EINVAL;
-
- return 0;
-}
-
-
-static int vidioc_reqbufs(struct file *file, void *priv,
- struct v4l2_requestbuffers *rb)
-{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- u32 i;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- rb->memory != V4L2_MEMORY_MMAP)
- return -EINVAL;
-
- if (dev->io == IO_READ) {
- em28xx_videodbg("method is set to read;"
- " close and open the device again to"
- " choose the mmap I/O method\n");
- return -EINVAL;
- }
-
- for (i = 0; i < dev->num_frames; i++)
- if (dev->frame[i].vma_use_count) {
- em28xx_videodbg("VIDIOC_REQBUFS failed; "
- "previous buffers are still mapped\n");
- return -EINVAL;
- }
-
- mutex_lock(&dev->lock);
-
- if (dev->stream == STREAM_ON) {
- em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n");
- rc = em28xx_stream_interrupt(dev);
- if (rc < 0) {
- mutex_unlock(&dev->lock);
- return rc;
- }
+ if (copy_to_user(buf, f->bufmem, count)) {
+ mutex_unlock(&dev->fileop_lock);
+ return -EFAULT;
}
+ *f_pos += count;
- em28xx_empty_framequeues(dev);
-
- em28xx_release_buffers(dev);
- if (rb->count)
- rb->count = em28xx_request_buffers(dev, rb->count);
-
- dev->frame_current = NULL;
- dev->io = rb->count ? IO_MMAP : IO_NONE;
+ mutex_unlock(&dev->fileop_lock);
- mutex_unlock(&dev->lock);
- return 0;
+ return count;
}
-static int vidioc_querybuf(struct file *file, void *priv,
- struct v4l2_buffer *b)
+/*
+ * em28xx_v4l2_poll()
+ * will allocate buffers when called for the first time
+ */
+static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int rc;
+ unsigned int mask = 0;
+ struct em28xx *dev = filp->private_data;
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
+ if (mutex_lock_interruptible(&dev->fileop_lock))
+ return POLLERR;
- if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- b->index >= dev->num_frames || dev->io != IO_MMAP)
- return -EINVAL;
+ if (dev->state & DEV_DISCONNECTED) {
+ em28xx_videodbg("device not present\n");
+ } else if (dev->state & DEV_MISCONFIGURED) {
+ em28xx_videodbg("device is misconfigured; close and open it again\n");
+ } else {
+ if (dev->io == IO_NONE) {
+ if (!em28xx_request_buffers
+ (dev, EM28XX_NUM_READ_FRAMES)) {
+ em28xx_warn
+ ("poll() failed, not enough memory\n");
+ } else {
+ dev->io = IO_READ;
+ dev->stream = STREAM_ON;
+ }
+ }
- mutex_lock(&dev->lock);
+ if (dev->io == IO_READ) {
+ em28xx_queue_unusedframes(dev);
+ poll_wait(filp, &dev->wait_frame, wait);
- memcpy(b, &dev->frame[b->index].buf, sizeof(*b));
+ if (!list_empty(&dev->outqueue))
+ mask |= POLLIN | POLLRDNORM;
- if (dev->frame[b->index].vma_use_count)
- b->flags |= V4L2_BUF_FLAG_MAPPED;
+ mutex_unlock(&dev->fileop_lock);
- if (dev->frame[b->index].state == F_DONE)
- b->flags |= V4L2_BUF_FLAG_DONE;
- else if (dev->frame[b->index].state != F_UNUSED)
- b->flags |= V4L2_BUF_FLAG_QUEUED;
+ return mask;
+ }
+ }
- mutex_unlock(&dev->lock);
- return 0;
+ mutex_unlock(&dev->fileop_lock);
+ return POLLERR;
}
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+/*
+ * em28xx_vm_open()
+ */
+static void em28xx_vm_open(struct vm_area_struct *vma)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- unsigned long lock_flags;
- int rc;
-
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
-
- if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP ||
- b->index >= dev->num_frames)
- return -EINVAL;
-
- if (dev->frame[b->index].state != F_UNUSED)
- return -EAGAIN;
-
- dev->frame[b->index].state = F_QUEUED;
-
- /* add frame to fifo */
- spin_lock_irqsave(&dev->queue_lock, lock_flags);
- list_add_tail(&dev->frame[b->index].frame, &dev->inqueue);
- spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-
- return 0;
+ struct em28xx_frame_t *f = vma->vm_private_data;
+ f->vma_use_count++;
}
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+/*
+ * em28xx_vm_close()
+ */
+static void em28xx_vm_close(struct vm_area_struct *vma)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
- int rc;
- struct em28xx_frame_t *f;
- unsigned long lock_flags;
+ /* NOTE: buffers are not freed here */
+ struct em28xx_frame_t *f = vma->vm_private_data;
- rc = check_dev(dev);
- if (rc < 0)
- return rc;
+ if (f->vma_use_count)
+ f->vma_use_count--;
+}
- if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
- return -EINVAL;
+static struct vm_operations_struct em28xx_vm_ops = {
+ .open = em28xx_vm_open,
+ .close = em28xx_vm_close,
+};
- if (list_empty(&dev->outqueue)) {
- if (dev->stream == STREAM_OFF)
- return -EINVAL;
+/*
+ * em28xx_v4l2_mmap()
+ */
+static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ unsigned long size = vma->vm_end - vma->vm_start,
+ start = vma->vm_start;
+ void *pos;
+ u32 i;
- if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
+ struct em28xx *dev = filp->private_data;
- rc = wait_event_interruptible(dev->wait_frame,
- (!list_empty(&dev->outqueue)) ||
- (dev->state & DEV_DISCONNECTED));
- if (rc)
- return rc;
+ if (mutex_lock_interruptible(&dev->fileop_lock))
+ return -ERESTARTSYS;
- if (dev->state & DEV_DISCONNECTED)
- return -ENODEV;
+ if (dev->state & DEV_DISCONNECTED) {
+ em28xx_videodbg("mmap: device not present\n");
+ mutex_unlock(&dev->fileop_lock);
+ return -ENODEV;
}
- spin_lock_irqsave(&dev->queue_lock, lock_flags);
- f = list_entry(dev->outqueue.next, struct em28xx_frame_t, frame);
- list_del(dev->outqueue.next);
- spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-
- f->state = F_UNUSED;
- memcpy(b, &f->buf, sizeof(*b));
+ if (dev->state & DEV_MISCONFIGURED) {
+ em28xx_videodbg ("mmap: Device is misconfigured; close and "
+ "open it again\n");
+ mutex_unlock(&dev->fileop_lock);
+ return -EIO;
+ }
- if (f->vma_use_count)
- b->flags |= V4L2_BUF_FLAG_MAPPED;
+ if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
+ size != PAGE_ALIGN(dev->frame[0].buf.length)) {
+ mutex_unlock(&dev->fileop_lock);
+ return -EINVAL;
+ }
- return 0;
-}
+ for (i = 0; i < dev->num_frames; i++) {
+ if ((dev->frame[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
+ break;
+ }
+ if (i == dev->num_frames) {
+ em28xx_videodbg("mmap: user supplied mapping address is out of range\n");
+ mutex_unlock(&dev->fileop_lock);
+ return -EINVAL;
+ }
-/* ----------------------------------------------------------- */
-/* RADIO ESPECIFIC IOCTLS */
-/* ----------------------------------------------------------- */
+ /* VM_IO is eventually going to replace PageReserved altogether */
+ vma->vm_flags |= VM_IO;
+ vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
-static int radio_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
+ pos = dev->frame[i].bufmem;
+ while (size > 0) { /* size is page-aligned */
+ if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
+ em28xx_videodbg("mmap: vm_insert_page failed\n");
+ mutex_unlock(&dev->fileop_lock);
+ return -EAGAIN;
+ }
+ start += PAGE_SIZE;
+ pos += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
- strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
- strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
- strlcpy(cap->bus_info, dev->udev->dev.bus_id, sizeof(cap->bus_info));
+ vma->vm_ops = &em28xx_vm_ops;
+ vma->vm_private_data = &dev->frame[i];
- cap->version = EM28XX_VERSION_CODE;
- cap->capabilities = V4L2_CAP_TUNER;
+ em28xx_vm_open(vma);
+ mutex_unlock(&dev->fileop_lock);
return 0;
}
-static int radio_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
+/*
+ * em28xx_get_ctrl()
+ * return the current saturation, brightness or contrast, mute state
+ */
+static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
{
- struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
-
- if (unlikely(t->index > 0))
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ ctrl->value = dev->mute;
+ return 0;
+ case V4L2_CID_AUDIO_VOLUME:
+ ctrl->value = dev->volume;
+ return 0;
+ default:
return -EINVAL;
-
- strcpy(t->name, "Radio");
- t->type = V4L2_TUNER_RADIO;
-
- em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
- return 0;
+ }
}
-static int radio_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
+/*
+ * em28xx_set_ctrl()
+ * mute or set new saturation, brightness or contrast
+ */
+static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
{
- if (i->index != 0)
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ if (ctrl->value != dev->mute) {
+ dev->mute = ctrl->value;
+ em28xx_audio_usb_mute(dev, ctrl->value);
+ return em28xx_audio_analog_set(dev);
+ }
+ return 0;
+ case V4L2_CID_AUDIO_VOLUME:
+ dev->volume = ctrl->value;
+ return em28xx_audio_analog_set(dev);
+ default:
return -EINVAL;
- strcpy(i->name, "Radio");
- i->type = V4L2_INPUT_TYPE_TUNER;
-
- return 0;
+ }
}
-static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+/*
+ * em28xx_stream_interrupt()
+ * stops streaming
+ */
+static int em28xx_stream_interrupt(struct em28xx *dev)
{
- if (unlikely(a->index))
- return -EINVAL;
+ int ret = 0;
+
+ /* stop reading from the device */
+
+ dev->stream = STREAM_INTERRUPT;
+ ret = wait_event_timeout(dev->wait_stream,
+ (dev->stream == STREAM_OFF) ||
+ (dev->state & DEV_DISCONNECTED),
+ EM28XX_URB_TIMEOUT);
+ if (dev->state & DEV_DISCONNECTED)
+ return -ENODEV;
+ else if (ret) {
+ dev->state |= DEV_MISCONFIGURED;
+ em28xx_videodbg("device is misconfigured; close and "
+ "open /dev/video%d again\n",
+ dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN);
+ return ret;
+ }
- strcpy(a->name, "Radio");
return 0;
}
-static int radio_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
+static int em28xx_set_norm(struct em28xx *dev, int width, int height)
{
- struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
-
- if (0 != t->index)
- return -EINVAL;
+ unsigned int hscale, vscale;
+ unsigned int maxh, maxw;
- em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t);
+ maxw = norm_maxw(dev);
+ maxh = norm_maxh(dev);
- return 0;
-}
+ /* width must even because of the YUYV format */
+ /* height must be even because of interlacing */
+ height &= 0xfffe;
+ width &= 0xfffe;
-static int radio_s_audio(struct file *file, void *fh,
- struct v4l2_audio *a)
-{
- return 0;
-}
+ if (height < 32)
+ height = 32;
+ if (height > maxh)
+ height = maxh;
+ if (width < 48)
+ width = 48;
+ if (width > maxw)
+ width = maxw;
-static int radio_s_input(struct file *file, void *fh, unsigned int i)
-{
- return 0;
-}
+ if ((hscale = (((unsigned long)maxw) << 12) / width - 4096L) >= 0x4000)
+ hscale = 0x3fff;
+ width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
-static int radio_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- int i;
+ if ((vscale = (((unsigned long)maxh) << 12) / height - 4096L) >= 0x4000)
+ vscale = 0x3fff;
+ height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
- if (qc->id < V4L2_CID_BASE ||
- qc->id >= V4L2_CID_LASTP1)
- return -EINVAL;
+ /* set new image size */
+ dev->width = width;
+ dev->height = height;
+ dev->frame_size = dev->width * dev->height * 2;
+ dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */
+ dev->bytesperline = dev->width * 2;
+ dev->hscale = hscale;
+ dev->vscale = vscale;
- for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
- if (qc->id && qc->id == em28xx_qctrl[i].id) {
- memcpy(qc, &(em28xx_qctrl[i]), sizeof(*qc));
- return 0;
- }
- }
+ em28xx_resolution_set(dev);
- return -EINVAL;
+ return 0;
}
-/*
- * em28xx_v4l2_open()
- * inits the device and starts isoc transfer
- */
-static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
+static int em28xx_get_fmt(struct em28xx *dev, struct v4l2_format *format)
{
- int minor = iminor(inode);
- int errCode = 0, radio = 0;
- struct em28xx *h,*dev = NULL;
- struct em28xx_fh *fh;
+ em28xx_videodbg("VIDIOC_G_FMT: type=%s\n",
+ (format->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE) ?
+ "V4L2_BUF_TYPE_VIDEO_CAPTURE" :
+ (format->type ==V4L2_BUF_TYPE_VBI_CAPTURE) ?
+ "V4L2_BUF_TYPE_VBI_CAPTURE" :
+ (format->type ==V4L2_CAP_SLICED_VBI_CAPTURE) ?
+ "V4L2_BUF_TYPE_SLICED_VBI_CAPTURE " :
+ "not supported");
- list_for_each_entry(h, &em28xx_devlist, devlist) {
- if (h->vdev->minor == minor) {
- dev = h;
- dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- }
- if (h->vbi_dev->minor == minor) {
- dev = h;
- dev->type = V4L2_BUF_TYPE_VBI_CAPTURE;
- }
- if (h->radio_dev &&
- h->radio_dev->minor == minor) {
- radio = 1;
- dev = h;
- }
+ switch (format->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ {
+ format->fmt.pix.width = dev->width;
+ format->fmt.pix.height = dev->height;
+ format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ format->fmt.pix.bytesperline = dev->bytesperline;
+ format->fmt.pix.sizeimage = dev->frame_size;
+ format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ format->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
+
+ em28xx_videodbg("VIDIOC_G_FMT: %dx%d\n", dev->width,
+ dev->height);
+ break;
}
- if (NULL == dev)
- return -ENODEV;
- em28xx_videodbg("open minor=%d type=%s users=%d\n",
- minor,v4l2_type_names[dev->type],dev->users);
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ {
+ format->fmt.sliced.service_set=0;
- fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
+ em28xx_i2c_call_clients(dev,VIDIOC_G_FMT,format);
- if (!fh) {
- em28xx_errdev("em28xx-video.c: Out of memory?!\n");
- return -ENOMEM;
+ if (format->fmt.sliced.service_set==0)
+ return -EINVAL;
+
+ break;
}
- mutex_lock(&dev->lock);
- fh->dev = dev;
- fh->radio = radio;
- filp->private_data = fh;
- if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
- em28xx_set_alternate(dev);
+ default:
+ return -EINVAL;
+ }
+ return (0);
+}
- dev->width = norm_maxw(dev);
- dev->height = norm_maxh(dev);
- dev->frame_size = dev->width * dev->height * 2;
- dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */
- dev->bytesperline = dev->width * 2;
- dev->hscale = 0;
- dev->vscale = 0;
+static int em28xx_set_fmt(struct em28xx *dev, unsigned int cmd, struct v4l2_format *format)
+{
+ u32 i;
+ int ret = 0;
+ int width = format->fmt.pix.width;
+ int height = format->fmt.pix.height;
+ unsigned int hscale, vscale;
+ unsigned int maxh, maxw;
- em28xx_capture_start(dev, 1);
- em28xx_resolution_set(dev);
+ maxw = norm_maxw(dev);
+ maxh = norm_maxh(dev);
+ em28xx_videodbg("%s: type=%s\n",
+ cmd == VIDIOC_TRY_FMT ?
+ "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT",
+ format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
+ "V4L2_BUF_TYPE_VIDEO_CAPTURE" :
+ format->type == V4L2_BUF_TYPE_VBI_CAPTURE ?
+ "V4L2_BUF_TYPE_VBI_CAPTURE " :
+ "not supported");
- /* start the transfer */
- errCode = em28xx_init_isoc(dev);
- if (errCode)
- goto err;
+ if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
+ em28xx_i2c_call_clients(dev,VIDIOC_G_FMT,format);
- em28xx_empty_framequeues(dev);
- }
- if (fh->radio) {
- em28xx_videodbg("video_open: setting radio device\n");
- em28xx_i2c_call_clients(dev, AUDC_SET_RADIO, NULL);
+ if (format->fmt.sliced.service_set==0)
+ return -EINVAL;
+
+ return 0;
}
- dev->users++;
-err:
- mutex_unlock(&dev->lock);
- return errCode;
-}
+ if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
-/*
- * em28xx_realease_resources()
- * unregisters the v4l2,i2c and usb devices
- * called when the device gets disconected or at module unload
-*/
-static void em28xx_release_resources(struct em28xx *dev)
-{
+ em28xx_videodbg("%s: requested %dx%d\n",
+ cmd == VIDIOC_TRY_FMT ?
+ "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT",
+ format->fmt.pix.width, format->fmt.pix.height);
- /*FIXME: I2C IR should be disconnected */
+ /* FIXME: Move some code away from here */
+ /* width must even because of the YUYV format */
+ /* height must be even because of interlacing */
+ height &= 0xfffe;
+ width &= 0xfffe;
- em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n",
- dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN,
- dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN);
- list_del(&dev->devlist);
- if (dev->radio_dev) {
- if (-1 != dev->radio_dev->minor)
- video_unregister_device(dev->radio_dev);
- else
- video_device_release(dev->radio_dev);
- dev->radio_dev = NULL;
- }
- if (dev->vbi_dev) {
- if (-1 != dev->vbi_dev->minor)
- video_unregister_device(dev->vbi_dev);
- else
- video_device_release(dev->vbi_dev);
- dev->vbi_dev = NULL;
- }
- if (dev->vdev) {
- if (-1 != dev->vdev->minor)
- video_unregister_device(dev->vdev);
- else
- video_device_release(dev->vdev);
- dev->vdev = NULL;
+ if (height < 32)
+ height = 32;
+ if (height > maxh)
+ height = maxh;
+ if (width < 48)
+ width = 48;
+ if (width > maxw)
+ width = maxw;
+
+ if(dev->is_em2800){
+ /* the em2800 can only scale down to 50% */
+ if(height % (maxh / 2))
+ height=maxh;
+ if(width % (maxw / 2))
+ width=maxw;
+ /* according to empiatech support */
+ /* the MaxPacketSize is to small to support */
+ /* framesizes larger than 640x480 @ 30 fps */
+ /* or 640x576 @ 25 fps. As this would cut */
+ /* of a part of the image we prefer */
+ /* 360x576 or 360x480 for now */
+ if(width == maxw && height == maxh)
+ width /= 2;
}
- em28xx_i2c_unregister(dev);
- usb_put_dev(dev->udev);
- /* Mark device as unused */
- em28xx_devused&=~(1<devno);
-}
+ if ((hscale = (((unsigned long)maxw) << 12) / width - 4096L) >= 0x4000)
+ hscale = 0x3fff;
-/*
- * em28xx_v4l2_close()
- * stops streaming and deallocates all resources allocated by the v4l2 calls and ioctls
- */
-static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
-{
- struct em28xx_fh *fh = filp->private_data;
- struct em28xx *dev = fh->dev;
- int errCode;
+ width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
- em28xx_videodbg("users=%d\n", dev->users);
+ if ((vscale = (((unsigned long)maxh) << 12) / height - 4096L) >= 0x4000)
+ vscale = 0x3fff;
+ height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
- if (res_check(fh))
- res_free(fh);
+ format->fmt.pix.width = width;
+ format->fmt.pix.height = height;
+ format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ format->fmt.pix.bytesperline = width * 2;
+ format->fmt.pix.sizeimage = width * 2 * height;
+ format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ format->fmt.pix.field = V4L2_FIELD_INTERLACED;
- mutex_lock(&dev->lock);
+ em28xx_videodbg("%s: returned %dx%d (%d, %d)\n",
+ cmd == VIDIOC_TRY_FMT ?
+ "VIDIOC_TRY_FMT" :"VIDIOC_S_FMT",
+ format->fmt.pix.width, format->fmt.pix.height, hscale, vscale);
- if (dev->users == 1) {
- em28xx_uninit_isoc(dev);
- em28xx_release_buffers(dev);
- dev->io = IO_NONE;
+ if (cmd == VIDIOC_TRY_FMT)
+ return 0;
- /* the device is already disconnect,
- free the remaining resources */
- if (dev->state & DEV_DISCONNECTED) {
- em28xx_release_resources(dev);
- mutex_unlock(&dev->lock);
- kfree(dev);
- return 0;
+ for (i = 0; i < dev->num_frames; i++)
+ if (dev->frame[i].vma_use_count) {
+ em28xx_videodbg("VIDIOC_S_FMT failed. "
+ "Unmap the buffers first.\n");
+ return -EINVAL;
}
- /* set alternate 0 */
- dev->alt = 0;
- em28xx_videodbg("setting alternate 0\n");
- errCode = usb_set_interface(dev->udev, 0, 0);
- if (errCode < 0) {
- em28xx_errdev("cannot change alternate number to "
- "0 (error=%i)\n", errCode);
- }
+ /* stop io in case it is already in progress */
+ if (dev->stream == STREAM_ON) {
+ em28xx_videodbg("VIDIOC_SET_FMT: interrupting stream\n");
+ if ((ret = em28xx_stream_interrupt(dev)))
+ return ret;
}
- kfree(fh);
- dev->users--;
- wake_up_interruptible_nr(&dev->open, 1);
- mutex_unlock(&dev->lock);
+
+ em28xx_release_buffers(dev);
+ dev->io = IO_NONE;
+
+ /* set new image size */
+ dev->width = width;
+ dev->height = height;
+ dev->frame_size = dev->width * dev->height * 2;
+ dev->field_size = dev->frame_size >> 1;
+ dev->bytesperline = dev->width * 2;
+ dev->hscale = hscale;
+ dev->vscale = vscale;
+ em28xx_uninit_isoc(dev);
+ em28xx_set_alternate(dev);
+ em28xx_capture_start(dev, 1);
+ em28xx_resolution_set(dev);
+ em28xx_init_isoc(dev);
+
return 0;
}
/*
- * em28xx_v4l2_read()
- * will allocate buffers when called for the first time
+ * em28xx_v4l2_do_ioctl()
+ * This function is _not_ called directly, but from
+ * em28xx_v4l2_ioctl. Userspace
+ * copying is done already, arg is a kernel pointer.
*/
-static ssize_t
-em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
- loff_t * f_pos)
+static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
+ struct em28xx *dev, unsigned int cmd, void *arg,
+ v4l2_kioctl driver_ioctl)
{
- struct em28xx_frame_t *f, *i;
- unsigned long lock_flags;
- int ret = 0;
- struct em28xx_fh *fh = filp->private_data;
- struct em28xx *dev = fh->dev;
+ int ret;
- /* FIXME: read() is not prepared to allow changing the video
- resolution while streaming. Seems a bug at em28xx_set_fmt
- */
+ switch (cmd) {
+ /* ---------- tv norms ---------- */
+ case VIDIOC_ENUMSTD:
+ {
+ struct v4l2_standard *e = arg;
+ unsigned int i;
- if (unlikely(res_get(fh) < 0))
- return -EBUSY;
+ i = e->index;
+ if (i >= TVNORMS)
+ return -EINVAL;
+ ret = v4l2_video_std_construct(e, tvnorms[e->index].id,
+ tvnorms[e->index].name);
+ e->index = i;
+ if (ret < 0)
+ return ret;
+ return 0;
+ }
+ case VIDIOC_G_STD:
+ {
+ v4l2_std_id *id = arg;
- mutex_lock(&dev->lock);
+ *id = dev->tvnorm->id;
+ return 0;
+ }
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *id = arg;
+ unsigned int i;
- if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
- em28xx_videodbg("V4l2_Buf_type_videocapture is set\n");
+ for (i = 0; i < TVNORMS; i++)
+ if (*id == tvnorms[i].id)
+ break;
+ if (i == TVNORMS)
+ for (i = 0; i < TVNORMS; i++)
+ if (*id & tvnorms[i].id)
+ break;
+ if (i == TVNORMS)
+ return -EINVAL;
+
+ mutex_lock(&dev->lock);
+ dev->tvnorm = &tvnorms[i];
+
+ em28xx_set_norm(dev, dev->width, dev->height);
+
+ em28xx_i2c_call_clients(dev, VIDIOC_S_STD,
+ &dev->tvnorm->id);
- if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
- em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n");
- em28xx_videodbg("not supported yet! ...\n");
- if (copy_to_user(buf, "", 1)) {
- mutex_unlock(&dev->lock);
- return -EFAULT;
- }
- mutex_unlock(&dev->lock);
- return (1);
- }
- if (dev->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
- em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n");
- em28xx_videodbg("not supported yet! ...\n");
- if (copy_to_user(buf, "", 1)) {
- mutex_unlock(&dev->lock);
- return -EFAULT;
- }
mutex_unlock(&dev->lock);
- return (1);
+
+ return 0;
}
- if (dev->state & DEV_DISCONNECTED) {
- em28xx_videodbg("device not present\n");
- mutex_unlock(&dev->lock);
- return -ENODEV;
+ /* ------ input switching ---------- */
+ case VIDIOC_ENUMINPUT:
+ {
+ struct v4l2_input *i = arg;
+ unsigned int n;
+ static const char *iname[] = {
+ [EM28XX_VMUX_COMPOSITE1] = "Composite1",
+ [EM28XX_VMUX_COMPOSITE2] = "Composite2",
+ [EM28XX_VMUX_COMPOSITE3] = "Composite3",
+ [EM28XX_VMUX_COMPOSITE4] = "Composite4",
+ [EM28XX_VMUX_SVIDEO] = "S-Video",
+ [EM28XX_VMUX_TELEVISION] = "Television",
+ [EM28XX_VMUX_CABLE] = "Cable TV",
+ [EM28XX_VMUX_DVB] = "DVB",
+ [EM28XX_VMUX_DEBUG] = "for debug only",
+ };
+
+ n = i->index;
+ if (n >= MAX_EM28XX_INPUT)
+ return -EINVAL;
+ if (0 == INPUT(n)->type)
+ return -EINVAL;
+ memset(i, 0, sizeof(*i));
+ i->index = n;
+ i->type = V4L2_INPUT_TYPE_CAMERA;
+ strcpy(i->name, iname[INPUT(n)->type]);
+ if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
+ (EM28XX_VMUX_CABLE == INPUT(n)->type))
+ i->type = V4L2_INPUT_TYPE_TUNER;
+ for (n = 0; n < ARRAY_SIZE(tvnorms); n++)
+ i->std |= tvnorms[n].id;
+ return 0;
}
+ case VIDIOC_G_INPUT:
+ {
+ int *i = arg;
+ *i = dev->ctl_input;
- if (dev->state & DEV_MISCONFIGURED) {
- em28xx_videodbg("device misconfigured; close and open it again\n");
- mutex_unlock(&dev->lock);
- return -EIO;
+ return 0;
}
+ case VIDIOC_S_INPUT:
+ {
+ int *index = arg;
- if (dev->io == IO_MMAP) {
- em28xx_videodbg ("IO method is set to mmap; close and open"
- " the device again to choose the read method\n");
+ if (*index >= MAX_EM28XX_INPUT)
+ return -EINVAL;
+ if (0 == INPUT(*index)->type)
+ return -EINVAL;
+
+ mutex_lock(&dev->lock);
+ video_mux(dev, *index);
mutex_unlock(&dev->lock);
- return -EINVAL;
+
+ return 0;
}
+ case VIDIOC_G_AUDIO:
+ {
+ struct v4l2_audio *a = arg;
+ unsigned int index = a->index;
- if (dev->io == IO_NONE) {
- if (!em28xx_request_buffers(dev, EM28XX_NUM_READ_FRAMES)) {
- em28xx_errdev("read failed, not enough memory\n");
- mutex_unlock(&dev->lock);
- return -ENOMEM;
+ if (a->index > 1)
+ return -EINVAL;
+ memset(a, 0, sizeof(*a));
+ index = dev->ctl_ainput;
+
+ if (index == 0) {
+ strcpy(a->name, "Television");
+ } else {
+ strcpy(a->name, "Line In");
}
- dev->io = IO_READ;
- dev->stream = STREAM_ON;
- em28xx_queue_unusedframes(dev);
+ a->capability = V4L2_AUDCAP_STEREO;
+ a->index = index;
+ return 0;
}
+ case VIDIOC_S_AUDIO:
+ {
+ struct v4l2_audio *a = arg;
+
+ if (a->index != dev->ctl_ainput)
+ return -EINVAL;
- if (!count) {
- mutex_unlock(&dev->lock);
return 0;
}
- if (list_empty(&dev->outqueue)) {
- if (filp->f_flags & O_NONBLOCK) {
- mutex_unlock(&dev->lock);
- return -EAGAIN;
- }
- ret = wait_event_interruptible
- (dev->wait_frame,
- (!list_empty(&dev->outqueue)) ||
- (dev->state & DEV_DISCONNECTED));
- if (ret) {
- mutex_unlock(&dev->lock);
- return ret;
- }
- if (dev->state & DEV_DISCONNECTED) {
- mutex_unlock(&dev->lock);
- return -ENODEV;
+ /* --- controls ---------------------------------------------- */
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *qc = arg;
+ int i, id=qc->id;
+
+ memset(qc,0,sizeof(*qc));
+ qc->id=id;
+
+ if (!dev->has_msp34xx) {
+ for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
+ if (qc->id && qc->id == em28xx_qctrl[i].id) {
+ memcpy(qc, &(em28xx_qctrl[i]),
+ sizeof(*qc));
+ return 0;
+ }
+ }
}
- dev->video_bytesread = 0;
+ em28xx_i2c_call_clients(dev,cmd,qc);
+ if (qc->type)
+ return 0;
+ else
+ return -EINVAL;
}
+ case VIDIOC_G_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+ int retval=-EINVAL;
- f = list_entry(dev->outqueue.prev, struct em28xx_frame_t, frame);
+ if (!dev->has_msp34xx)
+ retval=em28xx_get_ctrl(dev, ctrl);
+ if (retval==-EINVAL) {
+ em28xx_i2c_call_clients(dev,cmd,arg);
+ return 0;
+ } else return retval;
+ }
+ case VIDIOC_S_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+ u8 i;
+
+ if (!dev->has_msp34xx){
+ for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
+ if (ctrl->id == em28xx_qctrl[i].id) {
+ if (ctrl->value <
+ em28xx_qctrl[i].minimum
+ || ctrl->value >
+ em28xx_qctrl[i].maximum)
+ return -ERANGE;
+ return em28xx_set_ctrl(dev, ctrl);
+ }
+ }
+ }
- em28xx_queue_unusedframes(dev);
+ em28xx_i2c_call_clients(dev,cmd,arg);
+ return 0;
+ }
+ /* --- tuner ioctls ------------------------------------------ */
+ case VIDIOC_G_TUNER:
+ {
+ struct v4l2_tuner *t = arg;
- if (count > f->buf.length)
- count = f->buf.length;
+ if (0 != t->index)
+ return -EINVAL;
- if ((dev->video_bytesread + count) > dev->frame_size)
- count = dev->frame_size - dev->video_bytesread;
+ memset(t, 0, sizeof(*t));
+ strcpy(t->name, "Tuner");
+ mutex_lock(&dev->lock);
+ /* let clients fill in the remainder of this struct */
+ em28xx_i2c_call_clients(dev, cmd, t);
+ mutex_unlock(&dev->lock);
+ em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x\n", t->signal,
+ t->afc);
+ return 0;
+ }
+ case VIDIOC_S_TUNER:
+ {
+ struct v4l2_tuner *t = arg;
- if (copy_to_user(buf, f->bufmem+dev->video_bytesread, count)) {
- em28xx_err("Error while copying to user\n");
- return -EFAULT;
+ if (0 != t->index)
+ return -EINVAL;
+ mutex_lock(&dev->lock);
+ /* let clients handle this */
+ em28xx_i2c_call_clients(dev, cmd, t);
+ mutex_unlock(&dev->lock);
+ return 0;
}
- dev->video_bytesread += count;
+ case VIDIOC_G_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
- if (dev->video_bytesread == dev->frame_size) {
- spin_lock_irqsave(&dev->queue_lock, lock_flags);
- list_for_each_entry(i, &dev->outqueue, frame)
- i->state = F_UNUSED;
- INIT_LIST_HEAD(&dev->outqueue);
- spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
+ memset(f, 0, sizeof(*f));
+ f->type = V4L2_TUNER_ANALOG_TV;
+ f->frequency = dev->ctl_freq;
- em28xx_queue_unusedframes(dev);
- dev->video_bytesread = 0;
+ return 0;
}
+ case VIDIOC_S_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
- *f_pos += count;
+ if (0 != f->tuner)
+ return -EINVAL;
- mutex_unlock(&dev->lock);
+ if (V4L2_TUNER_ANALOG_TV != f->type)
+ return -EINVAL;
- return count;
-}
+ mutex_lock(&dev->lock);
+ dev->ctl_freq = f->frequency;
+ em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f);
+ mutex_unlock(&dev->lock);
+ return 0;
+ }
+ case VIDIOC_CROPCAP:
+ {
+ struct v4l2_cropcap *cc = arg;
-/*
- * em28xx_v4l2_poll()
- * will allocate buffers when called for the first time
- */
-static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait)
-{
- unsigned int mask = 0;
- struct em28xx_fh *fh = filp->private_data;
- struct em28xx *dev = fh->dev;
+ if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ cc->bounds.left = 0;
+ cc->bounds.top = 0;
+ cc->bounds.width = dev->width;
+ cc->bounds.height = dev->height;
+ cc->defrect = cc->bounds;
+ cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */
+ cc->pixelaspect.denominator = 59;
+ return 0;
+ }
+ case VIDIOC_STREAMON:
+ {
+ int *type = arg;
- if (unlikely(res_get(fh) < 0))
- return POLLERR;
+ if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE
+ || dev->io != IO_MMAP)
+ return -EINVAL;
- mutex_lock(&dev->lock);
+ if (list_empty(&dev->inqueue))
+ return -EINVAL;
- if (dev->state & DEV_DISCONNECTED) {
- em28xx_videodbg("device not present\n");
- } else if (dev->state & DEV_MISCONFIGURED) {
- em28xx_videodbg("device is misconfigured; close and open it again\n");
- } else {
- if (dev->io == IO_NONE) {
- if (!em28xx_request_buffers
- (dev, EM28XX_NUM_READ_FRAMES)) {
- em28xx_warn
- ("poll() failed, not enough memory\n");
- } else {
- dev->io = IO_READ;
- dev->stream = STREAM_ON;
- }
- }
+ dev->stream = STREAM_ON; /* FIXME: Start video capture here? */
- if (dev->io == IO_READ) {
- em28xx_queue_unusedframes(dev);
- poll_wait(filp, &dev->wait_frame, wait);
+ em28xx_videodbg("VIDIOC_STREAMON: starting stream\n");
- if (!list_empty(&dev->outqueue))
- mask |= POLLIN | POLLRDNORM;
+ return 0;
+ }
+ case VIDIOC_STREAMOFF:
+ {
+ int *type = arg;
+ int ret;
- mutex_unlock(&dev->lock);
+ if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE
+ || dev->io != IO_MMAP)
+ return -EINVAL;
- return mask;
+ if (dev->stream == STREAM_ON) {
+ em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream\n");
+ if ((ret = em28xx_stream_interrupt(dev)))
+ return ret;
}
- }
+ em28xx_empty_framequeues(dev);
- mutex_unlock(&dev->lock);
- return POLLERR;
+ return 0;
+ }
+ default:
+ return v4l_compat_translate_ioctl(inode, filp, cmd, arg,
+ driver_ioctl);
+ }
+ return 0;
}
/*
- * em28xx_v4l2_mmap()
+ * em28xx_v4l2_do_ioctl()
+ * This function is _not_ called directly, but from
+ * em28xx_v4l2_ioctl. Userspace
+ * copying is done already, arg is a kernel pointer.
*/
-static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
+static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, void *arg)
{
- struct em28xx_fh *fh = filp->private_data;
- struct em28xx *dev = fh->dev;
- unsigned long size = vma->vm_end - vma->vm_start;
- unsigned long start = vma->vm_start;
- void *pos;
- u32 i;
-
- if (unlikely(res_get(fh) < 0))
- return -EBUSY;
-
- mutex_lock(&dev->lock);
+ struct em28xx *dev = filp->private_data;
- if (dev->state & DEV_DISCONNECTED) {
- em28xx_videodbg("mmap: device not present\n");
- mutex_unlock(&dev->lock);
+ if (!dev)
return -ENODEV;
- }
- if (dev->state & DEV_MISCONFIGURED) {
- em28xx_videodbg ("mmap: Device is misconfigured; close and "
- "open it again\n");
- mutex_unlock(&dev->lock);
- return -EIO;
+ if (video_debug > 1)
+ v4l_print_ioctl(dev->name,cmd);
+
+ switch (cmd) {
+
+ /* --- capabilities ------------------------------------------ */
+ case VIDIOC_QUERYCAP:
+ {
+ struct v4l2_capability *cap = arg;
+
+ memset(cap, 0, sizeof(*cap));
+ strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
+ strlcpy(cap->card, em28xx_boards[dev->model].name,
+ sizeof(cap->card));
+ strlcpy(cap->bus_info, dev->udev->dev.bus_id,
+ sizeof(cap->bus_info));
+ cap->version = EM28XX_VERSION_CODE;
+ cap->capabilities =
+ V4L2_CAP_SLICED_VBI_CAPTURE |
+ V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_AUDIO |
+ V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+ if (dev->has_tuner)
+ cap->capabilities |= V4L2_CAP_TUNER;
+ return 0;
}
+ /* --- capture ioctls ---------------------------------------- */
+ case VIDIOC_ENUM_FMT:
+ {
+ struct v4l2_fmtdesc *fmtd = arg;
- if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE)) {
- mutex_unlock(&dev->lock);
- return -EINVAL;
+ if (fmtd->index != 0)
+ return -EINVAL;
+ memset(fmtd, 0, sizeof(*fmtd));
+ fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ strcpy(fmtd->description, "Packed YUY2");
+ fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
+ memset(fmtd->reserved, 0, sizeof(fmtd->reserved));
+ return 0;
}
+ case VIDIOC_G_FMT:
+ return em28xx_get_fmt(dev, (struct v4l2_format *) arg);
- if (size > PAGE_ALIGN(dev->frame[0].buf.length))
- size = PAGE_ALIGN(dev->frame[0].buf.length);
+ case VIDIOC_TRY_FMT:
+ case VIDIOC_S_FMT:
+ return em28xx_set_fmt(dev, cmd, (struct v4l2_format *)arg);
- for (i = 0; i < dev->num_frames; i++) {
- if ((dev->frame[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
- break;
- }
- if (i == dev->num_frames) {
- em28xx_videodbg("mmap: user supplied mapping address is out of range\n");
- mutex_unlock(&dev->lock);
- return -EINVAL;
- }
+ case VIDIOC_REQBUFS:
+ {
+ struct v4l2_requestbuffers *rb = arg;
+ u32 i;
+ int ret;
- /* VM_IO is eventually going to replace PageReserved altogether */
- vma->vm_flags |= VM_IO;
- vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
+ if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ rb->memory != V4L2_MEMORY_MMAP)
+ return -EINVAL;
- pos = dev->frame[i].bufmem;
- while (size > 0) { /* size is page-aligned */
- if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
- em28xx_videodbg("mmap: vm_insert_page failed\n");
- mutex_unlock(&dev->lock);
- return -EAGAIN;
+ if (dev->io == IO_READ) {
+ em28xx_videodbg ("method is set to read;"
+ " close and open the device again to"
+ " choose the mmap I/O method\n");
+ return -EINVAL;
}
- start += PAGE_SIZE;
- pos += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
- vma->vm_ops = &em28xx_vm_ops;
- vma->vm_private_data = &dev->frame[i];
+ for (i = 0; i < dev->num_frames; i++)
+ if (dev->frame[i].vma_use_count) {
+ em28xx_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped\n");
+ return -EINVAL;
+ }
- em28xx_vm_open(vma);
- mutex_unlock(&dev->lock);
- return 0;
-}
+ if (dev->stream == STREAM_ON) {
+ em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n");
+ if ((ret = em28xx_stream_interrupt(dev)))
+ return ret;
+ }
-static const struct file_operations em28xx_v4l_fops = {
- .owner = THIS_MODULE,
- .open = em28xx_v4l2_open,
- .release = em28xx_v4l2_close,
- .read = em28xx_v4l2_read,
- .poll = em28xx_v4l2_poll,
- .mmap = em28xx_v4l2_mmap,
- .ioctl = video_ioctl2,
- .llseek = no_llseek,
- .compat_ioctl = v4l_compat_ioctl32,
-};
+ em28xx_empty_framequeues(dev);
-static const struct file_operations radio_fops = {
- .owner = THIS_MODULE,
- .open = em28xx_v4l2_open,
- .release = em28xx_v4l2_close,
- .ioctl = video_ioctl2,
- .compat_ioctl = v4l_compat_ioctl32,
- .llseek = no_llseek,
-};
+ em28xx_release_buffers(dev);
+ if (rb->count)
+ rb->count =
+ em28xx_request_buffers(dev, rb->count);
-static const struct video_device em28xx_video_template = {
- .fops = &em28xx_v4l_fops,
- .release = video_device_release,
-
- .minor = -1,
- .vidioc_querycap = vidioc_querycap,
- .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap,
- .vidioc_g_fmt_cap = vidioc_g_fmt_cap,
- .vidioc_try_fmt_cap = vidioc_try_fmt_cap,
- .vidioc_s_fmt_cap = vidioc_s_fmt_cap,
- .vidioc_g_audio = vidioc_g_audio,
- .vidioc_s_audio = vidioc_s_audio,
- .vidioc_cropcap = vidioc_cropcap,
-
- .vidioc_g_fmt_vbi_capture = vidioc_g_fmt_vbi_capture,
- .vidioc_try_fmt_vbi_capture = vidioc_try_set_vbi_capture,
- .vidioc_s_fmt_vbi_capture = vidioc_try_set_vbi_capture,
-
- .vidioc_reqbufs = vidioc_reqbufs,
- .vidioc_querybuf = vidioc_querybuf,
- .vidioc_qbuf = vidioc_qbuf,
- .vidioc_dqbuf = vidioc_dqbuf,
- .vidioc_s_std = vidioc_s_std,
- .vidioc_enum_input = vidioc_enum_input,
- .vidioc_g_input = vidioc_g_input,
- .vidioc_s_input = vidioc_s_input,
- .vidioc_queryctrl = vidioc_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
- .vidioc_streamon = vidioc_streamon,
- .vidioc_streamoff = vidioc_streamoff,
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_tuner = vidioc_s_tuner,
- .vidioc_g_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
-
- .tvnorms = V4L2_STD_ALL,
- .current_norm = V4L2_STD_PAL,
-};
+ dev->frame_current = NULL;
-static struct video_device em28xx_radio_template = {
- .name = "em28xx-radio",
- .type = VID_TYPE_TUNER,
- .fops = &radio_fops,
- .minor = -1,
- .vidioc_querycap = radio_querycap,
- .vidioc_g_tuner = radio_g_tuner,
- .vidioc_enum_input = radio_enum_input,
- .vidioc_g_audio = radio_g_audio,
- .vidioc_s_tuner = radio_s_tuner,
- .vidioc_s_audio = radio_s_audio,
- .vidioc_s_input = radio_s_input,
- .vidioc_queryctrl = radio_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
- .vidioc_g_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
-};
+ em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i\n",
+ rb->count);
+ dev->io = rb->count ? IO_MMAP : IO_NONE;
+ return 0;
+ }
+ case VIDIOC_QUERYBUF:
+ {
+ struct v4l2_buffer *b = arg;
-/******************************** usb interface *****************************************/
+ if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ b->index >= dev->num_frames || dev->io != IO_MMAP)
+ return -EINVAL;
+ memcpy(b, &dev->frame[b->index].buf, sizeof(*b));
-static LIST_HEAD(em28xx_extension_devlist);
-static DEFINE_MUTEX(em28xx_extension_devlist_lock);
+ if (dev->frame[b->index].vma_use_count) {
+ b->flags |= V4L2_BUF_FLAG_MAPPED;
+ }
+ if (dev->frame[b->index].state == F_DONE)
+ b->flags |= V4L2_BUF_FLAG_DONE;
+ else if (dev->frame[b->index].state != F_UNUSED)
+ b->flags |= V4L2_BUF_FLAG_QUEUED;
+ return 0;
+ }
+ case VIDIOC_QBUF:
+ {
+ struct v4l2_buffer *b = arg;
+ unsigned long lock_flags;
-int em28xx_register_extension(struct em28xx_ops *ops)
-{
- struct em28xx *h, *dev = NULL;
+ if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ b->index >= dev->num_frames || dev->io != IO_MMAP) {
+ return -EINVAL;
+ }
+
+ if (dev->frame[b->index].state != F_UNUSED) {
+ return -EAGAIN;
+ }
+ dev->frame[b->index].state = F_QUEUED;
- list_for_each_entry(h, &em28xx_devlist, devlist)
- dev = h;
+ /* add frame to fifo */
+ spin_lock_irqsave(&dev->queue_lock, lock_flags);
+ list_add_tail(&dev->frame[b->index].frame,
+ &dev->inqueue);
+ spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
- mutex_lock(&em28xx_extension_devlist_lock);
- list_add_tail(&ops->next, &em28xx_extension_devlist);
- if (dev)
- ops->init(dev);
+ return 0;
+ }
+ case VIDIOC_DQBUF:
+ {
+ struct v4l2_buffer *b = arg;
+ struct em28xx_frame_t *f;
+ unsigned long lock_flags;
+ int ret = 0;
- printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
- mutex_unlock(&em28xx_extension_devlist_lock);
+ if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
+ || dev->io != IO_MMAP)
+ return -EINVAL;
- return 0;
-}
-EXPORT_SYMBOL(em28xx_register_extension);
+ if (list_empty(&dev->outqueue)) {
+ if (dev->stream == STREAM_OFF)
+ return -EINVAL;
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ ret = wait_event_interruptible
+ (dev->wait_frame,
+ (!list_empty(&dev->outqueue)) ||
+ (dev->state & DEV_DISCONNECTED));
+ if (ret)
+ return ret;
+ if (dev->state & DEV_DISCONNECTED)
+ return -ENODEV;
+ }
-void em28xx_unregister_extension(struct em28xx_ops *ops)
-{
- struct em28xx *h, *dev = NULL;
+ spin_lock_irqsave(&dev->queue_lock, lock_flags);
+ f = list_entry(dev->outqueue.next,
+ struct em28xx_frame_t, frame);
+ list_del(dev->outqueue.next);
+ spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
- list_for_each_entry(h, &em28xx_devlist, devlist)
- dev = h;
+ f->state = F_UNUSED;
+ memcpy(b, &f->buf, sizeof(*b));
- if (dev)
- ops->fini(dev);
+ if (f->vma_use_count)
+ b->flags |= V4L2_BUF_FLAG_MAPPED;
- mutex_lock(&em28xx_extension_devlist_lock);
- printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
- list_del(&ops->next);
- mutex_unlock(&em28xx_extension_devlist_lock);
+ return 0;
+ }
+ default:
+ return em28xx_do_ioctl(inode, filp, dev, cmd, arg,
+ em28xx_video_do_ioctl);
+ }
+ return 0;
}
-EXPORT_SYMBOL(em28xx_unregister_extension);
-struct video_device *em28xx_vdev_init(struct em28xx *dev,
- const struct video_device *template,
- const int type,
- const char *type_name)
+/*
+ * em28xx_v4l2_ioctl()
+ * handle v4l2 ioctl the main action happens in em28xx_v4l2_do_ioctl()
+ */
+static int em28xx_v4l2_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- struct video_device *vfd;
+ int ret = 0;
+ struct em28xx *dev = filp->private_data;
+
+ if (mutex_lock_interruptible(&dev->fileop_lock))
+ return -ERESTARTSYS;
+
+ if (dev->state & DEV_DISCONNECTED) {
+ em28xx_errdev("v4l2 ioctl: device not present\n");
+ mutex_unlock(&dev->fileop_lock);
+ return -ENODEV;
+ }
+
+ if (dev->state & DEV_MISCONFIGURED) {
+ em28xx_errdev
+ ("v4l2 ioctl: device is misconfigured; close and open it again\n");
+ mutex_unlock(&dev->fileop_lock);
+ return -EIO;
+ }
- vfd = video_device_alloc();
- if (NULL == vfd)
- return NULL;
- *vfd = *template;
- vfd->minor = -1;
- vfd->dev = &dev->udev->dev;
- vfd->release = video_device_release;
- vfd->type = type;
+ ret = video_usercopy(inode, filp, cmd, arg, em28xx_video_do_ioctl);
- snprintf(vfd->name, sizeof(vfd->name), "%s %s",
- dev->name, type_name);
+ mutex_unlock(&dev->fileop_lock);
- return vfd;
+ return ret;
}
+static const struct file_operations em28xx_v4l_fops = {
+ .owner = THIS_MODULE,
+ .open = em28xx_v4l2_open,
+ .release = em28xx_v4l2_close,
+ .ioctl = em28xx_v4l2_ioctl,
+ .read = em28xx_v4l2_read,
+ .poll = em28xx_v4l2_poll,
+ .mmap = em28xx_v4l2_mmap,
+ .llseek = no_llseek,
+ .compat_ioctl = v4l_compat_ioctl32,
+
+};
+
+/******************************** usb interface *****************************************/
/*
* em28xx_init_dev()
* allocates and inits the device structs, registers i2c bus and v4l device
*/
static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
- int minor)
+ int minor, int model)
{
- struct em28xx_ops *ops = NULL;
struct em28xx *dev = *devhandle;
int retval = -ENOMEM;
- int errCode;
+ int errCode, i;
unsigned int maxh, maxw;
dev->udev = udev;
+ dev->model = model;
mutex_init(&dev->lock);
- spin_lock_init(&dev->queue_lock);
init_waitqueue_head(&dev->open);
- init_waitqueue_head(&dev->wait_frame);
- init_waitqueue_head(&dev->wait_stream);
dev->em28xx_write_regs = em28xx_write_regs;
dev->em28xx_read_reg = em28xx_read_reg;
dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len;
dev->em28xx_write_regs_req = em28xx_write_regs_req;
dev->em28xx_read_reg_req = em28xx_read_reg_req;
- dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
-
- errCode = em28xx_read_reg(dev, CHIPID_REG);
- if (errCode >= 0)
- em28xx_info("em28xx chip ID = %d\n", errCode);
-
- em28xx_pre_card_setup(dev);
-
- errCode = em28xx_config(dev);
- if (errCode) {
- em28xx_errdev("error configuring device\n");
- em28xx_devused &= ~(1<devno);
- kfree(dev);
- return -ENOMEM;
- }
-
- /* register i2c bus */
- em28xx_i2c_register(dev);
+ dev->is_em2800 = em28xx_boards[model].is_em2800;
+ dev->has_tuner = em28xx_boards[model].has_tuner;
+ dev->has_msp34xx = em28xx_boards[model].has_msp34xx;
+ dev->tda9887_conf = em28xx_boards[model].tda9887_conf;
+ dev->decoder = em28xx_boards[model].decoder;
+
+ if (tuner >= 0)
+ dev->tuner_type = tuner;
+ else
+ dev->tuner_type = em28xx_boards[model].tuner_type;
- /* Do board specific init and eeprom reading */
- em28xx_card_setup(dev);
+ dev->video_inputs = em28xx_boards[model].vchannels;
- /* Configure audio */
- em28xx_audio_analog_set(dev);
+ for (i = 0; i < TVNORMS; i++)
+ if (em28xx_boards[model].norm == tvnorms[i].mode)
+ break;
+ if (i == TVNORMS)
+ i = 0;
- /* configure the device */
- em28xx_config_i2c(dev);
+ dev->tvnorm = &tvnorms[i]; /* set default norm */
- /* set default norm */
- dev->norm = em28xx_video_template.current_norm;
+ em28xx_videodbg("tvnorm=%s\n", dev->tvnorm->name);
maxw = norm_maxw(dev);
maxh = norm_maxh(dev);
@@ -1890,110 +1555,138 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
dev->vscale = 0;
dev->ctl_input = 2;
+ /* setup video picture settings for saa7113h */
+ memset(&dev->vpic, 0, sizeof(dev->vpic));
+ dev->vpic.colour = 128 << 8;
+ dev->vpic.hue = 128 << 8;
+ dev->vpic.brightness = 128 << 8;
+ dev->vpic.contrast = 192 << 8;
+ dev->vpic.whiteness = 128 << 8; /* This one isn't used */
+ dev->vpic.depth = 16;
+ dev->vpic.palette = VIDEO_PALETTE_YUV422;
+
+ em28xx_pre_card_setup(dev);
+#ifdef CONFIG_MODULES
+ /* request some modules */
+ if (dev->decoder == EM28XX_SAA7113 || dev->decoder == EM28XX_SAA7114)
+ request_module("saa7115");
+ if (dev->decoder == EM28XX_TVP5150)
+ request_module("tvp5150");
+ if (dev->has_tuner)
+ request_module("tuner");
+#endif
errCode = em28xx_config(dev);
+ if (errCode) {
+ em28xx_errdev("error configuring device\n");
+ em28xx_devused&=~(1<devno);
+ kfree(dev);
+ return -ENOMEM;
+ }
+
+ mutex_lock(&dev->lock);
+ /* register i2c bus */
+ em28xx_i2c_register(dev);
+
+ /* Do board specific init and eeprom reading */
+ em28xx_card_setup(dev);
+
+ /* configure the device */
+ em28xx_config_i2c(dev);
+
+ mutex_unlock(&dev->lock);
- list_add_tail(&dev->devlist, &em28xx_devlist);
+ errCode = em28xx_config(dev);
- /* allocate and fill video video_device struct */
- dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template,
- VID_TYPE_CAPTURE, "video");
+#ifdef CONFIG_MODULES
+ if (dev->has_msp34xx)
+ request_module("msp3400");
+#endif
+ /* allocate and fill v4l2 device struct */
+ dev->vdev = video_device_alloc();
if (NULL == dev->vdev) {
em28xx_errdev("cannot allocate video_device.\n");
- goto fail_unreg;
+ em28xx_devused&=~(1<