diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 22:09:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 22:09:32 -0400 |
commit | c634920abaf9c0a93266a57beff6fce9d3852cb2 (patch) | |
tree | 5ac85f54905a8cd3b12b262c66189084cbff54fc | |
parent | 6abd2c860e34add677de50e8b134f5af6f4b0893 (diff) | |
parent | a991f44b79fa49b281eb078eed4a76a42101012a (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (310 commits)
V4L/DVB (6316): Change list_for_each+list_entry to list_for_each_entry
V4L/DVB (6315): pvrusb2: Change list_for_each+list_entry to list_for_each_entry
V4L/DVB (6314): saa7134: Replace list_for_each+list_entry with list_for_each_entry
V4L/DVB (6313): ivtv: Replace list_for_each+list_entry with list_for_each_entry
V4L/DVB (6312): cx88: Replace list_for_each+list_entry with list_for_each_entry
V4L/DVB (6311): dvb: Replace list_for_each+list_entry with list_for_each_entry
V4L/DVB (6308): V4L: zc0301, remove bad usage of ERESTARTSYS
V4L/DVB (6307): V4L: w9968cf, remove bad usage of ERESTARTSYS
V4L/DVB (6306): Few clenups for saa7134 resume code
V4L/DVB (6305): V4L: videobuf-core.c avoid NULL dereferences in videobuf-core
V4L/DVB (6301): pvrusb: Update DEBUGIFC sysfs to kernel 2.6.13+
V4L/DVB (6300): CodingStyle cleanup
V4L/DVB (6299): dvb: Add dependencies for VIDEOBUF_DVB
V4L/DVB (6297): cx23885: remove wrong Kconfig selection of VIDEOBUF
V4L/DVB (6296): dib0700: add support for AverMedia DVB-T Express card
V4L/DVB (6295): saa7134: add autodetection for KWorld ATSC-115
V4L/DVB (6293): V4L: convert struct class_device to struct device
V4L/DVB (6292): videobuf_core init always require callback implementation
V4L/DVB (6291): Fix: avoid oops on some SMP machines
V4L/DVB (6290): remove videobuf_set_pci_ops
...
276 files changed, 18481 insertions, 5788 deletions
diff --git a/Documentation/dvb/faq.txt b/Documentation/dvb/faq.txt index dbcedf5833ee..2511a335abd6 100644 --- a/Documentation/dvb/faq.txt +++ b/Documentation/dvb/faq.txt | |||
@@ -150,7 +150,7 @@ Some very frequently asked questions about linuxtv-dvb | |||
150 | - saa7146_vv: SAA7146 video and vbi functions. These are only needed | 150 | - saa7146_vv: SAA7146 video and vbi functions. These are only needed |
151 | for full-featured cards. | 151 | for full-featured cards. |
152 | 152 | ||
153 | - video-buf: capture helper module for the saa7146_vv driver. This | 153 | - videobuf-dma-sg: capture helper module for the saa7146_vv driver. This |
154 | one is responsible to handle capture buffers. | 154 | one is responsible to handle capture buffers. |
155 | 155 | ||
156 | - dvb-ttpci: The main driver for AV7110 based, full-featured | 156 | - dvb-ttpci: The main driver for AV7110 based, full-featured |
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 177159c5f4c4..d97cf7cc6088 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv | |||
@@ -147,3 +147,4 @@ | |||
147 | 146 -> SSAI Ultrasound Video Interface [414a:5353] | 147 | 146 -> SSAI Ultrasound Video Interface [414a:5353] |
148 | 147 -> VoodooTV 200 (USA) [121a:3000] | 148 | 147 -> VoodooTV 200 (USA) [121a:3000] |
149 | 148 -> DViCO FusionHDTV 2 [dbc0:d200] | 149 | 148 -> DViCO FusionHDTV 2 [dbc0:d200] |
150 | 149 -> Typhoon TV-Tuner PCI (50684) | ||
diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 new file mode 100644 index 000000000000..00cb646a4bde --- /dev/null +++ b/Documentation/video4linux/CARDLIST.cx23885 | |||
@@ -0,0 +1,5 @@ | |||
1 | 0 -> UNKNOWN/GENERIC [0070:3400] | ||
2 | 1 -> Hauppauge WinTV-HVR1800lp [0070:7600] | ||
3 | 2 -> Hauppauge WinTV-HVR1800 [0070:7800,0070:7801] | ||
4 | 3 -> Hauppauge WinTV-HVR1250 [0070:7911] | ||
5 | 4 -> DViCO FusionHDTV5 Express [18ac:d500] | ||
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 3f8aeab50a10..a14545300e4c 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 | |||
@@ -88,11 +88,11 @@ | |||
88 | 87 -> ADS Instant TV Duo Cardbus PTV331 [0331:1421] | 88 | 87 -> ADS Instant TV Duo Cardbus PTV331 [0331:1421] |
89 | 88 -> Tevion/KWorld DVB-T 220RF [17de:7201] | 89 | 88 -> Tevion/KWorld DVB-T 220RF [17de:7201] |
90 | 89 -> ELSA EX-VISION 700TV [1048:226c] | 90 | 89 -> ELSA EX-VISION 700TV [1048:226c] |
91 | 90 -> Kworld ATSC110 [17de:7350] | 91 | 90 -> Kworld ATSC110/115 [17de:7350,17de:7352] |
92 | 91 -> AVerMedia A169 B [1461:7360] | 92 | 91 -> AVerMedia A169 B [1461:7360] |
93 | 92 -> AVerMedia A169 B1 [1461:6360] | 93 | 92 -> AVerMedia A169 B1 [1461:6360] |
94 | 93 -> Medion 7134 Bridge #2 [16be:0005] | 94 | 93 -> Medion 7134 Bridge #2 [16be:0005] |
95 | 94 -> LifeView FlyDVB-T Hybrid Cardbus [5168:3306,5168:3502] | 95 | 94 -> LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB [5168:3306,5168:3502,4e42:3502] |
96 | 95 -> LifeView FlyVIDEO3000 (NTSC) [5169:0138] | 96 | 95 -> LifeView FlyVIDEO3000 (NTSC) [5169:0138] |
97 | 96 -> Medion Md8800 Quadro [16be:0007,16be:0008] | 97 | 96 -> Medion Md8800 Quadro [16be:0007,16be:0008] |
98 | 97 -> LifeView FlyDVB-S /Acorp TV134DS [5168:0300,4e42:0300] | 98 | 97 -> LifeView FlyDVB-S /Acorp TV134DS [5168:0300,4e42:0300] |
@@ -115,3 +115,4 @@ | |||
115 | 114 -> KWorld DVB-T 210 [17de:7250] | 115 | 114 -> KWorld DVB-T 210 [17de:7250] |
116 | 115 -> Sabrent PCMCIA TV-PCB05 [0919:2003] | 116 | 115 -> Sabrent PCMCIA TV-PCB05 [0919:2003] |
117 | 116 -> 10MOONS TM300 TV Card [1131:2304] | 117 | 116 -> 10MOONS TM300 TV Card [1131:2304] |
118 | 117 -> Avermedia Super 007 [1461:f01d] | ||
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index d9d033e07e19..dd9bd4310c84 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig | |||
@@ -69,13 +69,79 @@ source "drivers/media/common/Kconfig" | |||
69 | config VIDEO_TUNER | 69 | config VIDEO_TUNER |
70 | tristate | 70 | tristate |
71 | depends on I2C | 71 | depends on I2C |
72 | select TUNER_MT20XX if !VIDEO_TUNER_CUSTOMIZE | ||
73 | select TUNER_TDA8290 if !VIDEO_TUNER_CUSTOMIZE | ||
74 | select TUNER_TEA5761 if !VIDEO_TUNER_CUSTOMIZE | ||
75 | select TUNER_TEA5767 if !VIDEO_TUNER_CUSTOMIZE | ||
76 | select TUNER_SIMPLE if !VIDEO_TUNER_CUSTOMIZE | ||
77 | |||
78 | menuconfig VIDEO_TUNER_CUSTOMIZE | ||
79 | bool "Customize analog tuner modules to build" | ||
80 | depends on VIDEO_TUNER | ||
81 | help | ||
82 | This allows the user to deselect tuner drivers unnecessary | ||
83 | for their hardware from the build. Use this option with care | ||
84 | as deselecting tuner drivers which are in fact necessary will | ||
85 | result in V4L devices which cannot be tuned due to lack of | ||
86 | driver support | ||
87 | |||
88 | If unsure say N. | ||
89 | |||
90 | if VIDEO_TUNER_CUSTOMIZE | ||
91 | |||
92 | config TUNER_MT20XX | ||
93 | tristate "Microtune 2032 / 2050 tuners" | ||
94 | depends on I2C | ||
95 | default m if VIDEO_TUNER_CUSTOMIZE | ||
96 | help | ||
97 | Say Y here to include support for the MT2032 / MT2050 tuner. | ||
98 | |||
99 | config TUNER_TDA8290 | ||
100 | tristate "TDA 8290+8275(a) tuner combo" | ||
101 | depends on I2C | ||
102 | default m if VIDEO_TUNER_CUSTOMIZE | ||
103 | help | ||
104 | Say Y here to include support for Philips TDA8290+8275(a) tuner. | ||
105 | |||
106 | config TUNER_TEA5761 | ||
107 | tristate "TEA 5761 radio tuner (EXPERIMENTAL)" | ||
108 | depends on I2C && EXPERIMENTAL | ||
109 | default m if VIDEO_TUNER_CUSTOMIZE | ||
110 | help | ||
111 | Say Y here to include support for the Philips TEA5761 radio tuner. | ||
112 | |||
113 | config TUNER_TEA5767 | ||
114 | tristate "TEA 5767 radio tuner" | ||
115 | depends on I2C | ||
116 | default m if VIDEO_TUNER_CUSTOMIZE | ||
117 | help | ||
118 | Say Y here to include support for the Philips TEA5767 radio tuner. | ||
119 | |||
120 | config TUNER_SIMPLE | ||
121 | tristate "Simple tuner support" | ||
122 | depends on I2C | ||
123 | default m if VIDEO_TUNER_CUSTOMIZE | ||
124 | help | ||
125 | Say Y here to include support for various simple tuners. | ||
72 | 126 | ||
73 | config VIDEO_BUF | 127 | endif # VIDEO_TUNER_CUSTOMIZE |
128 | |||
129 | config VIDEOBUF_GEN | ||
130 | tristate | ||
131 | |||
132 | config VIDEOBUF_DMA_SG | ||
74 | depends on PCI | 133 | depends on PCI |
134 | select VIDEOBUF_GEN | ||
135 | tristate | ||
136 | |||
137 | config VIDEOBUF_VMALLOC | ||
138 | select VIDEOBUF_GEN | ||
75 | tristate | 139 | tristate |
76 | 140 | ||
77 | config VIDEO_BUF_DVB | 141 | config VIDEOBUF_DVB |
78 | tristate | 142 | tristate |
143 | select VIDEOBUF_GEN | ||
144 | select VIDEOBUF_DMA_SG | ||
79 | 145 | ||
80 | config VIDEO_BTCX | 146 | config VIDEO_BTCX |
81 | tristate | 147 | tristate |
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig index 5c63c8e24ee7..c5092ef1082f 100644 --- a/drivers/media/common/Kconfig +++ b/drivers/media/common/Kconfig | |||
@@ -5,5 +5,5 @@ config VIDEO_SAA7146 | |||
5 | config VIDEO_SAA7146_VV | 5 | config VIDEO_SAA7146_VV |
6 | tristate | 6 | tristate |
7 | depends on VIDEO_DEV | 7 | depends on VIDEO_DEV |
8 | select VIDEO_BUF | 8 | select VIDEOBUF_DMA_SG |
9 | select VIDEO_SAA7146 | 9 | select VIDEO_SAA7146 |
diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c index a3292e955aaa..e7c3ab951a44 100644 --- a/drivers/media/common/ir-functions.c +++ b/drivers/media/common/ir-functions.c | |||
@@ -21,7 +21,6 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/string.h> | 24 | #include <linux/string.h> |
26 | #include <linux/jiffies.h> | 25 | #include <linux/jiffies.h> |
27 | #include <media/ir-common.h> | 26 | #include <media/ir-common.h> |
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index cbd1184b5219..aefcf28da1ca 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c | |||
@@ -20,7 +20,6 @@ | |||
20 | 20 | ||
21 | */ | 21 | */ |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/moduleparam.h> | ||
24 | 23 | ||
25 | #include <linux/input.h> | 24 | #include <linux/input.h> |
26 | #include <media/ir-common.h> | 25 | #include <media/ir-common.h> |
@@ -1783,3 +1782,64 @@ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { | |||
1783 | }; | 1782 | }; |
1784 | 1783 | ||
1785 | EXPORT_SYMBOL_GPL(ir_codes_tt_1500); | 1784 | EXPORT_SYMBOL_GPL(ir_codes_tt_1500); |
1785 | |||
1786 | /* DViCO FUSION HDTV MCE remote */ | ||
1787 | IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = { | ||
1788 | |||
1789 | [ 0x0b ] = KEY_1, | ||
1790 | [ 0x17 ] = KEY_2, | ||
1791 | [ 0x1b ] = KEY_3, | ||
1792 | [ 0x07 ] = KEY_4, | ||
1793 | [ 0x50 ] = KEY_5, | ||
1794 | [ 0x54 ] = KEY_6, | ||
1795 | [ 0x48 ] = KEY_7, | ||
1796 | [ 0x4c ] = KEY_8, | ||
1797 | [ 0x58 ] = KEY_9, | ||
1798 | [ 0x03 ] = KEY_0, | ||
1799 | |||
1800 | [ 0x5e ] = KEY_OK, | ||
1801 | [ 0x51 ] = KEY_UP, | ||
1802 | [ 0x53 ] = KEY_DOWN, | ||
1803 | [ 0x5b ] = KEY_LEFT, | ||
1804 | [ 0x5f ] = KEY_RIGHT, | ||
1805 | |||
1806 | [ 0x02 ] = KEY_TV, /* Labeled DTV on remote */ | ||
1807 | [ 0x0e ] = KEY_MP3, | ||
1808 | [ 0x1a ] = KEY_DVD, | ||
1809 | [ 0x1e ] = KEY_FAVORITES, /* Labeled CPF on remote */ | ||
1810 | [ 0x16 ] = KEY_SETUP, | ||
1811 | [ 0x46 ] = KEY_POWER2, /* TV On/Off button on remote */ | ||
1812 | [ 0x0a ] = KEY_EPG, /* Labeled Guide on remote */ | ||
1813 | |||
1814 | [ 0x49 ] = KEY_BACK, | ||
1815 | [ 0x59 ] = KEY_INFO, /* Labeled MORE on remote */ | ||
1816 | [ 0x4d ] = KEY_MENU, /* Labeled DVDMENU on remote */ | ||
1817 | [ 0x55 ] = KEY_CYCLEWINDOWS, /* Labeled ALT-TAB on remote */ | ||
1818 | |||
1819 | [ 0x0f ] = KEY_PREVIOUSSONG, /* Labeled |<< REPLAY on remote */ | ||
1820 | [ 0x12 ] = KEY_NEXTSONG, /* Labeled >>| SKIP on remote */ | ||
1821 | [ 0x42 ] = KEY_ENTER, /* Labeled START with a green | ||
1822 | * MS windows logo on remote */ | ||
1823 | |||
1824 | [ 0x15 ] = KEY_VOLUMEUP, | ||
1825 | [ 0x05 ] = KEY_VOLUMEDOWN, | ||
1826 | [ 0x11 ] = KEY_CHANNELUP, | ||
1827 | [ 0x09 ] = KEY_CHANNELDOWN, | ||
1828 | |||
1829 | [ 0x52 ] = KEY_CAMERA, | ||
1830 | [ 0x5a ] = KEY_TUNER, | ||
1831 | [ 0x19 ] = KEY_OPEN, | ||
1832 | |||
1833 | [ 0x13 ] = KEY_MODE, /* 4:3 16:9 select */ | ||
1834 | [ 0x1f ] = KEY_ZOOM, | ||
1835 | |||
1836 | [ 0x43 ] = KEY_REWIND, | ||
1837 | [ 0x47 ] = KEY_PLAYPAUSE, | ||
1838 | [ 0x4f ] = KEY_FASTFORWARD, | ||
1839 | [ 0x57 ] = KEY_MUTE, | ||
1840 | [ 0x0d ] = KEY_STOP, | ||
1841 | [ 0x01 ] = KEY_RECORD, | ||
1842 | [ 0x4e ] = KEY_POWER, | ||
1843 | }; | ||
1844 | |||
1845 | EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce); | ||
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index ba6701e97671..365a22118a09 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c | |||
@@ -100,7 +100,7 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) | |||
100 | * general helper functions | 100 | * general helper functions |
101 | ****************************************************************************/ | 101 | ****************************************************************************/ |
102 | 102 | ||
103 | /* this is videobuf_vmalloc_to_sg() from video-buf.c | 103 | /* this is videobuf_vmalloc_to_sg() from videobuf-dma-sg.c |
104 | make sure virt has been allocated with vmalloc_32(), otherwise the BUG() | 104 | make sure virt has been allocated with vmalloc_32(), otherwise the BUG() |
105 | may be triggered on highmem machines */ | 105 | may be triggered on highmem machines */ |
106 | static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) | 106 | static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) |
@@ -248,10 +248,11 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt | |||
248 | static irqreturn_t interrupt_hw(int irq, void *dev_id) | 248 | static irqreturn_t interrupt_hw(int irq, void *dev_id) |
249 | { | 249 | { |
250 | struct saa7146_dev *dev = dev_id; | 250 | struct saa7146_dev *dev = dev_id; |
251 | u32 isr = 0; | 251 | u32 isr; |
252 | u32 ack_isr; | ||
252 | 253 | ||
253 | /* read out the interrupt status register */ | 254 | /* read out the interrupt status register */ |
254 | isr = saa7146_read(dev, ISR); | 255 | ack_isr = isr = saa7146_read(dev, ISR); |
255 | 256 | ||
256 | /* is this our interrupt? */ | 257 | /* is this our interrupt? */ |
257 | if ( 0 == isr ) { | 258 | if ( 0 == isr ) { |
@@ -259,8 +260,6 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id) | |||
259 | return IRQ_NONE; | 260 | return IRQ_NONE; |
260 | } | 261 | } |
261 | 262 | ||
262 | saa7146_write(dev, ISR, isr); | ||
263 | |||
264 | if( 0 != (dev->ext)) { | 263 | if( 0 != (dev->ext)) { |
265 | if( 0 != (dev->ext->irq_mask & isr )) { | 264 | if( 0 != (dev->ext->irq_mask & isr )) { |
266 | if( 0 != dev->ext->irq_func ) { | 265 | if( 0 != dev->ext->irq_func ) { |
@@ -283,21 +282,16 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id) | |||
283 | isr &= ~MASK_28; | 282 | isr &= ~MASK_28; |
284 | } | 283 | } |
285 | if (0 != (isr & (MASK_16|MASK_17))) { | 284 | if (0 != (isr & (MASK_16|MASK_17))) { |
286 | u32 status = saa7146_read(dev, I2C_STATUS); | 285 | SAA7146_IER_DISABLE(dev, MASK_16|MASK_17); |
287 | if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) { | 286 | /* only wake up if we expect something */ |
288 | SAA7146_IER_DISABLE(dev, MASK_16|MASK_17); | 287 | if (0 != dev->i2c_op) { |
289 | /* only wake up if we expect something */ | 288 | dev->i2c_op = 0; |
290 | if( 0 != dev->i2c_op ) { | 289 | wake_up(&dev->i2c_wq); |
291 | u32 psr = (saa7146_read(dev, PSR) >> 16) & 0x2; | ||
292 | u32 ssr = (saa7146_read(dev, SSR) >> 17) & 0x1f; | ||
293 | DEB_I2C(("irq: i2c, status: 0x%08x, psr:0x%02x, ssr:0x%02x).\n",status,psr,ssr)); | ||
294 | dev->i2c_op = 0; | ||
295 | wake_up(&dev->i2c_wq); | ||
296 | } else { | ||
297 | DEB_I2C(("unexpected irq: i2c, status: 0x%08x, isr %#x\n",status, isr)); | ||
298 | } | ||
299 | } else { | 290 | } else { |
300 | DEB_I2C(("unhandled irq: i2c, status: 0x%08x, isr %#x\n",status, isr)); | 291 | u32 psr = saa7146_read(dev, PSR); |
292 | u32 ssr = saa7146_read(dev, SSR); | ||
293 | printk(KERN_WARNING "%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n", | ||
294 | dev->name, isr, psr, ssr); | ||
301 | } | 295 | } |
302 | isr &= ~(MASK_16|MASK_17); | 296 | isr &= ~(MASK_16|MASK_17); |
303 | } | 297 | } |
@@ -306,6 +300,7 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id) | |||
306 | ERR(("disabling interrupt source(s)!\n")); | 300 | ERR(("disabling interrupt source(s)!\n")); |
307 | SAA7146_IER_DISABLE(dev,isr); | 301 | SAA7146_IER_DISABLE(dev,isr); |
308 | } | 302 | } |
303 | saa7146_write(dev, ISR, ack_isr); | ||
309 | return IRQ_HANDLED; | 304 | return IRQ_HANDLED; |
310 | } | 305 | } |
311 | 306 | ||
@@ -548,7 +543,6 @@ EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done); | |||
548 | 543 | ||
549 | EXPORT_SYMBOL_GPL(saa7146_setgpio); | 544 | EXPORT_SYMBOL_GPL(saa7146_setgpio); |
550 | 545 | ||
551 | EXPORT_SYMBOL_GPL(saa7146_i2c_transfer); | ||
552 | EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare); | 546 | EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare); |
553 | 547 | ||
554 | EXPORT_SYMBOL_GPL(saa7146_debug); | 548 | EXPORT_SYMBOL_GPL(saa7146_debug); |
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index b4770aecc01d..67d1b1b1b254 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c | |||
@@ -53,13 +53,14 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits) | |||
53 | void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q, | 53 | void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q, |
54 | struct saa7146_buf *buf) | 54 | struct saa7146_buf *buf) |
55 | { | 55 | { |
56 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
56 | DEB_EE(("dev:%p, buf:%p\n",dev,buf)); | 57 | DEB_EE(("dev:%p, buf:%p\n",dev,buf)); |
57 | 58 | ||
58 | BUG_ON(in_interrupt()); | 59 | BUG_ON(in_interrupt()); |
59 | 60 | ||
60 | videobuf_waiton(&buf->vb,0,0); | 61 | videobuf_waiton(&buf->vb,0,0); |
61 | videobuf_dma_unmap(q, &buf->vb.dma); | 62 | videobuf_dma_unmap(q, dma); |
62 | videobuf_dma_free(&buf->vb.dma); | 63 | videobuf_dma_free(dma); |
63 | buf->vb.state = STATE_NEEDS_INIT; | 64 | buf->vb.state = STATE_NEEDS_INIT; |
64 | } | 65 | } |
65 | 66 | ||
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c index 8c85efc26527..7e7689afae62 100644 --- a/drivers/media/common/saa7146_i2c.c +++ b/drivers/media/common/saa7146_i2c.c | |||
@@ -202,7 +202,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d | |||
202 | /* a signal arrived */ | 202 | /* a signal arrived */ |
203 | return -ERESTARTSYS; | 203 | return -ERESTARTSYS; |
204 | 204 | ||
205 | printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n"); | 205 | printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n", |
206 | dev->name, __FUNCTION__); | ||
206 | return -EIO; | 207 | return -EIO; |
207 | } | 208 | } |
208 | status = saa7146_read(dev, I2C_STATUS); | 209 | status = saa7146_read(dev, I2C_STATUS); |
@@ -219,7 +220,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d | |||
219 | break; | 220 | break; |
220 | } | 221 | } |
221 | if (time_after(jiffies,timeout)) { | 222 | if (time_after(jiffies,timeout)) { |
222 | printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for MC2\n"); | 223 | printk(KERN_WARNING "%s %s: timed out waiting for MC2\n", |
224 | dev->name, __FUNCTION__); | ||
223 | return -EIO; | 225 | return -EIO; |
224 | } | 226 | } |
225 | } | 227 | } |
@@ -235,7 +237,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d | |||
235 | /* this is normal when probing the bus | 237 | /* this is normal when probing the bus |
236 | * (no answer from nonexisistant device...) | 238 | * (no answer from nonexisistant device...) |
237 | */ | 239 | */ |
238 | DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n")); | 240 | printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n", |
241 | dev->name, __FUNCTION__); | ||
239 | return -EIO; | 242 | return -EIO; |
240 | } | 243 | } |
241 | if (++trial < 50 && short_delay) | 244 | if (++trial < 50 && short_delay) |
@@ -246,8 +249,16 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d | |||
246 | } | 249 | } |
247 | 250 | ||
248 | /* give a detailed status report */ | 251 | /* give a detailed status report */ |
249 | if ( 0 != (status & SAA7146_I2C_ERR)) { | 252 | if ( 0 != (status & (SAA7146_I2C_SPERR | SAA7146_I2C_APERR | |
250 | 253 | SAA7146_I2C_DTERR | SAA7146_I2C_DRERR | | |
254 | SAA7146_I2C_AL | SAA7146_I2C_ERR | | ||
255 | SAA7146_I2C_BUSY)) ) { | ||
256 | |||
257 | if ( 0 == (status & SAA7146_I2C_ERR) || | ||
258 | 0 == (status & SAA7146_I2C_BUSY) ) { | ||
259 | /* it may take some time until ERR goes high - ignore */ | ||
260 | DEB_I2C(("unexpected i2c status %04x\n", status)); | ||
261 | } | ||
251 | if( 0 != (status & SAA7146_I2C_SPERR) ) { | 262 | if( 0 != (status & SAA7146_I2C_SPERR) ) { |
252 | DEB_I2C(("error due to invalid start/stop condition.\n")); | 263 | DEB_I2C(("error due to invalid start/stop condition.\n")); |
253 | } | 264 | } |
@@ -277,7 +288,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d | |||
277 | return 0; | 288 | return 0; |
278 | } | 289 | } |
279 | 290 | ||
280 | int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries) | 291 | static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries) |
281 | { | 292 | { |
282 | int i = 0, count = 0; | 293 | int i = 0, count = 0; |
283 | u32* buffer = dev->d_i2c.cpu_addr; | 294 | u32* buffer = dev->d_i2c.cpu_addr; |
diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c index 063608462ebe..6103484e4442 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146_vbi.c | |||
@@ -165,7 +165,7 @@ static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf | |||
165 | /* we don't wait here for the first field anymore. this is different from the video | 165 | /* we don't wait here for the first field anymore. this is different from the video |
166 | capture and might cause that the first buffer is only half filled (with only | 166 | capture and might cause that the first buffer is only half filled (with only |
167 | one field). but since this is some sort of streaming data, this is not that negative. | 167 | one field). but since this is some sort of streaming data, this is not that negative. |
168 | but by doing this, we can use the whole engine from video-buf.c... */ | 168 | but by doing this, we can use the whole engine from videobuf-dma-sg.c... */ |
169 | 169 | ||
170 | /* | 170 | /* |
171 | WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | e_wait); | 171 | WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | e_wait); |
@@ -239,6 +239,8 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e | |||
239 | saa7146_dma_free(dev,q,buf); | 239 | saa7146_dma_free(dev,q,buf); |
240 | 240 | ||
241 | if (STATE_NEEDS_INIT == buf->vb.state) { | 241 | if (STATE_NEEDS_INIT == buf->vb.state) { |
242 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
243 | |||
242 | buf->vb.width = llength; | 244 | buf->vb.width = llength; |
243 | buf->vb.height = lines; | 245 | buf->vb.height = lines; |
244 | buf->vb.size = size; | 246 | buf->vb.size = size; |
@@ -250,7 +252,8 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e | |||
250 | err = videobuf_iolock(q,&buf->vb, NULL); | 252 | err = videobuf_iolock(q,&buf->vb, NULL); |
251 | if (err) | 253 | if (err) |
252 | goto oops; | 254 | goto oops; |
253 | err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen); | 255 | err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], |
256 | dma->sglist, dma->sglen); | ||
254 | if (0 != err) | 257 | if (0 != err) |
255 | return err; | 258 | return err; |
256 | } | 259 | } |
@@ -404,7 +407,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) | |||
404 | fh->vbi_fmt.start[1] = 312; | 407 | fh->vbi_fmt.start[1] = 312; |
405 | fh->vbi_fmt.count[1] = 16; | 408 | fh->vbi_fmt.count[1] = 16; |
406 | 409 | ||
407 | videobuf_queue_init(&fh->vbi_q, &vbi_qops, | 410 | videobuf_queue_pci_init(&fh->vbi_q, &vbi_qops, |
408 | dev->pci, &dev->slock, | 411 | dev->pci, &dev->slock, |
409 | V4L2_BUF_TYPE_VBI_CAPTURE, | 412 | V4L2_BUF_TYPE_VBI_CAPTURE, |
410 | V4L2_FIELD_SEQ_TB, // FIXME: does this really work? | 413 | V4L2_FIELD_SEQ_TB, // FIXME: does this really work? |
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 664280c78ff2..f245a3b2ef47 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c | |||
@@ -594,8 +594,9 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) | |||
594 | static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf) | 594 | static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf) |
595 | { | 595 | { |
596 | struct pci_dev *pci = dev->pci; | 596 | struct pci_dev *pci = dev->pci; |
597 | struct scatterlist *list = buf->vb.dma.sglist; | 597 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); |
598 | int length = buf->vb.dma.sglen; | 598 | struct scatterlist *list = dma->sglist; |
599 | int length = dma->sglen; | ||
599 | struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); | 600 | struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); |
600 | 601 | ||
601 | DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length)); | 602 | DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length)); |
@@ -655,7 +656,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu | |||
655 | 656 | ||
656 | /* if we have a user buffer, the first page may not be | 657 | /* if we have a user buffer, the first page may not be |
657 | aligned to a page boundary. */ | 658 | aligned to a page boundary. */ |
658 | pt1->offset = buf->vb.dma.sglist->offset; | 659 | pt1->offset = list->offset; |
659 | pt2->offset = pt1->offset+o1; | 660 | pt2->offset = pt1->offset+o1; |
660 | pt3->offset = pt1->offset+o2; | 661 | pt3->offset = pt1->offset+o2; |
661 | 662 | ||
@@ -1211,6 +1212,8 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int | |||
1211 | mutex_unlock(&q->lock); | 1212 | mutex_unlock(&q->lock); |
1212 | return err; | 1213 | return err; |
1213 | } | 1214 | } |
1215 | |||
1216 | gbuffers = err; | ||
1214 | memset(mbuf,0,sizeof(*mbuf)); | 1217 | memset(mbuf,0,sizeof(*mbuf)); |
1215 | mbuf->frames = gbuffers; | 1218 | mbuf->frames = gbuffers; |
1216 | mbuf->size = gbuffers * gbufsize; | 1219 | mbuf->size = gbuffers * gbufsize; |
@@ -1411,7 +1414,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file) | |||
1411 | sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); | 1414 | sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); |
1412 | fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8; | 1415 | fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8; |
1413 | 1416 | ||
1414 | videobuf_queue_init(&fh->video_q, &video_qops, | 1417 | videobuf_queue_pci_init(&fh->video_q, &video_qops, |
1415 | dev->pci, &dev->slock, | 1418 | dev->pci, &dev->slock, |
1416 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 1419 | V4L2_BUF_TYPE_VIDEO_CAPTURE, |
1417 | V4L2_FIELD_INTERLACED, | 1420 | V4L2_FIELD_INTERLACED, |
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index df72b4b8ee10..eca602d9b3de 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c | |||
@@ -28,7 +28,6 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
33 | #include <linux/pci.h> | 32 | #include <linux/pci.h> |
34 | #include <asm/io.h> | 33 | #include <asm/io.h> |
diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h index f685bc129609..d593bc145628 100644 --- a/drivers/media/dvb/bt8xx/bt878.h +++ b/drivers/media/dvb/bt8xx/bt878.h | |||
@@ -149,11 +149,10 @@ void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin, | |||
149 | void bt878_stop(struct bt878 *bt); | 149 | void bt878_stop(struct bt878 *bt); |
150 | 150 | ||
151 | #if defined(__powerpc__) /* big-endian */ | 151 | #if defined(__powerpc__) /* big-endian */ |
152 | extern __inline__ void io_st_le32(volatile unsigned __iomem *addr, unsigned val) | 152 | static inline void io_st_le32(volatile unsigned __iomem *addr, unsigned val) |
153 | { | 153 | { |
154 | __asm__ __volatile__("stwbrx %1,0,%2":"=m"(*addr):"r"(val), | 154 | st_le32(addr, val); |
155 | "r"(addr)); | 155 | eieio(); |
156 | __asm__ __volatile__("eieio":::"memory"); | ||
157 | } | 156 | } |
158 | 157 | ||
159 | #define bmtwrite(dat,adr) io_st_le32((adr),(dat)) | 158 | #define bmtwrite(dat,adr) io_st_le32((adr),(dat)) |
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 67613eb6fa3d..dedd30a8356b 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c | |||
@@ -21,7 +21,6 @@ | |||
21 | 21 | ||
22 | #include <linux/bitops.h> | 22 | #include <linux/bitops.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/init.h> | 24 | #include <linux/init.h> |
26 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
27 | #include <linux/device.h> | 26 | #include <linux/device.h> |
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 28929b618e20..5a12b5679556 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c | |||
@@ -548,19 +548,19 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct | |||
548 | { | 548 | { |
549 | struct dvb_device *dvbdev = file->private_data; | 549 | struct dvb_device *dvbdev = file->private_data; |
550 | struct cinergyt2 *cinergyt2 = dvbdev->priv; | 550 | struct cinergyt2 *cinergyt2 = dvbdev->priv; |
551 | unsigned int mask = 0; | 551 | unsigned int mask = 0; |
552 | 552 | ||
553 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) | 553 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) |
554 | return -ERESTARTSYS; | 554 | return -ERESTARTSYS; |
555 | 555 | ||
556 | poll_wait(file, &cinergyt2->poll_wq, wait); | 556 | poll_wait(file, &cinergyt2->poll_wq, wait); |
557 | 557 | ||
558 | if (cinergyt2->pending_fe_events != 0) | 558 | if (cinergyt2->pending_fe_events != 0) |
559 | mask |= (POLLIN | POLLRDNORM | POLLPRI); | 559 | mask |= (POLLIN | POLLRDNORM | POLLPRI); |
560 | 560 | ||
561 | mutex_unlock(&cinergyt2->sem); | 561 | mutex_unlock(&cinergyt2->sem); |
562 | 562 | ||
563 | return mask; | 563 | return mask; |
564 | } | 564 | } |
565 | 565 | ||
566 | 566 | ||
@@ -1008,6 +1008,8 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state) | |||
1008 | cinergyt2_sleep(cinergyt2, 1); | 1008 | cinergyt2_sleep(cinergyt2, 1); |
1009 | mutex_unlock(&cinergyt2->sem); | 1009 | mutex_unlock(&cinergyt2->sem); |
1010 | 1010 | ||
1011 | mutex_unlock(&cinergyt2->wq_sem); | ||
1012 | |||
1011 | return 0; | 1013 | return 0; |
1012 | } | 1014 | } |
1013 | 1015 | ||
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 5394de2e4ce0..f94bc31e3b33 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/vmalloc.h> | 25 | #include <linux/vmalloc.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/moduleparam.h> | ||
28 | #include <linux/poll.h> | 27 | #include <linux/poll.h> |
29 | #include <linux/ioctl.h> | 28 | #include <linux/ioctl.h> |
30 | #include <linux/wait.h> | 29 | #include <linux/wait.h> |
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index 4fadddb264d6..084a508a03da 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c | |||
@@ -32,11 +32,11 @@ | |||
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/list.h> | 33 | #include <linux/list.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/moduleparam.h> | ||
36 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
37 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
38 | #include <linux/spinlock.h> | 37 | #include <linux/spinlock.h> |
39 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
39 | #include <linux/kthread.h> | ||
40 | 40 | ||
41 | #include "dvb_ca_en50221.h" | 41 | #include "dvb_ca_en50221.h" |
42 | #include "dvb_ringbuffer.h" | 42 | #include "dvb_ringbuffer.h" |
@@ -140,13 +140,7 @@ struct dvb_ca_private { | |||
140 | wait_queue_head_t wait_queue; | 140 | wait_queue_head_t wait_queue; |
141 | 141 | ||
142 | /* PID of the monitoring thread */ | 142 | /* PID of the monitoring thread */ |
143 | pid_t thread_pid; | 143 | struct task_struct *thread; |
144 | |||
145 | /* Wait queue used when shutting thread down */ | ||
146 | wait_queue_head_t thread_queue; | ||
147 | |||
148 | /* Flag indicating when thread should exit */ | ||
149 | unsigned int exit:1; | ||
150 | 144 | ||
151 | /* Flag indicating if the CA device is open */ | 145 | /* Flag indicating if the CA device is open */ |
152 | unsigned int open:1; | 146 | unsigned int open:1; |
@@ -902,28 +896,10 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca) | |||
902 | 896 | ||
903 | ca->wakeup = 1; | 897 | ca->wakeup = 1; |
904 | mb(); | 898 | mb(); |
905 | wake_up_interruptible(&ca->thread_queue); | 899 | wake_up_process(ca->thread); |
906 | } | 900 | } |
907 | 901 | ||
908 | /** | 902 | /** |
909 | * Used by the CA thread to determine if an early wakeup is necessary | ||
910 | * | ||
911 | * @param ca CA instance. | ||
912 | */ | ||
913 | static int dvb_ca_en50221_thread_should_wakeup(struct dvb_ca_private *ca) | ||
914 | { | ||
915 | if (ca->wakeup) { | ||
916 | ca->wakeup = 0; | ||
917 | return 1; | ||
918 | } | ||
919 | if (ca->exit) | ||
920 | return 1; | ||
921 | |||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | |||
926 | /** | ||
927 | * Update the delay used by the thread. | 903 | * Update the delay used by the thread. |
928 | * | 904 | * |
929 | * @param ca CA instance. | 905 | * @param ca CA instance. |
@@ -982,7 +958,6 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca) | |||
982 | static int dvb_ca_en50221_thread(void *data) | 958 | static int dvb_ca_en50221_thread(void *data) |
983 | { | 959 | { |
984 | struct dvb_ca_private *ca = data; | 960 | struct dvb_ca_private *ca = data; |
985 | char name[15]; | ||
986 | int slot; | 961 | int slot; |
987 | int flags; | 962 | int flags; |
988 | int status; | 963 | int status; |
@@ -991,28 +966,17 @@ static int dvb_ca_en50221_thread(void *data) | |||
991 | 966 | ||
992 | dprintk("%s\n", __FUNCTION__); | 967 | dprintk("%s\n", __FUNCTION__); |
993 | 968 | ||
994 | /* setup kernel thread */ | ||
995 | snprintf(name, sizeof(name), "kdvb-ca-%i:%i", ca->dvbdev->adapter->num, ca->dvbdev->id); | ||
996 | |||
997 | lock_kernel(); | ||
998 | daemonize(name); | ||
999 | sigfillset(¤t->blocked); | ||
1000 | unlock_kernel(); | ||
1001 | |||
1002 | /* choose the correct initial delay */ | 969 | /* choose the correct initial delay */ |
1003 | dvb_ca_en50221_thread_update_delay(ca); | 970 | dvb_ca_en50221_thread_update_delay(ca); |
1004 | 971 | ||
1005 | /* main loop */ | 972 | /* main loop */ |
1006 | while (!ca->exit) { | 973 | while (!kthread_should_stop()) { |
1007 | /* sleep for a bit */ | 974 | /* sleep for a bit */ |
1008 | if (!ca->wakeup) { | 975 | while (!ca->wakeup) { |
1009 | flags = wait_event_interruptible_timeout(ca->thread_queue, | 976 | set_current_state(TASK_INTERRUPTIBLE); |
1010 | dvb_ca_en50221_thread_should_wakeup(ca), | 977 | schedule_timeout(ca->delay); |
1011 | ca->delay); | 978 | if (kthread_should_stop()) |
1012 | if ((flags == -ERESTARTSYS) || ca->exit) { | 979 | return 0; |
1013 | /* got signal or quitting */ | ||
1014 | break; | ||
1015 | } | ||
1016 | } | 980 | } |
1017 | ca->wakeup = 0; | 981 | ca->wakeup = 0; |
1018 | 982 | ||
@@ -1181,10 +1145,6 @@ static int dvb_ca_en50221_thread(void *data) | |||
1181 | } | 1145 | } |
1182 | } | 1146 | } |
1183 | 1147 | ||
1184 | /* completed */ | ||
1185 | ca->thread_pid = 0; | ||
1186 | mb(); | ||
1187 | wake_up_interruptible(&ca->thread_queue); | ||
1188 | return 0; | 1148 | return 0; |
1189 | } | 1149 | } |
1190 | 1150 | ||
@@ -1536,8 +1496,10 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) | |||
1536 | return -EIO; | 1496 | return -EIO; |
1537 | 1497 | ||
1538 | err = dvb_generic_open(inode, file); | 1498 | err = dvb_generic_open(inode, file); |
1539 | if (err < 0) | 1499 | if (err < 0) { |
1500 | module_put(ca->pub->owner); | ||
1540 | return err; | 1501 | return err; |
1502 | } | ||
1541 | 1503 | ||
1542 | for (i = 0; i < ca->slot_count; i++) { | 1504 | for (i = 0; i < ca->slot_count; i++) { |
1543 | 1505 | ||
@@ -1570,7 +1532,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) | |||
1570 | { | 1532 | { |
1571 | struct dvb_device *dvbdev = file->private_data; | 1533 | struct dvb_device *dvbdev = file->private_data; |
1572 | struct dvb_ca_private *ca = dvbdev->priv; | 1534 | struct dvb_ca_private *ca = dvbdev->priv; |
1573 | int err = 0; | 1535 | int err; |
1574 | 1536 | ||
1575 | dprintk("%s\n", __FUNCTION__); | 1537 | dprintk("%s\n", __FUNCTION__); |
1576 | 1538 | ||
@@ -1582,7 +1544,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) | |||
1582 | 1544 | ||
1583 | module_put(ca->pub->owner); | 1545 | module_put(ca->pub->owner); |
1584 | 1546 | ||
1585 | return 0; | 1547 | return err; |
1586 | } | 1548 | } |
1587 | 1549 | ||
1588 | 1550 | ||
@@ -1682,9 +1644,6 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, | |||
1682 | goto error; | 1644 | goto error; |
1683 | } | 1645 | } |
1684 | init_waitqueue_head(&ca->wait_queue); | 1646 | init_waitqueue_head(&ca->wait_queue); |
1685 | ca->thread_pid = 0; | ||
1686 | init_waitqueue_head(&ca->thread_queue); | ||
1687 | ca->exit = 0; | ||
1688 | ca->open = 0; | 1647 | ca->open = 0; |
1689 | ca->wakeup = 0; | 1648 | ca->wakeup = 0; |
1690 | ca->next_read_slot = 0; | 1649 | ca->next_read_slot = 0; |
@@ -1710,14 +1669,14 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, | |||
1710 | mb(); | 1669 | mb(); |
1711 | 1670 | ||
1712 | /* create a kthread for monitoring this CA device */ | 1671 | /* create a kthread for monitoring this CA device */ |
1713 | 1672 | ca->thread = kthread_run(dvb_ca_en50221_thread, ca, "kdvb-ca-%i:%i", | |
1714 | ret = kernel_thread(dvb_ca_en50221_thread, ca, 0); | 1673 | ca->dvbdev->adapter->num, ca->dvbdev->id); |
1715 | 1674 | if (IS_ERR(ca->thread)) { | |
1716 | if (ret < 0) { | 1675 | ret = PTR_ERR(ca->thread); |
1717 | printk("dvb_ca_init: failed to start kernel_thread (%d)\n", ret); | 1676 | printk("dvb_ca_init: failed to start kernel_thread (%d)\n", |
1677 | ret); | ||
1718 | goto error; | 1678 | goto error; |
1719 | } | 1679 | } |
1720 | ca->thread_pid = ret; | ||
1721 | return 0; | 1680 | return 0; |
1722 | 1681 | ||
1723 | error: | 1682 | error: |
@@ -1748,17 +1707,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca) | |||
1748 | dprintk("%s\n", __FUNCTION__); | 1707 | dprintk("%s\n", __FUNCTION__); |
1749 | 1708 | ||
1750 | /* shutdown the thread if there was one */ | 1709 | /* shutdown the thread if there was one */ |
1751 | if (ca->thread_pid) { | 1710 | kthread_stop(ca->thread); |
1752 | if (kill_proc(ca->thread_pid, 0, 1) == -ESRCH) { | ||
1753 | printk("dvb_ca_release adapter %d: thread PID %d already died\n", | ||
1754 | ca->dvbdev->adapter->num, ca->thread_pid); | ||
1755 | } else { | ||
1756 | ca->exit = 1; | ||
1757 | mb(); | ||
1758 | dvb_ca_en50221_thread_wakeup(ca); | ||
1759 | wait_event_interruptible(ca->thread_queue, ca->thread_pid == 0); | ||
1760 | } | ||
1761 | } | ||
1762 | 1711 | ||
1763 | for (i = 0; i < ca->slot_count; i++) { | 1712 | for (i = 0; i < ca->slot_count; i++) { |
1764 | dvb_ca_en50221_slot_shutdown(ca, i); | 1713 | dvb_ca_en50221_slot_shutdown(ca, i); |
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index cb6987fce26c..7959020f9317 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c | |||
@@ -373,13 +373,10 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, | |||
373 | static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) | 373 | static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) |
374 | { | 374 | { |
375 | struct dvb_demux_feed *feed; | 375 | struct dvb_demux_feed *feed; |
376 | struct list_head *pos, *head = &demux->feed_list; | ||
377 | u16 pid = ts_pid(buf); | 376 | u16 pid = ts_pid(buf); |
378 | int dvr_done = 0; | 377 | int dvr_done = 0; |
379 | 378 | ||
380 | list_for_each(pos, head) { | 379 | list_for_each_entry(feed, &demux->feed_list, list_head) { |
381 | feed = list_entry(pos, struct dvb_demux_feed, list_head); | ||
382 | |||
383 | if ((feed->pid != pid) && (feed->pid != 0x2000)) | 380 | if ((feed->pid != pid) && (feed->pid != 0x2000)) |
384 | continue; | 381 | continue; |
385 | 382 | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index b6c7f6610ec5..b203640ef1c5 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/poll.h> | 33 | #include <linux/poll.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/moduleparam.h> | ||
36 | #include <linux/list.h> | 35 | #include <linux/list.h> |
37 | #include <linux/freezer.h> | 36 | #include <linux/freezer.h> |
38 | #include <linux/jiffies.h> | 37 | #include <linux/jiffies.h> |
@@ -43,7 +42,7 @@ | |||
43 | #include "dvbdev.h" | 42 | #include "dvbdev.h" |
44 | 43 | ||
45 | static int dvb_frontend_debug; | 44 | static int dvb_frontend_debug; |
46 | static int dvb_shutdown_timeout = 5; | 45 | static int dvb_shutdown_timeout; |
47 | static int dvb_force_auto_inversion; | 46 | static int dvb_force_auto_inversion; |
48 | static int dvb_override_tune_delay; | 47 | static int dvb_override_tune_delay; |
49 | static int dvb_powerdown_on_sleep = 1; | 48 | static int dvb_powerdown_on_sleep = 1; |
@@ -138,7 +137,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) | |||
138 | 137 | ||
139 | dprintk ("%s\n", __FUNCTION__); | 138 | dprintk ("%s\n", __FUNCTION__); |
140 | 139 | ||
141 | if (down_interruptible (&events->sem)) | 140 | if (mutex_lock_interruptible (&events->mtx)) |
142 | return; | 141 | return; |
143 | 142 | ||
144 | wp = (events->eventw + 1) % MAX_EVENT; | 143 | wp = (events->eventw + 1) % MAX_EVENT; |
@@ -159,7 +158,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) | |||
159 | 158 | ||
160 | events->eventw = wp; | 159 | events->eventw = wp; |
161 | 160 | ||
162 | up (&events->sem); | 161 | mutex_unlock(&events->mtx); |
163 | 162 | ||
164 | e->status = status; | 163 | e->status = status; |
165 | 164 | ||
@@ -197,7 +196,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe, | |||
197 | return ret; | 196 | return ret; |
198 | } | 197 | } |
199 | 198 | ||
200 | if (down_interruptible (&events->sem)) | 199 | if (mutex_lock_interruptible (&events->mtx)) |
201 | return -ERESTARTSYS; | 200 | return -ERESTARTSYS; |
202 | 201 | ||
203 | memcpy (event, &events->events[events->eventr], | 202 | memcpy (event, &events->events[events->eventr], |
@@ -205,7 +204,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe, | |||
205 | 204 | ||
206 | events->eventr = (events->eventr + 1) % MAX_EVENT; | 205 | events->eventr = (events->eventr + 1) % MAX_EVENT; |
207 | 206 | ||
208 | up (&events->sem); | 207 | mutex_unlock(&events->mtx); |
209 | 208 | ||
210 | return 0; | 209 | return 0; |
211 | } | 210 | } |
@@ -574,10 +573,9 @@ restart: | |||
574 | dvb_frontend_swzigzag(fe); | 573 | dvb_frontend_swzigzag(fe); |
575 | } | 574 | } |
576 | 575 | ||
577 | if (dvb_shutdown_timeout) { | 576 | if (dvb_powerdown_on_sleep) { |
578 | if (dvb_powerdown_on_sleep) | 577 | if (fe->ops.set_voltage) |
579 | if (fe->ops.set_voltage) | 578 | fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF); |
580 | fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF); | ||
581 | if (fe->ops.tuner_ops.sleep) { | 579 | if (fe->ops.tuner_ops.sleep) { |
582 | fe->ops.tuner_ops.sleep(fe); | 580 | fe->ops.tuner_ops.sleep(fe); |
583 | if (fe->ops.i2c_gate_ctrl) | 581 | if (fe->ops.i2c_gate_ctrl) |
@@ -697,6 +695,65 @@ static int dvb_frontend_start(struct dvb_frontend *fe) | |||
697 | return 0; | 695 | return 0; |
698 | } | 696 | } |
699 | 697 | ||
698 | static void dvb_frontend_get_frequeny_limits(struct dvb_frontend *fe, | ||
699 | u32 *freq_min, u32 *freq_max) | ||
700 | { | ||
701 | *freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min); | ||
702 | |||
703 | if (fe->ops.info.frequency_max == 0) | ||
704 | *freq_max = fe->ops.tuner_ops.info.frequency_max; | ||
705 | else if (fe->ops.tuner_ops.info.frequency_max == 0) | ||
706 | *freq_max = fe->ops.info.frequency_max; | ||
707 | else | ||
708 | *freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max); | ||
709 | |||
710 | if (*freq_min == 0 || *freq_max == 0) | ||
711 | printk(KERN_WARNING "DVB: frontend %u frequency limits undefined - fix the driver\n", | ||
712 | fe->dvb->num); | ||
713 | } | ||
714 | |||
715 | static int dvb_frontend_check_parameters(struct dvb_frontend *fe, | ||
716 | struct dvb_frontend_parameters *parms) | ||
717 | { | ||
718 | u32 freq_min; | ||
719 | u32 freq_max; | ||
720 | |||
721 | /* range check: frequency */ | ||
722 | dvb_frontend_get_frequeny_limits(fe, &freq_min, &freq_max); | ||
723 | if ((freq_min && parms->frequency < freq_min) || | ||
724 | (freq_max && parms->frequency > freq_max)) { | ||
725 | printk(KERN_WARNING "DVB: frontend %u frequency %u out of range (%u..%u)\n", | ||
726 | fe->dvb->num, parms->frequency, freq_min, freq_max); | ||
727 | return -EINVAL; | ||
728 | } | ||
729 | |||
730 | /* range check: symbol rate */ | ||
731 | if (fe->ops.info.type == FE_QPSK) { | ||
732 | if ((fe->ops.info.symbol_rate_min && | ||
733 | parms->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) || | ||
734 | (fe->ops.info.symbol_rate_max && | ||
735 | parms->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) { | ||
736 | printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n", | ||
737 | fe->dvb->num, parms->u.qpsk.symbol_rate, | ||
738 | fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); | ||
739 | return -EINVAL; | ||
740 | } | ||
741 | |||
742 | } else if (fe->ops.info.type == FE_QAM) { | ||
743 | if ((fe->ops.info.symbol_rate_min && | ||
744 | parms->u.qam.symbol_rate < fe->ops.info.symbol_rate_min) || | ||
745 | (fe->ops.info.symbol_rate_max && | ||
746 | parms->u.qam.symbol_rate > fe->ops.info.symbol_rate_max)) { | ||
747 | printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n", | ||
748 | fe->dvb->num, parms->u.qam.symbol_rate, | ||
749 | fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); | ||
750 | return -EINVAL; | ||
751 | } | ||
752 | } | ||
753 | |||
754 | return 0; | ||
755 | } | ||
756 | |||
700 | static int dvb_frontend_ioctl(struct inode *inode, struct file *file, | 757 | static int dvb_frontend_ioctl(struct inode *inode, struct file *file, |
701 | unsigned int cmd, void *parg) | 758 | unsigned int cmd, void *parg) |
702 | { | 759 | { |
@@ -707,7 +764,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, | |||
707 | 764 | ||
708 | dprintk ("%s\n", __FUNCTION__); | 765 | dprintk ("%s\n", __FUNCTION__); |
709 | 766 | ||
710 | if (!fe || fepriv->exit) | 767 | if (fepriv->exit) |
711 | return -ENODEV; | 768 | return -ENODEV; |
712 | 769 | ||
713 | if ((file->f_flags & O_ACCMODE) == O_RDONLY && | 770 | if ((file->f_flags & O_ACCMODE) == O_RDONLY && |
@@ -722,6 +779,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, | |||
722 | case FE_GET_INFO: { | 779 | case FE_GET_INFO: { |
723 | struct dvb_frontend_info* info = parg; | 780 | struct dvb_frontend_info* info = parg; |
724 | memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info)); | 781 | memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info)); |
782 | dvb_frontend_get_frequeny_limits(fe, &info->frequency_min, &info->frequency_max); | ||
725 | 783 | ||
726 | /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't | 784 | /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't |
727 | * do it, it is done for it. */ | 785 | * do it, it is done for it. */ |
@@ -883,6 +941,11 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, | |||
883 | case FE_SET_FRONTEND: { | 941 | case FE_SET_FRONTEND: { |
884 | struct dvb_frontend_tune_settings fetunesettings; | 942 | struct dvb_frontend_tune_settings fetunesettings; |
885 | 943 | ||
944 | if (dvb_frontend_check_parameters(fe, parg) < 0) { | ||
945 | err = -EINVAL; | ||
946 | break; | ||
947 | } | ||
948 | |||
886 | memcpy (&fepriv->parameters, parg, | 949 | memcpy (&fepriv->parameters, parg, |
887 | sizeof (struct dvb_frontend_parameters)); | 950 | sizeof (struct dvb_frontend_parameters)); |
888 | 951 | ||
@@ -992,18 +1055,15 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) | |||
992 | 1055 | ||
993 | dprintk ("%s\n", __FUNCTION__); | 1056 | dprintk ("%s\n", __FUNCTION__); |
994 | 1057 | ||
995 | if ((ret = dvb_generic_open (inode, file)) < 0) | 1058 | if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) { |
996 | return ret; | 1059 | if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0) |
997 | |||
998 | if (fe->ops.ts_bus_ctrl) { | ||
999 | if ((ret = fe->ops.ts_bus_ctrl (fe, 1)) < 0) { | ||
1000 | dvb_generic_release (inode, file); | ||
1001 | return ret; | 1060 | return ret; |
1002 | } | ||
1003 | } | 1061 | } |
1004 | 1062 | ||
1005 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { | 1063 | if ((ret = dvb_generic_open (inode, file)) < 0) |
1064 | goto err1; | ||
1006 | 1065 | ||
1066 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { | ||
1007 | /* normal tune mode when opened R/W */ | 1067 | /* normal tune mode when opened R/W */ |
1008 | fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; | 1068 | fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; |
1009 | fepriv->tone = -1; | 1069 | fepriv->tone = -1; |
@@ -1011,13 +1071,20 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) | |||
1011 | 1071 | ||
1012 | ret = dvb_frontend_start (fe); | 1072 | ret = dvb_frontend_start (fe); |
1013 | if (ret) | 1073 | if (ret) |
1014 | dvb_generic_release (inode, file); | 1074 | goto err2; |
1015 | 1075 | ||
1016 | /* empty event queue */ | 1076 | /* empty event queue */ |
1017 | fepriv->events.eventr = fepriv->events.eventw = 0; | 1077 | fepriv->events.eventr = fepriv->events.eventw = 0; |
1018 | } | 1078 | } |
1019 | 1079 | ||
1020 | return ret; | 1080 | return ret; |
1081 | |||
1082 | err2: | ||
1083 | dvb_generic_release(inode, file); | ||
1084 | err1: | ||
1085 | if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) | ||
1086 | fe->ops.ts_bus_ctrl(fe, 0); | ||
1087 | return ret; | ||
1021 | } | 1088 | } |
1022 | 1089 | ||
1023 | static int dvb_frontend_release(struct inode *inode, struct file *file) | 1090 | static int dvb_frontend_release(struct inode *inode, struct file *file) |
@@ -1032,16 +1099,18 @@ static int dvb_frontend_release(struct inode *inode, struct file *file) | |||
1032 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) | 1099 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) |
1033 | fepriv->release_jiffies = jiffies; | 1100 | fepriv->release_jiffies = jiffies; |
1034 | 1101 | ||
1035 | if (fe->ops.ts_bus_ctrl) | ||
1036 | fe->ops.ts_bus_ctrl (fe, 0); | ||
1037 | |||
1038 | ret = dvb_generic_release (inode, file); | 1102 | ret = dvb_generic_release (inode, file); |
1039 | 1103 | ||
1040 | if (dvbdev->users==-1 && fepriv->exit==1) { | 1104 | if (dvbdev->users == -1) { |
1041 | fops_put(file->f_op); | 1105 | if (fepriv->exit == 1) { |
1042 | file->f_op = NULL; | 1106 | fops_put(file->f_op); |
1043 | wake_up(&dvbdev->wait_queue); | 1107 | file->f_op = NULL; |
1108 | wake_up(&dvbdev->wait_queue); | ||
1109 | } | ||
1110 | if (fe->ops.ts_bus_ctrl) | ||
1111 | fe->ops.ts_bus_ctrl(fe, 0); | ||
1044 | } | 1112 | } |
1113 | |||
1045 | return ret; | 1114 | return ret; |
1046 | } | 1115 | } |
1047 | 1116 | ||
@@ -1080,7 +1149,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb, | |||
1080 | init_MUTEX (&fepriv->sem); | 1149 | init_MUTEX (&fepriv->sem); |
1081 | init_waitqueue_head (&fepriv->wait_queue); | 1150 | init_waitqueue_head (&fepriv->wait_queue); |
1082 | init_waitqueue_head (&fepriv->events.wait_queue); | 1151 | init_waitqueue_head (&fepriv->events.wait_queue); |
1083 | init_MUTEX (&fepriv->events.sem); | 1152 | mutex_init(&fepriv->events.mtx); |
1084 | fe->dvb = dvb; | 1153 | fe->dvb = dvb; |
1085 | fepriv->inversion = INVERSION_OFF; | 1154 | fepriv->inversion = INVERSION_OFF; |
1086 | 1155 | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index a770a87b9a93..a5262e852c82 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/errno.h> | 36 | #include <linux/errno.h> |
37 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
38 | #include <linux/mutex.h> | ||
38 | 39 | ||
39 | #include <linux/dvb/frontend.h> | 40 | #include <linux/dvb/frontend.h> |
40 | 41 | ||
@@ -61,6 +62,13 @@ struct dvb_tuner_info { | |||
61 | u32 bandwidth_step; | 62 | u32 bandwidth_step; |
62 | }; | 63 | }; |
63 | 64 | ||
65 | struct analog_parameters { | ||
66 | unsigned int frequency; | ||
67 | unsigned int mode; | ||
68 | unsigned int audmode; | ||
69 | u64 std; | ||
70 | }; | ||
71 | |||
64 | struct dvb_tuner_ops { | 72 | struct dvb_tuner_ops { |
65 | 73 | ||
66 | struct dvb_tuner_info info; | 74 | struct dvb_tuner_info info; |
@@ -71,6 +79,7 @@ struct dvb_tuner_ops { | |||
71 | 79 | ||
72 | /** This is for simple PLLs - set all parameters in one go. */ | 80 | /** This is for simple PLLs - set all parameters in one go. */ |
73 | int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p); | 81 | int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p); |
82 | int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p); | ||
74 | 83 | ||
75 | /** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */ | 84 | /** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */ |
76 | int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len); | 85 | int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len); |
@@ -79,7 +88,9 @@ struct dvb_tuner_ops { | |||
79 | int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth); | 88 | int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth); |
80 | 89 | ||
81 | #define TUNER_STATUS_LOCKED 1 | 90 | #define TUNER_STATUS_LOCKED 1 |
91 | #define TUNER_STATUS_STEREO 2 | ||
82 | int (*get_status)(struct dvb_frontend *fe, u32 *status); | 92 | int (*get_status)(struct dvb_frontend *fe, u32 *status); |
93 | int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength); | ||
83 | 94 | ||
84 | /** These are provided seperately from set_params in order to facilitate silicon | 95 | /** These are provided seperately from set_params in order to facilitate silicon |
85 | * tuners which require sophisticated tuning loops, controlling each parameter seperately. */ | 96 | * tuners which require sophisticated tuning loops, controlling each parameter seperately. */ |
@@ -142,7 +153,7 @@ struct dvb_fe_events { | |||
142 | int eventr; | 153 | int eventr; |
143 | int overflow; | 154 | int overflow; |
144 | wait_queue_head_t wait_queue; | 155 | wait_queue_head_t wait_queue; |
145 | struct semaphore sem; | 156 | struct mutex mtx; |
146 | }; | 157 | }; |
147 | 158 | ||
148 | struct dvb_frontend { | 159 | struct dvb_frontend { |
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index bdd797071cb0..2117377c141d 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c | |||
@@ -357,11 +357,6 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
357 | static unsigned char *ule_where = ule_hist, ule_dump = 0; | 357 | static unsigned char *ule_where = ule_hist, ule_dump = 0; |
358 | #endif | 358 | #endif |
359 | 359 | ||
360 | if (dev == NULL) { | ||
361 | printk( KERN_ERR "NO netdev struct!\n" ); | ||
362 | return; | ||
363 | } | ||
364 | |||
365 | /* For all TS cells in current buffer. | 360 | /* For all TS cells in current buffer. |
366 | * Appearently, we are called for every single TS cell. | 361 | * Appearently, we are called for every single TS cell. |
367 | */ | 362 | */ |
@@ -800,8 +795,8 @@ static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len, | |||
800 | } | 795 | } |
801 | 796 | ||
802 | 797 | ||
803 | static void dvb_net_sec(struct net_device *dev, const u8 *pkt, int | 798 | static void dvb_net_sec(struct net_device *dev, |
804 | pkt_len) | 799 | const u8 *pkt, int pkt_len) |
805 | { | 800 | { |
806 | u8 *eth; | 801 | u8 *eth; |
807 | struct sk_buff *skb; | 802 | struct sk_buff *skb; |
@@ -1446,18 +1441,9 @@ static int dvb_net_close(struct inode *inode, struct file *file) | |||
1446 | struct dvb_device *dvbdev = file->private_data; | 1441 | struct dvb_device *dvbdev = file->private_data; |
1447 | struct dvb_net *dvbnet = dvbdev->priv; | 1442 | struct dvb_net *dvbnet = dvbdev->priv; |
1448 | 1443 | ||
1449 | if (!dvbdev) | 1444 | dvb_generic_release(inode, file); |
1450 | return -ENODEV; | ||
1451 | |||
1452 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | ||
1453 | dvbdev->readers++; | ||
1454 | } else { | ||
1455 | dvbdev->writers++; | ||
1456 | } | ||
1457 | |||
1458 | dvbdev->users++; | ||
1459 | 1445 | ||
1460 | if(dvbdev->users == 1 && dvbnet->exit==1) { | 1446 | if(dvbdev->users == 1 && dvbnet->exit == 1) { |
1461 | fops_put(file->f_op); | 1447 | fops_put(file->f_op); |
1462 | file->f_op = NULL; | 1448 | file->f_op = NULL; |
1463 | wake_up(&dvbdev->wait_queue); | 1449 | wake_up(&dvbdev->wait_queue); |
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 9ef0c00605ee..56231d8edc07 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
26 | #include <linux/string.h> | 26 | #include <linux/string.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | ||
29 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
30 | #include <linux/init.h> | 29 | #include <linux/init.h> |
31 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
@@ -59,18 +58,13 @@ static struct class *dvb_class; | |||
59 | 58 | ||
60 | static struct dvb_device* dvbdev_find_device (int minor) | 59 | static struct dvb_device* dvbdev_find_device (int minor) |
61 | { | 60 | { |
62 | struct list_head *entry; | 61 | struct dvb_adapter *adap; |
63 | 62 | ||
64 | list_for_each (entry, &dvb_adapter_list) { | 63 | list_for_each_entry(adap, &dvb_adapter_list, list_head) { |
65 | struct list_head *entry0; | 64 | struct dvb_device *dev; |
66 | struct dvb_adapter *adap; | 65 | list_for_each_entry(dev, &adap->device_list, list_head) |
67 | adap = list_entry (entry, struct dvb_adapter, list_head); | ||
68 | list_for_each (entry0, &adap->device_list) { | ||
69 | struct dvb_device *dev; | ||
70 | dev = list_entry (entry0, struct dvb_device, list_head); | ||
71 | if (nums2minor(adap->num, dev->type, dev->id) == minor) | 66 | if (nums2minor(adap->num, dev->type, dev->id) == minor) |
72 | return dev; | 67 | return dev; |
73 | } | ||
74 | } | 68 | } |
75 | 69 | ||
76 | return NULL; | 70 | return NULL; |
@@ -180,13 +174,10 @@ static int dvbdev_get_free_id (struct dvb_adapter *adap, int type) | |||
180 | u32 id = 0; | 174 | u32 id = 0; |
181 | 175 | ||
182 | while (id < DVB_MAX_IDS) { | 176 | while (id < DVB_MAX_IDS) { |
183 | struct list_head *entry; | 177 | struct dvb_device *dev; |
184 | list_for_each (entry, &adap->device_list) { | 178 | list_for_each_entry(dev, &adap->device_list, list_head) |
185 | struct dvb_device *dev; | ||
186 | dev = list_entry (entry, struct dvb_device, list_head); | ||
187 | if (dev->type == type && dev->id == id) | 179 | if (dev->type == type && dev->id == id) |
188 | goto skip; | 180 | goto skip; |
189 | } | ||
190 | return id; | 181 | return id; |
191 | skip: | 182 | skip: |
192 | id++; | 183 | id++; |
@@ -200,7 +191,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | |||
200 | { | 191 | { |
201 | struct dvb_device *dvbdev; | 192 | struct dvb_device *dvbdev; |
202 | struct file_operations *dvbdevfops; | 193 | struct file_operations *dvbdevfops; |
203 | struct class_device *clsdev; | 194 | struct device *clsdev; |
204 | int id; | 195 | int id; |
205 | 196 | ||
206 | mutex_lock(&dvbdev_register_lock); | 197 | mutex_lock(&dvbdev_register_lock); |
@@ -242,10 +233,9 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | |||
242 | 233 | ||
243 | mutex_unlock(&dvbdev_register_lock); | 234 | mutex_unlock(&dvbdev_register_lock); |
244 | 235 | ||
245 | clsdev = class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, | 236 | clsdev = device_create(dvb_class, adap->device, |
246 | nums2minor(adap->num, type, id)), | 237 | MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), |
247 | adap->device, "dvb%d.%s%d", adap->num, | 238 | "dvb%d.%s%d", adap->num, dnames[type], id); |
248 | dnames[type], id); | ||
249 | if (IS_ERR(clsdev)) { | 239 | if (IS_ERR(clsdev)) { |
250 | printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n", | 240 | printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n", |
251 | __FUNCTION__, adap->num, dnames[type], id, PTR_ERR(clsdev)); | 241 | __FUNCTION__, adap->num, dnames[type], id, PTR_ERR(clsdev)); |
@@ -266,8 +256,8 @@ void dvb_unregister_device(struct dvb_device *dvbdev) | |||
266 | if (!dvbdev) | 256 | if (!dvbdev) |
267 | return; | 257 | return; |
268 | 258 | ||
269 | class_device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num, | 259 | device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num, |
270 | dvbdev->type, dvbdev->id))); | 260 | dvbdev->type, dvbdev->id))); |
271 | 261 | ||
272 | list_del (&dvbdev->list_head); | 262 | list_del (&dvbdev->list_head); |
273 | kfree (dvbdev->fops); | 263 | kfree (dvbdev->fops); |
@@ -281,13 +271,10 @@ static int dvbdev_get_free_adapter_num (void) | |||
281 | int num = 0; | 271 | int num = 0; |
282 | 272 | ||
283 | while (num < DVB_MAX_ADAPTERS) { | 273 | while (num < DVB_MAX_ADAPTERS) { |
284 | struct list_head *entry; | 274 | struct dvb_adapter *adap; |
285 | list_for_each (entry, &dvb_adapter_list) { | 275 | list_for_each_entry(adap, &dvb_adapter_list, list_head) |
286 | struct dvb_adapter *adap; | ||
287 | adap = list_entry (entry, struct dvb_adapter, list_head); | ||
288 | if (adap->num == num) | 276 | if (adap->num == num) |
289 | goto skip; | 277 | goto skip; |
290 | } | ||
291 | return num; | 278 | return num; |
292 | skip: | 279 | skip: |
293 | num++; | 280 | num++; |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 40e41f2f5afe..d73934dd4c57 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -74,6 +74,8 @@ config DVB_USB_DIB0700 | |||
74 | select DVB_DIB7000M | 74 | select DVB_DIB7000M |
75 | select DVB_DIB3000MC | 75 | select DVB_DIB3000MC |
76 | select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE | 76 | select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE |
77 | select DVB_TUNER_MT2266 if !DVB_FE_CUSTOMISE | ||
78 | select DVB_TUNER_DIB0070 | ||
77 | help | 79 | help |
78 | Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The | 80 | Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The |
79 | USB bridge is also present in devices having the DiB7700 DVB-T-USB | 81 | USB bridge is also present in devices having the DiB7700 DVB-T-USB |
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index cda3adea24fb..4a903ea95896 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h | |||
@@ -30,17 +30,19 @@ extern int dvb_usb_dib0700_debug; | |||
30 | // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog) | 30 | // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog) |
31 | // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) | 31 | // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) |
32 | // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) | 32 | // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) |
33 | #define REQUEST_SET_RC 0x11 | ||
33 | #define REQUEST_GET_VERSION 0x15 | 34 | #define REQUEST_GET_VERSION 0x15 |
34 | 35 | ||
35 | struct dib0700_state { | 36 | struct dib0700_state { |
36 | u8 channel_state; | 37 | u8 channel_state; |
37 | u16 mt2060_if1[2]; | 38 | u16 mt2060_if1[2]; |
38 | 39 | u8 rc_toggle; | |
39 | u8 is_dib7000pc; | 40 | u8 is_dib7000pc; |
40 | }; | 41 | }; |
41 | 42 | ||
42 | extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); | 43 | extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); |
43 | extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); | 44 | extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); |
45 | extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen); | ||
44 | extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw); | 46 | extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw); |
45 | extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); | 47 | extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); |
46 | extern struct i2c_algorithm dib0700_i2c_algo; | 48 | extern struct i2c_algorithm dib0700_i2c_algo; |
@@ -50,5 +52,4 @@ extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device | |||
50 | extern int dib0700_device_count; | 52 | extern int dib0700_device_count; |
51 | extern struct dvb_usb_device_properties dib0700_devices[]; | 53 | extern struct dvb_usb_device_properties dib0700_devices[]; |
52 | extern struct usb_device_id dib0700_usb_id_table[]; | 54 | extern struct usb_device_id dib0700_usb_id_table[]; |
53 | |||
54 | #endif | 55 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index dddf164f269a..3ea294eb96bd 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c | |||
@@ -13,6 +13,10 @@ int dvb_usb_dib0700_debug; | |||
13 | module_param_named(debug,dvb_usb_dib0700_debug, int, 0644); | 13 | module_param_named(debug,dvb_usb_dib0700_debug, int, 0644); |
14 | MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS); | 14 | MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS); |
15 | 15 | ||
16 | static int dvb_usb_dib0700_ir_proto = 1; | ||
17 | module_param(dvb_usb_dib0700_ir_proto, int, 0644); | ||
18 | MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6)."); | ||
19 | |||
16 | /* expecting rx buffer: request data[0] data[1] ... data[2] */ | 20 | /* expecting rx buffer: request data[0] data[1] ... data[2] */ |
17 | static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen) | 21 | static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen) |
18 | { | 22 | { |
@@ -32,7 +36,7 @@ static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen) | |||
32 | } | 36 | } |
33 | 37 | ||
34 | /* expecting tx buffer: request data[0] ... data[n] (n <= 4) */ | 38 | /* expecting tx buffer: request data[0] ... data[n] (n <= 4) */ |
35 | static int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen) | 39 | int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen) |
36 | { | 40 | { |
37 | u16 index, value; | 41 | u16 index, value; |
38 | int status; | 42 | int status; |
@@ -260,14 +264,29 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
260 | return dib0700_ctrl_wr(adap->dev, b, 4); | 264 | return dib0700_ctrl_wr(adap->dev, b, 4); |
261 | } | 265 | } |
262 | 266 | ||
267 | static int dib0700_rc_setup(struct dvb_usb_device *d) | ||
268 | { | ||
269 | u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0}; | ||
270 | int i = dib0700_ctrl_wr(d, rc_setup, 3); | ||
271 | if (i<0) { | ||
272 | err("ir protocol setup failed"); | ||
273 | return -1; | ||
274 | } | ||
275 | return 0; | ||
276 | } | ||
277 | |||
263 | static int dib0700_probe(struct usb_interface *intf, | 278 | static int dib0700_probe(struct usb_interface *intf, |
264 | const struct usb_device_id *id) | 279 | const struct usb_device_id *id) |
265 | { | 280 | { |
266 | int i; | 281 | int i; |
282 | struct dvb_usb_device *dev; | ||
267 | 283 | ||
268 | for (i = 0; i < dib0700_device_count; i++) | 284 | for (i = 0; i < dib0700_device_count; i++) |
269 | if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, NULL) == 0) | 285 | if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, &dev) == 0) |
286 | { | ||
287 | dib0700_rc_setup(dev); | ||
270 | return 0; | 288 | return 0; |
289 | } | ||
271 | 290 | ||
272 | return -ENODEV; | 291 | return -ENODEV; |
273 | } | 292 | } |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 2208757d9017..e8c4a8694532 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * under the terms of the GNU General Public License as published by the Free | 4 | * under the terms of the GNU General Public License as published by the Free |
5 | * Software Foundation, version 2. | 5 | * Software Foundation, version 2. |
6 | * | 6 | * |
7 | * Copyright (C) 2005-6 DiBcom, SA | 7 | * Copyright (C) 2005-7 DiBcom, SA |
8 | */ | 8 | */ |
9 | #include "dib0700.h" | 9 | #include "dib0700.h" |
10 | 10 | ||
@@ -12,13 +12,19 @@ | |||
12 | #include "dib7000m.h" | 12 | #include "dib7000m.h" |
13 | #include "dib7000p.h" | 13 | #include "dib7000p.h" |
14 | #include "mt2060.h" | 14 | #include "mt2060.h" |
15 | #include "mt2266.h" | ||
16 | #include "dib0070.h" | ||
15 | 17 | ||
16 | static int force_lna_activation; | 18 | static int force_lna_activation; |
17 | module_param(force_lna_activation, int, 0644); | 19 | module_param(force_lna_activation, int, 0644); |
18 | MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), " | 20 | MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), " |
19 | "if applicable for the device (default: 0=automatic/off)."); | 21 | "if applicable for the device (default: 0=automatic/off)."); |
20 | 22 | ||
21 | /* Hauppauge Nova-T 500 | 23 | struct dib0700_adapter_state { |
24 | int (*set_param_save) (struct dvb_frontend *, struct dvb_frontend_parameters *); | ||
25 | }; | ||
26 | |||
27 | /* Hauppauge Nova-T 500 (aka Bristol) | ||
22 | * has a LNA on GPIO0 which is enabled by setting 1 */ | 28 | * has a LNA on GPIO0 which is enabled by setting 1 */ |
23 | static struct mt2060_config bristol_mt2060_config[2] = { | 29 | static struct mt2060_config bristol_mt2060_config[2] = { |
24 | { | 30 | { |
@@ -96,6 +102,321 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap) | |||
96 | st->mt2060_if1[adap->id]) == NULL ? -ENODEV : 0; | 102 | st->mt2060_if1[adap->id]) == NULL ? -ENODEV : 0; |
97 | } | 103 | } |
98 | 104 | ||
105 | /* STK7700D: Pinnacle/Terratec/Hauppauge Dual DVB-T Diversity */ | ||
106 | |||
107 | /* MT226x */ | ||
108 | static struct dibx000_agc_config stk7700d_7000p_mt2266_agc_config[2] = { | ||
109 | { | ||
110 | BAND_UHF, // band_caps | ||
111 | |||
112 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1, | ||
113 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | ||
114 | (0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup | ||
115 | |||
116 | 1130, // inv_gain | ||
117 | 21, // time_stabiliz | ||
118 | |||
119 | 0, // alpha_level | ||
120 | 118, // thlock | ||
121 | |||
122 | 0, // wbd_inv | ||
123 | 3530, // wbd_ref | ||
124 | 1, // wbd_sel | ||
125 | 0, // wbd_alpha | ||
126 | |||
127 | 65535, // agc1_max | ||
128 | 33770, // agc1_min | ||
129 | 65535, // agc2_max | ||
130 | 23592, // agc2_min | ||
131 | |||
132 | 0, // agc1_pt1 | ||
133 | 62, // agc1_pt2 | ||
134 | 255, // agc1_pt3 | ||
135 | 64, // agc1_slope1 | ||
136 | 64, // agc1_slope2 | ||
137 | 132, // agc2_pt1 | ||
138 | 192, // agc2_pt2 | ||
139 | 80, // agc2_slope1 | ||
140 | 80, // agc2_slope2 | ||
141 | |||
142 | 17, // alpha_mant | ||
143 | 27, // alpha_exp | ||
144 | 23, // beta_mant | ||
145 | 51, // beta_exp | ||
146 | |||
147 | 1, // perform_agc_softsplit | ||
148 | }, { | ||
149 | BAND_VHF | BAND_LBAND, // band_caps | ||
150 | |||
151 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1, | ||
152 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | ||
153 | (0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup | ||
154 | |||
155 | 2372, // inv_gain | ||
156 | 21, // time_stabiliz | ||
157 | |||
158 | 0, // alpha_level | ||
159 | 118, // thlock | ||
160 | |||
161 | 0, // wbd_inv | ||
162 | 3530, // wbd_ref | ||
163 | 1, // wbd_sel | ||
164 | 0, // wbd_alpha | ||
165 | |||
166 | 65535, // agc1_max | ||
167 | 0, // agc1_min | ||
168 | 65535, // agc2_max | ||
169 | 23592, // agc2_min | ||
170 | |||
171 | 0, // agc1_pt1 | ||
172 | 128, // agc1_pt2 | ||
173 | 128, // agc1_pt3 | ||
174 | 128, // agc1_slope1 | ||
175 | 0, // agc1_slope2 | ||
176 | 128, // agc2_pt1 | ||
177 | 253, // agc2_pt2 | ||
178 | 81, // agc2_slope1 | ||
179 | 0, // agc2_slope2 | ||
180 | |||
181 | 17, // alpha_mant | ||
182 | 27, // alpha_exp | ||
183 | 23, // beta_mant | ||
184 | 51, // beta_exp | ||
185 | |||
186 | 1, // perform_agc_softsplit | ||
187 | } | ||
188 | }; | ||
189 | |||
190 | static struct dibx000_bandwidth_config stk7700d_mt2266_pll_config = { | ||
191 | 60000, 30000, // internal, sampling | ||
192 | 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass | ||
193 | 0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo | ||
194 | (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k | ||
195 | 0, // ifreq | ||
196 | 20452225, // timf | ||
197 | }; | ||
198 | |||
199 | static struct dib7000p_config stk7700d_dib7000p_mt2266_config[] = { | ||
200 | { .output_mpeg2_in_188_bytes = 1, | ||
201 | .hostbus_diversity = 1, | ||
202 | .tuner_is_baseband = 1, | ||
203 | |||
204 | .agc_config_count = 2, | ||
205 | .agc = stk7700d_7000p_mt2266_agc_config, | ||
206 | .bw = &stk7700d_mt2266_pll_config, | ||
207 | |||
208 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
209 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
210 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
211 | }, | ||
212 | { .output_mpeg2_in_188_bytes = 1, | ||
213 | .hostbus_diversity = 1, | ||
214 | .tuner_is_baseband = 1, | ||
215 | |||
216 | .agc_config_count = 2, | ||
217 | .agc = stk7700d_7000p_mt2266_agc_config, | ||
218 | .bw = &stk7700d_mt2266_pll_config, | ||
219 | |||
220 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
221 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
222 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
223 | } | ||
224 | }; | ||
225 | |||
226 | static struct mt2266_config stk7700d_mt2266_config[2] = { | ||
227 | { .i2c_address = 0x60 | ||
228 | }, | ||
229 | { .i2c_address = 0x60 | ||
230 | } | ||
231 | }; | ||
232 | |||
233 | static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap) | ||
234 | { | ||
235 | if (adap->id == 0) { | ||
236 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
237 | msleep(10); | ||
238 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
239 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
240 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
241 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
242 | msleep(10); | ||
243 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
244 | msleep(10); | ||
245 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
246 | dib7000p_i2c_enumeration(&adap->dev->i2c_adap,2,18,stk7700d_dib7000p_mt2266_config); | ||
247 | } | ||
248 | |||
249 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1), | ||
250 | &stk7700d_dib7000p_mt2266_config[adap->id]); | ||
251 | |||
252 | return adap->fe == NULL ? -ENODEV : 0; | ||
253 | } | ||
254 | |||
255 | static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap) | ||
256 | { | ||
257 | struct i2c_adapter *tun_i2c; | ||
258 | tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
259 | return dvb_attach(mt2266_attach, adap->fe, tun_i2c, | ||
260 | &stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;; | ||
261 | } | ||
262 | |||
263 | #define DEFAULT_RC_INTERVAL 150 | ||
264 | |||
265 | static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; | ||
266 | |||
267 | static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
268 | { | ||
269 | u8 key[4]; | ||
270 | int i; | ||
271 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | ||
272 | struct dib0700_state *st = d->priv; | ||
273 | *event = 0; | ||
274 | *state = REMOTE_NO_KEY_PRESSED; | ||
275 | i=dib0700_ctrl_rd(d,rc_request,2,key,4); | ||
276 | if (i<=0) { | ||
277 | err("RC Query Failed"); | ||
278 | return -1; | ||
279 | } | ||
280 | if (key[0]==0 && key[1]==0 && key[2]==0 && key[3]==0) return 0; | ||
281 | if (key[3-1]!=st->rc_toggle) { | ||
282 | for (i=0;i<d->props.rc_key_map_size; i++) { | ||
283 | if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) { | ||
284 | *event = keymap[i].event; | ||
285 | *state = REMOTE_KEY_PRESSED; | ||
286 | st->rc_toggle=key[3-1]; | ||
287 | return 0; | ||
288 | } | ||
289 | } | ||
290 | err("Unknown remote controller key : %2X %2X",(int)key[3-2],(int)key[3-3]); | ||
291 | } | ||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static struct dvb_usb_rc_key dib0700_rc_keys[] = { | ||
296 | /* Key codes for the tiny Pinnacle remote*/ | ||
297 | { 0x07, 0x00, KEY_MUTE }, | ||
298 | { 0x07, 0x01, KEY_MENU }, // Pinnacle logo | ||
299 | { 0x07, 0x39, KEY_POWER }, | ||
300 | { 0x07, 0x03, KEY_VOLUMEUP }, | ||
301 | { 0x07, 0x09, KEY_VOLUMEDOWN }, | ||
302 | { 0x07, 0x06, KEY_CHANNELUP }, | ||
303 | { 0x07, 0x0c, KEY_CHANNELDOWN }, | ||
304 | { 0x07, 0x0f, KEY_1 }, | ||
305 | { 0x07, 0x15, KEY_2 }, | ||
306 | { 0x07, 0x10, KEY_3 }, | ||
307 | { 0x07, 0x18, KEY_4 }, | ||
308 | { 0x07, 0x1b, KEY_5 }, | ||
309 | { 0x07, 0x1e, KEY_6 }, | ||
310 | { 0x07, 0x11, KEY_7 }, | ||
311 | { 0x07, 0x21, KEY_8 }, | ||
312 | { 0x07, 0x12, KEY_9 }, | ||
313 | { 0x07, 0x27, KEY_0 }, | ||
314 | { 0x07, 0x24, KEY_SCREEN }, // 'Square' key | ||
315 | { 0x07, 0x2a, KEY_TEXT }, // 'T' key | ||
316 | { 0x07, 0x2d, KEY_REWIND }, | ||
317 | { 0x07, 0x30, KEY_PLAY }, | ||
318 | { 0x07, 0x33, KEY_FASTFORWARD }, | ||
319 | { 0x07, 0x36, KEY_RECORD }, | ||
320 | { 0x07, 0x3c, KEY_STOP }, | ||
321 | { 0x07, 0x3f, KEY_CANCEL }, // '?' key | ||
322 | /* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */ | ||
323 | { 0xeb, 0x01, KEY_POWER }, | ||
324 | { 0xeb, 0x02, KEY_1 }, | ||
325 | { 0xeb, 0x03, KEY_2 }, | ||
326 | { 0xeb, 0x04, KEY_3 }, | ||
327 | { 0xeb, 0x05, KEY_4 }, | ||
328 | { 0xeb, 0x06, KEY_5 }, | ||
329 | { 0xeb, 0x07, KEY_6 }, | ||
330 | { 0xeb, 0x08, KEY_7 }, | ||
331 | { 0xeb, 0x09, KEY_8 }, | ||
332 | { 0xeb, 0x0a, KEY_9 }, | ||
333 | { 0xeb, 0x0b, KEY_VIDEO }, | ||
334 | { 0xeb, 0x0c, KEY_0 }, | ||
335 | { 0xeb, 0x0d, KEY_REFRESH }, | ||
336 | { 0xeb, 0x0f, KEY_EPG }, | ||
337 | { 0xeb, 0x10, KEY_UP }, | ||
338 | { 0xeb, 0x11, KEY_LEFT }, | ||
339 | { 0xeb, 0x12, KEY_OK }, | ||
340 | { 0xeb, 0x13, KEY_RIGHT }, | ||
341 | { 0xeb, 0x14, KEY_DOWN }, | ||
342 | { 0xeb, 0x16, KEY_INFO }, | ||
343 | { 0xeb, 0x17, KEY_RED }, | ||
344 | { 0xeb, 0x18, KEY_GREEN }, | ||
345 | { 0xeb, 0x19, KEY_YELLOW }, | ||
346 | { 0xeb, 0x1a, KEY_BLUE }, | ||
347 | { 0xeb, 0x1b, KEY_CHANNELUP }, | ||
348 | { 0xeb, 0x1c, KEY_VOLUMEUP }, | ||
349 | { 0xeb, 0x1d, KEY_MUTE }, | ||
350 | { 0xeb, 0x1e, KEY_VOLUMEDOWN }, | ||
351 | { 0xeb, 0x1f, KEY_CHANNELDOWN }, | ||
352 | { 0xeb, 0x40, KEY_PAUSE }, | ||
353 | { 0xeb, 0x41, KEY_HOME }, | ||
354 | { 0xeb, 0x42, KEY_MENU }, /* DVD Menu */ | ||
355 | { 0xeb, 0x43, KEY_SUBTITLE }, | ||
356 | { 0xeb, 0x44, KEY_TEXT }, /* Teletext */ | ||
357 | { 0xeb, 0x45, KEY_DELETE }, | ||
358 | { 0xeb, 0x46, KEY_TV }, | ||
359 | { 0xeb, 0x47, KEY_DVD }, | ||
360 | { 0xeb, 0x48, KEY_STOP }, | ||
361 | { 0xeb, 0x49, KEY_VIDEO }, | ||
362 | { 0xeb, 0x4a, KEY_AUDIO }, /* Music */ | ||
363 | { 0xeb, 0x4b, KEY_SCREEN }, /* Pic */ | ||
364 | { 0xeb, 0x4c, KEY_PLAY }, | ||
365 | { 0xeb, 0x4d, KEY_BACK }, | ||
366 | { 0xeb, 0x4e, KEY_REWIND }, | ||
367 | { 0xeb, 0x4f, KEY_FASTFORWARD }, | ||
368 | { 0xeb, 0x54, KEY_PREVIOUS }, | ||
369 | { 0xeb, 0x58, KEY_RECORD }, | ||
370 | { 0xeb, 0x5c, KEY_NEXT }, | ||
371 | |||
372 | /* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */ | ||
373 | { 0x1e, 0x00, KEY_0 }, | ||
374 | { 0x1e, 0x01, KEY_1 }, | ||
375 | { 0x1e, 0x02, KEY_2 }, | ||
376 | { 0x1e, 0x03, KEY_3 }, | ||
377 | { 0x1e, 0x04, KEY_4 }, | ||
378 | { 0x1e, 0x05, KEY_5 }, | ||
379 | { 0x1e, 0x06, KEY_6 }, | ||
380 | { 0x1e, 0x07, KEY_7 }, | ||
381 | { 0x1e, 0x08, KEY_8 }, | ||
382 | { 0x1e, 0x09, KEY_9 }, | ||
383 | { 0x1e, 0x0a, KEY_KPASTERISK }, | ||
384 | { 0x1e, 0x0b, KEY_RED }, | ||
385 | { 0x1e, 0x0c, KEY_RADIO }, | ||
386 | { 0x1e, 0x0d, KEY_MENU }, | ||
387 | { 0x1e, 0x0e, KEY_GRAVE }, /* # */ | ||
388 | { 0x1e, 0x0f, KEY_MUTE }, | ||
389 | { 0x1e, 0x10, KEY_VOLUMEUP }, | ||
390 | { 0x1e, 0x11, KEY_VOLUMEDOWN }, | ||
391 | { 0x1e, 0x12, KEY_CHANNEL }, | ||
392 | { 0x1e, 0x14, KEY_UP }, | ||
393 | { 0x1e, 0x15, KEY_DOWN }, | ||
394 | { 0x1e, 0x16, KEY_LEFT }, | ||
395 | { 0x1e, 0x17, KEY_RIGHT }, | ||
396 | { 0x1e, 0x18, KEY_VIDEO }, | ||
397 | { 0x1e, 0x19, KEY_AUDIO }, | ||
398 | { 0x1e, 0x1a, KEY_MEDIA }, | ||
399 | { 0x1e, 0x1b, KEY_EPG }, | ||
400 | { 0x1e, 0x1c, KEY_TV }, | ||
401 | { 0x1e, 0x1e, KEY_NEXT }, | ||
402 | { 0x1e, 0x1f, KEY_BACK }, | ||
403 | { 0x1e, 0x20, KEY_CHANNELUP }, | ||
404 | { 0x1e, 0x21, KEY_CHANNELDOWN }, | ||
405 | { 0x1e, 0x24, KEY_LAST }, /* Skip backwards */ | ||
406 | { 0x1e, 0x25, KEY_OK }, | ||
407 | { 0x1e, 0x29, KEY_BLUE}, | ||
408 | { 0x1e, 0x2e, KEY_GREEN }, | ||
409 | { 0x1e, 0x30, KEY_PAUSE }, | ||
410 | { 0x1e, 0x32, KEY_REWIND }, | ||
411 | { 0x1e, 0x34, KEY_FASTFORWARD }, | ||
412 | { 0x1e, 0x35, KEY_PLAY }, | ||
413 | { 0x1e, 0x36, KEY_STOP }, | ||
414 | { 0x1e, 0x37, KEY_RECORD }, | ||
415 | { 0x1e, 0x38, KEY_YELLOW }, | ||
416 | { 0x1e, 0x3b, KEY_GOTO }, | ||
417 | { 0x1e, 0x3d, KEY_POWER }, | ||
418 | }; | ||
419 | |||
99 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ | 420 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ |
100 | static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = { | 421 | static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = { |
101 | BAND_UHF | BAND_VHF, // band_caps | 422 | BAND_UHF | BAND_VHF, // band_caps |
@@ -194,6 +515,7 @@ static struct dibx000_bandwidth_config stk7700p_pll_config = { | |||
194 | (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k | 515 | (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k |
195 | 60258167, // ifreq | 516 | 60258167, // ifreq |
196 | 20452225, // timf | 517 | 20452225, // timf |
518 | 30000000, // xtal | ||
197 | }; | 519 | }; |
198 | 520 | ||
199 | static struct dib7000m_config stk7700p_dib7000m_config = { | 521 | static struct dib7000m_config stk7700p_dib7000m_config = { |
@@ -213,6 +535,7 @@ static struct dib7000m_config stk7700p_dib7000m_config = { | |||
213 | static struct dib7000p_config stk7700p_dib7000p_config = { | 535 | static struct dib7000p_config stk7700p_dib7000p_config = { |
214 | .output_mpeg2_in_188_bytes = 1, | 536 | .output_mpeg2_in_188_bytes = 1, |
215 | 537 | ||
538 | .agc_config_count = 1, | ||
216 | .agc = &stk7700p_7000p_mt2060_agc_config, | 539 | .agc = &stk7700p_7000p_mt2060_agc_config, |
217 | .bw = &stk7700p_pll_config, | 540 | .bw = &stk7700p_pll_config, |
218 | 541 | ||
@@ -267,27 +590,245 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) | |||
267 | st->mt2060_if1[0]) == NULL ? -ENODEV : 0; | 590 | st->mt2060_if1[0]) == NULL ? -ENODEV : 0; |
268 | } | 591 | } |
269 | 592 | ||
593 | /* DIB7070 generic */ | ||
594 | static struct dibx000_agc_config dib7070_agc_config = { | ||
595 | BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, | ||
596 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | ||
597 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ | ||
598 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup | ||
599 | |||
600 | 600, // inv_gain | ||
601 | 10, // time_stabiliz | ||
602 | |||
603 | 0, // alpha_level | ||
604 | 118, // thlock | ||
605 | |||
606 | 0, // wbd_inv | ||
607 | 3530, // wbd_ref | ||
608 | 1, // wbd_sel | ||
609 | 5, // wbd_alpha | ||
610 | |||
611 | 65535, // agc1_max | ||
612 | 0, // agc1_min | ||
613 | |||
614 | 65535, // agc2_max | ||
615 | 0, // agc2_min | ||
616 | |||
617 | 0, // agc1_pt1 | ||
618 | 40, // agc1_pt2 | ||
619 | 183, // agc1_pt3 | ||
620 | 206, // agc1_slope1 | ||
621 | 255, // agc1_slope2 | ||
622 | 72, // agc2_pt1 | ||
623 | 152, // agc2_pt2 | ||
624 | 88, // agc2_slope1 | ||
625 | 90, // agc2_slope2 | ||
626 | |||
627 | 17, // alpha_mant | ||
628 | 27, // alpha_exp | ||
629 | 23, // beta_mant | ||
630 | 51, // beta_exp | ||
631 | |||
632 | 0, // perform_agc_softsplit | ||
633 | }; | ||
634 | |||
635 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) | ||
636 | { | ||
637 | return dib7000p_set_gpio(fe, 8, 0, !onoff); | ||
638 | } | ||
639 | |||
640 | static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) | ||
641 | { | ||
642 | return dib7000p_set_gpio(fe, 9, 0, onoff); | ||
643 | } | ||
644 | |||
645 | static struct dib0070_config dib7070p_dib0070_config[2] = { | ||
646 | { | ||
647 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | ||
648 | .reset = dib7070_tuner_reset, | ||
649 | .sleep = dib7070_tuner_sleep, | ||
650 | .clock_khz = 12000, | ||
651 | .clock_pad_drive = 4 | ||
652 | }, { | ||
653 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | ||
654 | .reset = dib7070_tuner_reset, | ||
655 | .sleep = dib7070_tuner_sleep, | ||
656 | .clock_khz = 12000, | ||
657 | |||
658 | } | ||
659 | }; | ||
660 | |||
661 | static int dib7070_set_param_override(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) | ||
662 | { | ||
663 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
664 | struct dib0700_adapter_state *state = adap->priv; | ||
665 | |||
666 | u16 offset; | ||
667 | u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); | ||
668 | switch (band) { | ||
669 | case BAND_VHF: offset = 950; break; | ||
670 | case BAND_UHF: | ||
671 | default: offset = 550; break; | ||
672 | } | ||
673 | deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe)); | ||
674 | dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); | ||
675 | return state->set_param_save(fe, fep); | ||
676 | } | ||
677 | |||
678 | static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap) | ||
679 | { | ||
680 | struct dib0700_adapter_state *st = adap->priv; | ||
681 | struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
682 | |||
683 | if (adap->id == 0) { | ||
684 | if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL) | ||
685 | return -ENODEV; | ||
686 | } else { | ||
687 | if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL) | ||
688 | return -ENODEV; | ||
689 | } | ||
690 | |||
691 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
692 | adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override; | ||
693 | return 0; | ||
694 | } | ||
695 | |||
696 | static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = { | ||
697 | 60000, 15000, // internal, sampling | ||
698 | 1, 20, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass | ||
699 | 0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo | ||
700 | (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k | ||
701 | (0 << 25) | 0, // ifreq = 0.000000 MHz | ||
702 | 20452225, // timf | ||
703 | 12000000, // xtal_hz | ||
704 | }; | ||
705 | |||
706 | static struct dib7000p_config dib7070p_dib7000p_config = { | ||
707 | .output_mpeg2_in_188_bytes = 1, | ||
708 | |||
709 | .agc_config_count = 1, | ||
710 | .agc = &dib7070_agc_config, | ||
711 | .bw = &dib7070_bw_config_12_mhz, | ||
712 | |||
713 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
714 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
715 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
716 | |||
717 | .hostbus_diversity = 1, | ||
718 | }; | ||
719 | |||
720 | /* STK7070P */ | ||
721 | static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) | ||
722 | { | ||
723 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
724 | msleep(10); | ||
725 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
726 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
727 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
728 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
729 | |||
730 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
731 | |||
732 | msleep(10); | ||
733 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
734 | msleep(10); | ||
735 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
736 | |||
737 | dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, &dib7070p_dib7000p_config); | ||
738 | |||
739 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &dib7070p_dib7000p_config); | ||
740 | return adap->fe == NULL ? -ENODEV : 0; | ||
741 | } | ||
742 | |||
743 | /* STK7070PD */ | ||
744 | static struct dib7000p_config stk7070pd_dib7000p_config[2] = { | ||
745 | { | ||
746 | .output_mpeg2_in_188_bytes = 1, | ||
747 | |||
748 | .agc_config_count = 1, | ||
749 | .agc = &dib7070_agc_config, | ||
750 | .bw = &dib7070_bw_config_12_mhz, | ||
751 | |||
752 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
753 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
754 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
755 | |||
756 | .hostbus_diversity = 1, | ||
757 | }, { | ||
758 | .output_mpeg2_in_188_bytes = 1, | ||
759 | |||
760 | .agc_config_count = 1, | ||
761 | .agc = &dib7070_agc_config, | ||
762 | .bw = &dib7070_bw_config_12_mhz, | ||
763 | |||
764 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
765 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
766 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
767 | |||
768 | .hostbus_diversity = 1, | ||
769 | } | ||
770 | }; | ||
771 | |||
772 | static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap) | ||
773 | { | ||
774 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
775 | msleep(10); | ||
776 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
777 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
778 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
779 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
780 | |||
781 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
782 | |||
783 | msleep(10); | ||
784 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
785 | msleep(10); | ||
786 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
787 | |||
788 | dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, stk7070pd_dib7000p_config); | ||
789 | |||
790 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]); | ||
791 | return adap->fe == NULL ? -ENODEV : 0; | ||
792 | } | ||
793 | |||
794 | static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap) | ||
795 | { | ||
796 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]); | ||
797 | return adap->fe == NULL ? -ENODEV : 0; | ||
798 | } | ||
799 | |||
800 | /* DVB-USB and USB stuff follows */ | ||
270 | struct usb_device_id dib0700_usb_id_table[] = { | 801 | struct usb_device_id dib0700_usb_id_table[] = { |
271 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, | 802 | /* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, |
272 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, | 803 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, |
273 | 804 | ||
274 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, | 805 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, |
275 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, | 806 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, |
276 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, | 807 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, |
277 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, | 808 | /* 5 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, |
278 | { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, | 809 | { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, |
279 | { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, | 810 | { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, |
280 | { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) }, | 811 | { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) }, |
281 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) }, | 812 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) }, |
282 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) }, | 813 | /* 10 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) }, |
283 | { } /* Terminating entry */ | 814 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV2000E) }, |
815 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) }, | ||
816 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) }, | ||
817 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700D) }, | ||
818 | /* 15 */{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070P) }, | ||
819 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DVB_T_FLASH) }, | ||
820 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070PD) }, | ||
821 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) }, | ||
822 | { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500_PC) }, | ||
823 | /* 20 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_EXPRESS) }, | ||
824 | { 0 } /* Terminating entry */ | ||
284 | }; | 825 | }; |
285 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 826 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
286 | 827 | ||
287 | #define DIB0700_DEFAULT_DEVICE_PROPERTIES \ | 828 | #define DIB0700_DEFAULT_DEVICE_PROPERTIES \ |
288 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ | 829 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ |
289 | .usb_ctrl = DEVICE_SPECIFIC, \ | 830 | .usb_ctrl = DEVICE_SPECIFIC, \ |
290 | .firmware = "dvb-usb-dib0700-01.fw", \ | 831 | .firmware = "dvb-usb-dib0700-03-pre1.fw", \ |
291 | .download_firmware = dib0700_download_firmware, \ | 832 | .download_firmware = dib0700_download_firmware, \ |
292 | .no_reconnect = 1, \ | 833 | .no_reconnect = 1, \ |
293 | .size_of_priv = sizeof(struct dib0700_state), \ | 834 | .size_of_priv = sizeof(struct dib0700_state), \ |
@@ -321,7 +862,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
321 | }, | 862 | }, |
322 | }, | 863 | }, |
323 | 864 | ||
324 | .num_device_descs = 6, | 865 | .num_device_descs = 7, |
325 | .devices = { | 866 | .devices = { |
326 | { "DiBcom STK7700P reference design", | 867 | { "DiBcom STK7700P reference design", |
327 | { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] }, | 868 | { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] }, |
@@ -336,7 +877,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
336 | { NULL }, | 877 | { NULL }, |
337 | }, | 878 | }, |
338 | { "Compro Videomate U500", | 879 | { "Compro Videomate U500", |
339 | { &dib0700_usb_id_table[6], NULL }, | 880 | { &dib0700_usb_id_table[6], &dib0700_usb_id_table[19] }, |
340 | { NULL }, | 881 | { NULL }, |
341 | }, | 882 | }, |
342 | { "Uniwill STK7700P based (Hama and others)", | 883 | { "Uniwill STK7700P based (Hama and others)", |
@@ -346,8 +887,17 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
346 | { "Leadtek Winfast DTV Dongle (STK7700P based)", | 887 | { "Leadtek Winfast DTV Dongle (STK7700P based)", |
347 | { &dib0700_usb_id_table[8], NULL }, | 888 | { &dib0700_usb_id_table[8], NULL }, |
348 | { NULL }, | 889 | { NULL }, |
890 | }, | ||
891 | { "AVerMedia AVerTV DVB-T Express", | ||
892 | { &dib0700_usb_id_table[20] }, | ||
893 | { NULL }, | ||
349 | } | 894 | } |
350 | } | 895 | }, |
896 | |||
897 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
898 | .rc_key_map = dib0700_rc_keys, | ||
899 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | ||
900 | .rc_query = dib0700_rc_query | ||
351 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 901 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
352 | 902 | ||
353 | .num_adapters = 2, | 903 | .num_adapters = 2, |
@@ -371,8 +921,112 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
371 | { &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL }, | 921 | { &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL }, |
372 | { NULL }, | 922 | { NULL }, |
373 | }, | 923 | }, |
924 | }, | ||
925 | |||
926 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
927 | .rc_key_map = dib0700_rc_keys, | ||
928 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | ||
929 | .rc_query = dib0700_rc_query | ||
930 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
931 | |||
932 | .num_adapters = 2, | ||
933 | .adapter = { | ||
934 | { | ||
935 | .frontend_attach = stk7700d_frontend_attach, | ||
936 | .tuner_attach = stk7700d_tuner_attach, | ||
937 | |||
938 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
939 | }, { | ||
940 | .frontend_attach = stk7700d_frontend_attach, | ||
941 | .tuner_attach = stk7700d_tuner_attach, | ||
942 | |||
943 | DIB0700_DEFAULT_STREAMING_CONFIG(0x03), | ||
944 | } | ||
945 | }, | ||
946 | |||
947 | .num_device_descs = 4, | ||
948 | .devices = { | ||
949 | { "Pinnacle PCTV 2000e", | ||
950 | { &dib0700_usb_id_table[11], NULL }, | ||
951 | { NULL }, | ||
952 | }, | ||
953 | { "Terratec Cinergy DT XS Diversity", | ||
954 | { &dib0700_usb_id_table[12], NULL }, | ||
955 | { NULL }, | ||
956 | }, | ||
957 | { "Hauppauge Nova-TD Stick/Elgato Eye-TV Diversity", | ||
958 | { &dib0700_usb_id_table[13], NULL }, | ||
959 | { NULL }, | ||
960 | }, | ||
961 | { "DiBcom STK7700D reference design", | ||
962 | { &dib0700_usb_id_table[14], NULL }, | ||
963 | { NULL }, | ||
964 | }, | ||
965 | }, | ||
966 | |||
967 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
968 | .rc_key_map = dib0700_rc_keys, | ||
969 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | ||
970 | .rc_query = dib0700_rc_query | ||
971 | |||
972 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
973 | |||
974 | .num_adapters = 1, | ||
975 | .adapter = { | ||
976 | { | ||
977 | .frontend_attach = stk7070p_frontend_attach, | ||
978 | .tuner_attach = dib7070p_tuner_attach, | ||
979 | |||
980 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
981 | |||
982 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
983 | }, | ||
984 | }, | ||
985 | |||
986 | .num_device_descs = 2, | ||
987 | .devices = { | ||
988 | { "DiBcom STK7070P reference design", | ||
989 | { &dib0700_usb_id_table[15], NULL }, | ||
990 | { NULL }, | ||
991 | }, | ||
992 | { "Pinnacle PCTV DVB-T Flash Stick", | ||
993 | { &dib0700_usb_id_table[16], NULL }, | ||
994 | { NULL }, | ||
995 | }, | ||
374 | } | 996 | } |
375 | } | 997 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
998 | |||
999 | .num_adapters = 2, | ||
1000 | .adapter = { | ||
1001 | { | ||
1002 | .frontend_attach = stk7070pd_frontend_attach0, | ||
1003 | .tuner_attach = dib7070p_tuner_attach, | ||
1004 | |||
1005 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
1006 | |||
1007 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
1008 | }, { | ||
1009 | .frontend_attach = stk7070pd_frontend_attach1, | ||
1010 | .tuner_attach = dib7070p_tuner_attach, | ||
1011 | |||
1012 | DIB0700_DEFAULT_STREAMING_CONFIG(0x03), | ||
1013 | |||
1014 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
1015 | } | ||
1016 | }, | ||
1017 | |||
1018 | .num_device_descs = 2, | ||
1019 | .devices = { | ||
1020 | { "DiBcom STK7070PD reference design", | ||
1021 | { &dib0700_usb_id_table[17], NULL }, | ||
1022 | { NULL }, | ||
1023 | }, | ||
1024 | { "Pinnacle PCTV Dual DVB-T Diversity Stick", | ||
1025 | { &dib0700_usb_id_table[18], NULL }, | ||
1026 | { NULL }, | ||
1027 | }, | ||
1028 | } | ||
1029 | }, | ||
376 | }; | 1030 | }; |
377 | 1031 | ||
378 | int dib0700_device_count = ARRAY_SIZE(dib0700_devices); | 1032 | int dib0700_device_count = ARRAY_SIZE(dib0700_devices); |
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c index 7dbe14321019..d86cf9bee91c 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/drivers/media/dvb/dvb-usb/dtt200u.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/ | 1 | /* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/ |
2 | * Typhoon/ Yuan DVB-T USB2.0 receiver. | 2 | * Typhoon/ Yuan/ Miglia DVB-T USB2.0 receiver. |
3 | * | 3 | * |
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | 4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) |
5 | * | 5 | * |
@@ -96,6 +96,7 @@ static struct dvb_usb_device_properties dtt200u_properties; | |||
96 | static struct dvb_usb_device_properties wt220u_fc_properties; | 96 | static struct dvb_usb_device_properties wt220u_fc_properties; |
97 | static struct dvb_usb_device_properties wt220u_properties; | 97 | static struct dvb_usb_device_properties wt220u_properties; |
98 | static struct dvb_usb_device_properties wt220u_zl0353_properties; | 98 | static struct dvb_usb_device_properties wt220u_zl0353_properties; |
99 | static struct dvb_usb_device_properties wt220u_miglia_properties; | ||
99 | 100 | ||
100 | static int dtt200u_usb_probe(struct usb_interface *intf, | 101 | static int dtt200u_usb_probe(struct usb_interface *intf, |
101 | const struct usb_device_id *id) | 102 | const struct usb_device_id *id) |
@@ -103,7 +104,8 @@ static int dtt200u_usb_probe(struct usb_interface *intf, | |||
103 | if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 || | 104 | if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 || |
104 | dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 || | 105 | dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 || |
105 | dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 || | 106 | dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 || |
106 | dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0) | 107 | dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0 || |
108 | dvb_usb_device_init(intf,&wt220u_miglia_properties,THIS_MODULE,NULL) == 0) | ||
107 | return 0; | 109 | return 0; |
108 | 110 | ||
109 | return -ENODEV; | 111 | return -ENODEV; |
@@ -119,6 +121,7 @@ static struct usb_device_id dtt200u_usb_table [] = { | |||
119 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_COLD) }, | 121 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_COLD) }, |
120 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_WARM) }, | 122 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_WARM) }, |
121 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZAP250_COLD) }, | 123 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZAP250_COLD) }, |
124 | { USB_DEVICE(USB_VID_MIGLIA, USB_PID_WT220U_ZAP250_COLD) }, | ||
122 | { 0 }, | 125 | { 0 }, |
123 | }; | 126 | }; |
124 | MODULE_DEVICE_TABLE(usb, dtt200u_usb_table); | 127 | MODULE_DEVICE_TABLE(usb, dtt200u_usb_table); |
@@ -303,6 +306,25 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = { | |||
303 | } | 306 | } |
304 | }; | 307 | }; |
305 | 308 | ||
309 | static struct dvb_usb_device_properties wt220u_miglia_properties = { | ||
310 | .usb_ctrl = CYPRESS_FX2, | ||
311 | .firmware = "dvb-usb-wt220u-miglia-01.fw", | ||
312 | |||
313 | .num_adapters = 1, | ||
314 | .generic_bulk_ctrl_endpoint = 0x01, | ||
315 | |||
316 | .num_device_descs = 1, | ||
317 | .devices = { | ||
318 | { .name = "WideView WT-220U PenType Receiver (Miglia)", | ||
319 | .cold_ids = { &dtt200u_usb_table[9], NULL }, | ||
320 | /* This device turns into WT220U_ZL0353_WARM when fw | ||
321 | has been uploaded */ | ||
322 | .warm_ids = { NULL }, | ||
323 | }, | ||
324 | { NULL }, | ||
325 | } | ||
326 | }; | ||
327 | |||
306 | /* usb specific object needed to register this driver with the usb subsystem */ | 328 | /* usb specific object needed to register this driver with the usb subsystem */ |
307 | static struct usb_driver dtt200u_usb_driver = { | 329 | static struct usb_driver dtt200u_usb_driver = { |
308 | .name = "dvb_usb_dtt200u", | 330 | .name = "dvb_usb_dtt200u", |
@@ -333,6 +355,6 @@ module_init(dtt200u_usb_module_init); | |||
333 | module_exit(dtt200u_usb_module_exit); | 355 | module_exit(dtt200u_usb_module_exit); |
334 | 356 | ||
335 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | 357 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); |
336 | MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D DVB-T USB2.0 devices"); | 358 | MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices"); |
337 | MODULE_VERSION("1.0"); | 359 | MODULE_VERSION("1.0"); |
338 | MODULE_LICENSE("GPL"); | 360 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 4dfab02a8a0d..4fa3e895028a 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -12,7 +12,7 @@ | |||
12 | /* Vendor IDs */ | 12 | /* Vendor IDs */ |
13 | #define USB_VID_ADSTECH 0x06e1 | 13 | #define USB_VID_ADSTECH 0x06e1 |
14 | #define USB_VID_AFATECH 0x15a4 | 14 | #define USB_VID_AFATECH 0x15a4 |
15 | #define USB_VID_ALCOR_MICRO 0x058f | 15 | #define USB_VID_ALCOR_MICRO 0x058f |
16 | #define USB_VID_ALINK 0x05e3 | 16 | #define USB_VID_ALINK 0x05e3 |
17 | #define USB_VID_ANCHOR 0x0547 | 17 | #define USB_VID_ANCHOR 0x0547 |
18 | #define USB_VID_ANUBIS_ELECTRONIC 0x10fd | 18 | #define USB_VID_ANUBIS_ELECTRONIC 0x10fd |
@@ -34,6 +34,7 @@ | |||
34 | #define USB_VID_LEADTEK 0x0413 | 34 | #define USB_VID_LEADTEK 0x0413 |
35 | #define USB_VID_LITEON 0x04ca | 35 | #define USB_VID_LITEON 0x04ca |
36 | #define USB_VID_MEDION 0x1660 | 36 | #define USB_VID_MEDION 0x1660 |
37 | #define USB_VID_MIGLIA 0x18f3 | ||
37 | #define USB_VID_MSI 0x0db0 | 38 | #define USB_VID_MSI 0x0db0 |
38 | #define USB_VID_OPERA1 0x695c | 39 | #define USB_VID_OPERA1 0x695c |
39 | #define USB_VID_PINNACLE 0x2304 | 40 | #define USB_VID_PINNACLE 0x2304 |
@@ -58,6 +59,7 @@ | |||
58 | #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c | 59 | #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c |
59 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d | 60 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d |
60 | #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 | 61 | #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 |
62 | #define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80 | ||
61 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 | 63 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 |
62 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 | 64 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 |
63 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 | 65 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 |
@@ -66,6 +68,9 @@ | |||
66 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 | 68 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 |
67 | #define USB_PID_DIBCOM_STK7700P 0x1e14 | 69 | #define USB_PID_DIBCOM_STK7700P 0x1e14 |
68 | #define USB_PID_DIBCOM_STK7700P_PC 0x1e78 | 70 | #define USB_PID_DIBCOM_STK7700P_PC 0x1e78 |
71 | #define USB_PID_DIBCOM_STK7700D 0x1ef0 | ||
72 | #define USB_PID_DIBCOM_STK7070P 0x1ebc | ||
73 | #define USB_PID_DIBCOM_STK7070PD 0x1ebe | ||
69 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 | 74 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 |
70 | #define USB_PID_DPOSH_M9206_COLD 0x9206 | 75 | #define USB_PID_DPOSH_M9206_COLD 0x9206 |
71 | #define USB_PID_DPOSH_M9206_WARM 0xa090 | 76 | #define USB_PID_DPOSH_M9206_WARM 0xa090 |
@@ -115,8 +120,17 @@ | |||
115 | #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 | 120 | #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 |
116 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 | 121 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 |
117 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060 | 122 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060 |
123 | #define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580 | ||
124 | #define USB_PID_AVERMEDIA_EXPRESS 0xb568 | ||
118 | #define USB_PID_AVERMEDIA_VOLAR 0xa807 | 125 | #define USB_PID_AVERMEDIA_VOLAR 0xa807 |
119 | #define USB_PID_AVERMEDIA_VOLAR_2 0xb808 | 126 | #define USB_PID_AVERMEDIA_VOLAR_2 0xb808 |
127 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a | ||
128 | #define USB_PID_PINNACLE_PCTV2000E 0x022c | ||
129 | #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 | ||
130 | #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229 | ||
131 | #define USB_PID_PCTV_200E 0x020e | ||
132 | #define USB_PID_PCTV_400E 0x020f | ||
133 | #define USB_PID_PCTV_450E 0x0222 | ||
120 | #define USB_PID_NEBULA_DIGITV 0x0201 | 134 | #define USB_PID_NEBULA_DIGITV 0x0201 |
121 | #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 | 135 | #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 |
122 | #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 | 136 | #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 |
@@ -136,9 +150,6 @@ | |||
136 | #define USB_PID_MSI_MEGASKY580_55801 0x5581 | 150 | #define USB_PID_MSI_MEGASKY580_55801 0x5581 |
137 | #define USB_PID_KYE_DVB_T_COLD 0x701e | 151 | #define USB_PID_KYE_DVB_T_COLD 0x701e |
138 | #define USB_PID_KYE_DVB_T_WARM 0x701f | 152 | #define USB_PID_KYE_DVB_T_WARM 0x701f |
139 | #define USB_PID_PCTV_200E 0x020e | ||
140 | #define USB_PID_PCTV_400E 0x020f | ||
141 | #define USB_PID_PCTV_450E 0x0222 | ||
142 | #define USB_PID_LITEON_DVB_T_COLD 0xf000 | 153 | #define USB_PID_LITEON_DVB_T_COLD 0xf000 |
143 | #define USB_PID_LITEON_DVB_T_WARM 0xf001 | 154 | #define USB_PID_LITEON_DVB_T_WARM 0xf001 |
144 | #define USB_PID_DIGIVOX_MINI_SL_COLD 0xe360 | 155 | #define USB_PID_DIGIVOX_MINI_SL_COLD 0xe360 |
@@ -148,8 +159,11 @@ | |||
148 | #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 | 159 | #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 |
149 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 | 160 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 |
150 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 | 161 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 |
151 | #define USB_PID_GENPIX_8PSK_COLD 0x0200 | 162 | #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 |
152 | #define USB_PID_GENPIX_8PSK_WARM 0x0201 | 163 | #define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201 |
164 | #define USB_PID_GENPIX_8PSK_REV_2 0x0202 | ||
165 | #define USB_PID_GENPIX_SKYWALKER_1 0x0203 | ||
166 | #define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204 | ||
153 | #define USB_PID_SIGMATEK_DVB_110 0x6610 | 167 | #define USB_PID_SIGMATEK_DVB_110 0x6610 |
154 | #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 | 168 | #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 |
155 | #define USB_PID_OPERA1_COLD 0x2830 | 169 | #define USB_PID_OPERA1_COLD 0x2830 |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c index ffdde83d1e77..cdd717c3fe45 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c | |||
@@ -24,7 +24,7 @@ MODULE_PARM_DESC(disable_rc_polling, "disable remote control polling (default: 0 | |||
24 | 24 | ||
25 | static int dvb_usb_force_pid_filter_usage; | 25 | static int dvb_usb_force_pid_filter_usage; |
26 | module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444); | 26 | module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444); |
27 | MODULE_PARM_DESC(disable_rc_polling, "force all dvb-usb-devices to use a PID filter, if any (default: 0)."); | 27 | MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0)."); |
28 | 28 | ||
29 | static int dvb_usb_adapter_init(struct dvb_usb_device *d) | 29 | static int dvb_usb_adapter_init(struct dvb_usb_device *d) |
30 | { | 30 | { |
diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c index 6ccbdc9cd772..e37142d9271a 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk-fe.c +++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* DVB USB compliant Linux driver for the | 1 | /* DVB USB compliant Linux driver for the |
2 | * - GENPIX 8pks/qpsk USB2.0 DVB-S module | 2 | * - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com) | 4 | * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com) |
5 | * Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com) | ||
5 | * | 6 | * |
6 | * Thanks to GENPIX for the sample code used to implement this module. | 7 | * Thanks to GENPIX for the sample code used to implement this module. |
7 | * | 8 | * |
@@ -17,27 +18,39 @@ | |||
17 | 18 | ||
18 | struct gp8psk_fe_state { | 19 | struct gp8psk_fe_state { |
19 | struct dvb_frontend fe; | 20 | struct dvb_frontend fe; |
20 | |||
21 | struct dvb_usb_device *d; | 21 | struct dvb_usb_device *d; |
22 | 22 | u8 lock; | |
23 | u16 snr; | 23 | u16 snr; |
24 | 24 | unsigned long next_status_check; | |
25 | unsigned long next_snr_check; | 25 | unsigned long status_check_interval; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | static int gp8psk_fe_update_status(struct gp8psk_fe_state *st) | ||
29 | { | ||
30 | u8 buf[6]; | ||
31 | if (time_after(jiffies,st->next_status_check)) { | ||
32 | gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0,0,&st->lock,1); | ||
33 | gp8psk_usb_in_op(st->d, GET_SIGNAL_STRENGTH, 0,0,buf,6); | ||
34 | st->snr = (buf[1]) << 8 | buf[0]; | ||
35 | st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000; | ||
36 | } | ||
37 | return 0; | ||
38 | } | ||
39 | |||
28 | static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) | 40 | static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) |
29 | { | 41 | { |
30 | struct gp8psk_fe_state *st = fe->demodulator_priv; | 42 | struct gp8psk_fe_state *st = fe->demodulator_priv; |
31 | u8 lock; | 43 | gp8psk_fe_update_status(st); |
32 | 44 | ||
33 | if (gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0, 0, &lock,1)) | 45 | if (st->lock) |
34 | return -EINVAL; | ||
35 | |||
36 | if (lock) | ||
37 | *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER; | 46 | *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER; |
38 | else | 47 | else |
39 | *status = 0; | 48 | *status = 0; |
40 | 49 | ||
50 | if (*status & FE_HAS_LOCK) | ||
51 | st->status_check_interval = 1000; | ||
52 | else | ||
53 | st->status_check_interval = 100; | ||
41 | return 0; | 54 | return 0; |
42 | } | 55 | } |
43 | 56 | ||
@@ -60,33 +73,29 @@ static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) | |||
60 | static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr) | 73 | static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr) |
61 | { | 74 | { |
62 | struct gp8psk_fe_state *st = fe->demodulator_priv; | 75 | struct gp8psk_fe_state *st = fe->demodulator_priv; |
63 | u8 buf[2]; | 76 | gp8psk_fe_update_status(st); |
64 | 77 | /* snr is reported in dBu*256 */ | |
65 | if (time_after(jiffies,st->next_snr_check)) { | 78 | *snr = st->snr; |
66 | gp8psk_usb_in_op(st->d,GET_SIGNAL_STRENGTH,0,0,buf,2); | ||
67 | *snr = (int)(buf[1]) << 8 | buf[0]; | ||
68 | /* snr is reported in dBu*256 */ | ||
69 | /* snr / 38.4 ~= 100% strength */ | ||
70 | /* snr * 17 returns 100% strength as 65535 */ | ||
71 | if (*snr <= 3855) | ||
72 | *snr = (*snr<<4) + *snr; // snr * 17 | ||
73 | else | ||
74 | *snr = 65535; | ||
75 | st->next_snr_check = jiffies + (10*HZ)/1000; | ||
76 | } else { | ||
77 | *snr = st->snr; | ||
78 | } | ||
79 | return 0; | 79 | return 0; |
80 | } | 80 | } |
81 | 81 | ||
82 | static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) | 82 | static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) |
83 | { | 83 | { |
84 | return gp8psk_fe_read_snr(fe, strength); | 84 | struct gp8psk_fe_state *st = fe->demodulator_priv; |
85 | gp8psk_fe_update_status(st); | ||
86 | /* snr is reported in dBu*256 */ | ||
87 | /* snr / 38.4 ~= 100% strength */ | ||
88 | /* snr * 17 returns 100% strength as 65535 */ | ||
89 | if (st->snr > 0xf00) | ||
90 | *strength = 0xffff; | ||
91 | else | ||
92 | *strength = (st->snr << 4) + st->snr; /* snr*17 */ | ||
93 | return 0; | ||
85 | } | 94 | } |
86 | 95 | ||
87 | static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | 96 | static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) |
88 | { | 97 | { |
89 | tune->min_delay_ms = 800; | 98 | tune->min_delay_ms = 200; |
90 | return 0; | 99 | return 0; |
91 | } | 100 | } |
92 | 101 | ||
@@ -124,7 +133,9 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe, | |||
124 | 133 | ||
125 | gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10); | 134 | gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10); |
126 | 135 | ||
127 | state->next_snr_check = jiffies; | 136 | state->lock = 0; |
137 | state->next_status_check = jiffies; | ||
138 | state->status_check_interval = 200; | ||
128 | 139 | ||
129 | return 0; | 140 | return 0; |
130 | } | 141 | } |
@@ -190,6 +201,12 @@ static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t volt | |||
190 | return 0; | 201 | return 0; |
191 | } | 202 | } |
192 | 203 | ||
204 | static int gp8psk_fe_enable_high_lnb_voltage(struct dvb_frontend* fe, long onoff) | ||
205 | { | ||
206 | struct gp8psk_fe_state* state = fe->demodulator_priv; | ||
207 | return gp8psk_usb_out_op(state->d, USE_EXTRA_VOLT, onoff, 0,NULL,0); | ||
208 | } | ||
209 | |||
193 | static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd) | 210 | static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd) |
194 | { | 211 | { |
195 | struct gp8psk_fe_state* state = fe->demodulator_priv; | 212 | struct gp8psk_fe_state* state = fe->demodulator_priv; |
@@ -235,10 +252,10 @@ success: | |||
235 | 252 | ||
236 | static struct dvb_frontend_ops gp8psk_fe_ops = { | 253 | static struct dvb_frontend_ops gp8psk_fe_ops = { |
237 | .info = { | 254 | .info = { |
238 | .name = "Genpix 8psk-USB DVB-S", | 255 | .name = "Genpix 8psk-to-USB2 DVB-S", |
239 | .type = FE_QPSK, | 256 | .type = FE_QPSK, |
240 | .frequency_min = 950000, | 257 | .frequency_min = 800000, |
241 | .frequency_max = 2150000, | 258 | .frequency_max = 2250000, |
242 | .frequency_stepsize = 100, | 259 | .frequency_stepsize = 100, |
243 | .symbol_rate_min = 1000000, | 260 | .symbol_rate_min = 1000000, |
244 | .symbol_rate_max = 45000000, | 261 | .symbol_rate_max = 45000000, |
@@ -269,4 +286,5 @@ static struct dvb_frontend_ops gp8psk_fe_ops = { | |||
269 | .set_tone = gp8psk_fe_set_tone, | 286 | .set_tone = gp8psk_fe_set_tone, |
270 | .set_voltage = gp8psk_fe_set_voltage, | 287 | .set_voltage = gp8psk_fe_set_voltage, |
271 | .dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd, | 288 | .dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd, |
289 | .enable_high_lnb_voltage = gp8psk_fe_enable_high_lnb_voltage | ||
272 | }; | 290 | }; |
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c index 518d67fca5e8..92147ee3e14f 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/drivers/media/dvb/dvb-usb/gp8psk.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* DVB USB compliant Linux driver for the | 1 | /* DVB USB compliant Linux driver for the |
2 | * - GENPIX 8pks/qpsk USB2.0 DVB-S module | 2 | * - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com) | 4 | * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com) |
5 | * Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com) | ||
5 | * | 6 | * |
6 | * Thanks to GENPIX for the sample code used to implement this module. | 7 | * Thanks to GENPIX for the sample code used to implement this module. |
7 | * | 8 | * |
@@ -40,7 +41,7 @@ int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 | |||
40 | } | 41 | } |
41 | 42 | ||
42 | if (ret < 0 || ret != blen) { | 43 | if (ret < 0 || ret != blen) { |
43 | warn("usb in operation failed."); | 44 | warn("usb in %d operation failed.", req); |
44 | ret = -EIO; | 45 | ret = -EIO; |
45 | } else | 46 | } else |
46 | ret = 0; | 47 | ret = 0; |
@@ -97,10 +98,10 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d) | |||
97 | if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0)) | 98 | if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0)) |
98 | goto out_rel_fw; | 99 | goto out_rel_fw; |
99 | 100 | ||
100 | info("downloaidng bcm4500 firmware from file '%s'",bcm4500_firmware); | 101 | info("downloading bcm4500 firmware from file '%s'",bcm4500_firmware); |
101 | 102 | ||
102 | ptr = fw->data; | 103 | ptr = fw->data; |
103 | buf = kmalloc(512, GFP_KERNEL | GFP_DMA); | 104 | buf = kmalloc(64, GFP_KERNEL | GFP_DMA); |
104 | 105 | ||
105 | while (ptr[0] != 0xff) { | 106 | while (ptr[0] != 0xff) { |
106 | u16 buflen = ptr[0] + 4; | 107 | u16 buflen = ptr[0] + 4; |
@@ -129,25 +130,34 @@ out_rel_fw: | |||
129 | static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff) | 130 | static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff) |
130 | { | 131 | { |
131 | u8 status, buf; | 132 | u8 status, buf; |
133 | int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct); | ||
134 | |||
132 | if (onoff) { | 135 | if (onoff) { |
133 | gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1); | 136 | gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1); |
134 | if (! (status & 0x01)) /* started */ | 137 | if (! (status & bm8pskStarted)) { /* started */ |
138 | if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K) | ||
139 | gp8psk_usb_out_op(d, CW3K_INIT, 1, 0, NULL, 0); | ||
135 | if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1)) | 140 | if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1)) |
136 | return -EINVAL; | 141 | return -EINVAL; |
142 | } | ||
137 | 143 | ||
138 | if (! (status & 0x02)) /* BCM4500 firmware loaded */ | 144 | if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) |
139 | if(gp8psk_load_bcm4500fw(d)) | 145 | if (! (status & bm8pskFW_Loaded)) /* BCM4500 firmware loaded */ |
140 | return EINVAL; | 146 | if(gp8psk_load_bcm4500fw(d)) |
147 | return EINVAL; | ||
141 | 148 | ||
142 | if (! (status & 0x04)) /* LNB Power */ | 149 | if (! (status & bmIntersilOn)) /* LNB Power */ |
143 | if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0, | 150 | if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0, |
144 | &buf, 1)) | 151 | &buf, 1)) |
145 | return EINVAL; | 152 | return EINVAL; |
146 | 153 | ||
147 | /* Set DVB mode */ | 154 | /* Set DVB mode to 1 */ |
148 | if(gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0)) | 155 | if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) |
149 | return -EINVAL; | 156 | if (gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0)) |
150 | gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1); | 157 | return EINVAL; |
158 | /* Abort possible TS (if previous tune crashed) */ | ||
159 | if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0)) | ||
160 | return EINVAL; | ||
151 | } else { | 161 | } else { |
152 | /* Turn off LNB power */ | 162 | /* Turn off LNB power */ |
153 | if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1)) | 163 | if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1)) |
@@ -155,11 +165,28 @@ static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff) | |||
155 | /* Turn off 8psk power */ | 165 | /* Turn off 8psk power */ |
156 | if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1)) | 166 | if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1)) |
157 | return -EINVAL; | 167 | return -EINVAL; |
158 | 168 | if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K) | |
169 | gp8psk_usb_out_op(d, CW3K_INIT, 0, 0, NULL, 0); | ||
159 | } | 170 | } |
160 | return 0; | 171 | return 0; |
161 | } | 172 | } |
162 | 173 | ||
174 | int gp8psk_bcm4500_reload(struct dvb_usb_device *d) | ||
175 | { | ||
176 | u8 buf; | ||
177 | int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct); | ||
178 | /* Turn off 8psk power */ | ||
179 | if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1)) | ||
180 | return -EINVAL; | ||
181 | /* Turn On 8psk power */ | ||
182 | if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1)) | ||
183 | return -EINVAL; | ||
184 | /* load BCM4500 firmware */ | ||
185 | if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) | ||
186 | if (gp8psk_load_bcm4500fw(d)) | ||
187 | return EINVAL; | ||
188 | return 0; | ||
189 | } | ||
163 | 190 | ||
164 | static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | 191 | static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) |
165 | { | 192 | { |
@@ -177,12 +204,22 @@ static struct dvb_usb_device_properties gp8psk_properties; | |||
177 | static int gp8psk_usb_probe(struct usb_interface *intf, | 204 | static int gp8psk_usb_probe(struct usb_interface *intf, |
178 | const struct usb_device_id *id) | 205 | const struct usb_device_id *id) |
179 | { | 206 | { |
180 | return dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL); | 207 | int ret; |
208 | struct usb_device *udev = interface_to_usbdev(intf); | ||
209 | ret = dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL); | ||
210 | if (ret == 0) { | ||
211 | info("found Genpix USB device pID = %x (hex)", | ||
212 | le16_to_cpu(udev->descriptor.idProduct)); | ||
213 | } | ||
214 | return ret; | ||
181 | } | 215 | } |
182 | 216 | ||
183 | static struct usb_device_id gp8psk_usb_table [] = { | 217 | static struct usb_device_id gp8psk_usb_table [] = { |
184 | { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_COLD) }, | 218 | { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_COLD) }, |
185 | { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_WARM) }, | 219 | { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) }, |
220 | { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) }, | ||
221 | { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) }, | ||
222 | { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, | ||
186 | { 0 }, | 223 | { 0 }, |
187 | }; | 224 | }; |
188 | MODULE_DEVICE_TABLE(usb, gp8psk_usb_table); | 225 | MODULE_DEVICE_TABLE(usb, gp8psk_usb_table); |
@@ -213,12 +250,24 @@ static struct dvb_usb_device_properties gp8psk_properties = { | |||
213 | 250 | ||
214 | .generic_bulk_ctrl_endpoint = 0x01, | 251 | .generic_bulk_ctrl_endpoint = 0x01, |
215 | 252 | ||
216 | .num_device_descs = 1, | 253 | .num_device_descs = 4, |
217 | .devices = { | 254 | .devices = { |
218 | { .name = "Genpix 8PSK-USB DVB-S USB2.0 receiver", | 255 | { .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver", |
219 | .cold_ids = { &gp8psk_usb_table[0], NULL }, | 256 | .cold_ids = { &gp8psk_usb_table[0], NULL }, |
220 | .warm_ids = { &gp8psk_usb_table[1], NULL }, | 257 | .warm_ids = { &gp8psk_usb_table[1], NULL }, |
221 | }, | 258 | }, |
259 | { .name = "Genpix 8PSK-to-USB2 Rev.2 DVB-S receiver", | ||
260 | .cold_ids = { NULL }, | ||
261 | .warm_ids = { &gp8psk_usb_table[2], NULL }, | ||
262 | }, | ||
263 | { .name = "Genpix SkyWalker-1 DVB-S receiver", | ||
264 | .cold_ids = { NULL }, | ||
265 | .warm_ids = { &gp8psk_usb_table[3], NULL }, | ||
266 | }, | ||
267 | { .name = "Genpix SkyWalker-CW3K DVB-S receiver", | ||
268 | .cold_ids = { NULL }, | ||
269 | .warm_ids = { &gp8psk_usb_table[4], NULL }, | ||
270 | }, | ||
222 | { NULL }, | 271 | { NULL }, |
223 | } | 272 | } |
224 | }; | 273 | }; |
@@ -253,6 +302,6 @@ module_init(gp8psk_usb_module_init); | |||
253 | module_exit(gp8psk_usb_module_exit); | 302 | module_exit(gp8psk_usb_module_exit); |
254 | 303 | ||
255 | MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>"); | 304 | MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>"); |
256 | MODULE_DESCRIPTION("Driver for Genpix 8psk-USB DVB-S USB2.0"); | 305 | MODULE_DESCRIPTION("Driver for Genpix 8psk-to-USB2 DVB-S"); |
257 | MODULE_VERSION("1.0"); | 306 | MODULE_VERSION("1.1"); |
258 | MODULE_LICENSE("GPL"); | 307 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/dvb/dvb-usb/gp8psk.h index 3eba7061011c..e83a57506cfa 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk.h +++ b/drivers/media/dvb/dvb-usb/gp8psk.h | |||
@@ -1,7 +1,8 @@ | |||
1 | /* DVB USB compliant Linux driver for the | 1 | /* DVB USB compliant Linux driver for the |
2 | * - GENPIX 8pks/qpsk USB2.0 DVB-S module | 2 | * - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com) | 4 | * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com) |
5 | * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com) | ||
5 | * | 6 | * |
6 | * Thanks to GENPIX for the sample code used to implement this module. | 7 | * Thanks to GENPIX for the sample code used to implement this module. |
7 | * | 8 | * |
@@ -30,21 +31,37 @@ extern int dvb_usb_gp8psk_debug; | |||
30 | #define TH_COMMAND_IN 0xC0 | 31 | #define TH_COMMAND_IN 0xC0 |
31 | #define TH_COMMAND_OUT 0xC1 | 32 | #define TH_COMMAND_OUT 0xC1 |
32 | 33 | ||
33 | /* command bytes */ | 34 | /* gp8psk commands */ |
34 | #define GET_8PSK_CONFIG 0x80 | 35 | |
36 | #define GET_8PSK_CONFIG 0x80 /* in */ | ||
35 | #define SET_8PSK_CONFIG 0x81 | 37 | #define SET_8PSK_CONFIG 0x81 |
38 | #define I2C_WRITE 0x83 | ||
39 | #define I2C_READ 0x84 | ||
36 | #define ARM_TRANSFER 0x85 | 40 | #define ARM_TRANSFER 0x85 |
37 | #define TUNE_8PSK 0x86 | 41 | #define TUNE_8PSK 0x86 |
38 | #define GET_SIGNAL_STRENGTH 0x87 | 42 | #define GET_SIGNAL_STRENGTH 0x87 /* in */ |
39 | #define LOAD_BCM4500 0x88 | 43 | #define LOAD_BCM4500 0x88 |
40 | #define BOOT_8PSK 0x89 | 44 | #define BOOT_8PSK 0x89 /* in */ |
41 | #define START_INTERSIL 0x8A | 45 | #define START_INTERSIL 0x8A /* in */ |
42 | #define SET_LNB_VOLTAGE 0x8B | 46 | #define SET_LNB_VOLTAGE 0x8B |
43 | #define SET_22KHZ_TONE 0x8C | 47 | #define SET_22KHZ_TONE 0x8C |
44 | #define SEND_DISEQC_COMMAND 0x8D | 48 | #define SEND_DISEQC_COMMAND 0x8D |
45 | #define SET_DVB_MODE 0x8E | 49 | #define SET_DVB_MODE 0x8E |
46 | #define SET_DN_SWITCH 0x8F | 50 | #define SET_DN_SWITCH 0x8F |
47 | #define GET_SIGNAL_LOCK 0x90 | 51 | #define GET_SIGNAL_LOCK 0x90 /* in */ |
52 | #define GET_SERIAL_NUMBER 0x93 /* in */ | ||
53 | #define USE_EXTRA_VOLT 0x94 | ||
54 | #define CW3K_INIT 0x9d | ||
55 | |||
56 | /* PSK_configuration bits */ | ||
57 | #define bm8pskStarted 0x01 | ||
58 | #define bm8pskFW_Loaded 0x02 | ||
59 | #define bmIntersilOn 0x04 | ||
60 | #define bmDVBmode 0x08 | ||
61 | #define bm22kHz 0x10 | ||
62 | #define bmSEL18V 0x20 | ||
63 | #define bmDCtuned 0x40 | ||
64 | #define bmArmed 0x80 | ||
48 | 65 | ||
49 | /* Satellite modulation modes */ | 66 | /* Satellite modulation modes */ |
50 | #define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */ | 67 | #define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */ |
@@ -75,5 +92,6 @@ extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d); | |||
75 | extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); | 92 | extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); |
76 | extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, | 93 | extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, |
77 | u16 index, u8 *b, int blen); | 94 | u16 index, u8 *b, int blen); |
95 | extern int gp8psk_bcm4500_reload(struct dvb_usb_device *d); | ||
78 | 96 | ||
79 | #endif | 97 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index 69a46b3607a2..5bbd2d5192f0 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c | |||
@@ -159,7 +159,7 @@ static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
159 | return 0; | 159 | return 0; |
160 | } | 160 | } |
161 | 161 | ||
162 | for (i = 0; i < sizeof(vp7045_rc_keys)/sizeof(struct dvb_usb_rc_key); i++) | 162 | for (i = 0; i < ARRAY_SIZE(vp7045_rc_keys); i++) |
163 | if (vp7045_rc_keys[i].data == key) { | 163 | if (vp7045_rc_keys[i].data == key) { |
164 | *state = REMOTE_KEY_PRESSED; | 164 | *state = REMOTE_KEY_PRESSED; |
165 | *event = vp7045_rc_keys[i].event; | 165 | *event = vp7045_rc_keys[i].event; |
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index ff448761dcef..59b9ed1f1aec 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
@@ -283,6 +283,14 @@ config DVB_LGDT330X | |||
283 | An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want | 283 | An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want |
284 | to support this frontend. | 284 | to support this frontend. |
285 | 285 | ||
286 | config DVB_S5H1409 | ||
287 | tristate "Samsung S5H1409 based" | ||
288 | depends on DVB_CORE && I2C | ||
289 | default m if DVB_FE_CUSTOMISE | ||
290 | help | ||
291 | An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want | ||
292 | to support this frontend. | ||
293 | |||
286 | comment "Tuners/PLL support" | 294 | comment "Tuners/PLL support" |
287 | depends on DVB_CORE | 295 | depends on DVB_CORE |
288 | 296 | ||
@@ -291,7 +299,7 @@ config DVB_PLL | |||
291 | depends on DVB_CORE && I2C | 299 | depends on DVB_CORE && I2C |
292 | default m if DVB_FE_CUSTOMISE | 300 | default m if DVB_FE_CUSTOMISE |
293 | help | 301 | help |
294 | This module driver a number of tuners based on PLL chips with a | 302 | This module drives a number of tuners based on PLL chips with a |
295 | common I2C interface. Say Y when you want to support these tuners. | 303 | common I2C interface. Say Y when you want to support these tuners. |
296 | 304 | ||
297 | config DVB_TDA826X | 305 | config DVB_TDA826X |
@@ -322,6 +330,29 @@ config DVB_TUNER_MT2060 | |||
322 | help | 330 | help |
323 | A driver for the silicon IF tuner MT2060 from Microtune. | 331 | A driver for the silicon IF tuner MT2060 from Microtune. |
324 | 332 | ||
333 | config DVB_TUNER_MT2266 | ||
334 | tristate "Microtune MT2266 silicon tuner" | ||
335 | depends on I2C | ||
336 | default m if DVB_FE_CUSTOMISE | ||
337 | help | ||
338 | A driver for the silicon baseband tuner MT2266 from Microtune. | ||
339 | |||
340 | config DVB_TUNER_MT2131 | ||
341 | tristate "Microtune MT2131 silicon tuner" | ||
342 | depends on I2C | ||
343 | default m if DVB_FE_CUSTOMISE | ||
344 | help | ||
345 | A driver for the silicon baseband tuner MT2131 from Microtune. | ||
346 | |||
347 | config DVB_TUNER_DIB0070 | ||
348 | tristate "DiBcom DiB0070 silicon base-band tuner" | ||
349 | depends on I2C | ||
350 | default m if DVB_FE_CUSTOMISE | ||
351 | help | ||
352 | A driver for the silicon baseband tuner DiB0070 from DiBcom. | ||
353 | This device is only used inside a SiP called togther with a | ||
354 | demodulator for now. | ||
355 | |||
325 | comment "Miscellaneous devices" | 356 | comment "Miscellaneous devices" |
326 | depends on DVB_CORE | 357 | depends on DVB_CORE |
327 | 358 | ||
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 156b062e02c4..4b8ad1f132aa 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -40,5 +40,9 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o | |||
40 | obj-$(CONFIG_DVB_TDA826X) += tda826x.o | 40 | obj-$(CONFIG_DVB_TDA826X) += tda826x.o |
41 | obj-$(CONFIG_DVB_TDA827X) += tda827x.o | 41 | obj-$(CONFIG_DVB_TDA827X) += tda827x.o |
42 | obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o | 42 | obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o |
43 | obj-$(CONFIG_DVB_TUNER_MT2266) += mt2266.o | ||
44 | obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o | ||
43 | obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o | 45 | obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o |
44 | obj-$(CONFIG_DVB_TUA6100) += tua6100.o | 46 | obj-$(CONFIG_DVB_TUA6100) += tua6100.o |
47 | obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o | ||
48 | obj-$(CONFIG_DVB_S5H1409) += s5h1409.o | ||
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c index baeb311de893..a913f49c062b 100644 --- a/drivers/media/dvb/frontends/bcm3510.c +++ b/drivers/media/dvb/frontends/bcm3510.c | |||
@@ -33,7 +33,6 @@ | |||
33 | 33 | ||
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/moduleparam.h> | ||
37 | #include <linux/device.h> | 36 | #include <linux/device.h> |
38 | #include <linux/firmware.h> | 37 | #include <linux/firmware.h> |
39 | #include <linux/jiffies.h> | 38 | #include <linux/jiffies.h> |
diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb/frontends/cx22700.c index 13ad1bfae663..11a4968f18cb 100644 --- a/drivers/media/dvb/frontends/cx22700.c +++ b/drivers/media/dvb/frontends/cx22700.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/string.h> | 26 | #include <linux/string.h> |
28 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
29 | #include "dvb_frontend.h" | 28 | #include "dvb_frontend.h" |
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c index 10fc0c8316dd..b03d8283c37d 100644 --- a/drivers/media/dvb/frontends/cx24110.c +++ b/drivers/media/dvb/frontends/cx24110.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | ||
29 | #include <linux/init.h> | 28 | #include <linux/init.h> |
30 | 29 | ||
31 | #include "dvb_frontend.h" | 30 | #include "dvb_frontend.h" |
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index 0834c0677fef..d74fdbd63361 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/init.h> | 26 | #include <linux/init.h> |
28 | 27 | ||
29 | #include "dvb_frontend.h" | 28 | #include "dvb_frontend.h" |
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c new file mode 100644 index 000000000000..481eaa684157 --- /dev/null +++ b/drivers/media/dvb/frontends/dib0070.c | |||
@@ -0,0 +1,580 @@ | |||
1 | /* | ||
2 | * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner. | ||
3 | * | ||
4 | * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/i2c.h> | ||
12 | |||
13 | #include "dvb_frontend.h" | ||
14 | |||
15 | #include "dib0070.h" | ||
16 | #include "dibx000_common.h" | ||
17 | |||
18 | static int debug; | ||
19 | module_param(debug, int, 0644); | ||
20 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | ||
21 | |||
22 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB0070: "); printk(args); printk("\n"); } } while (0) | ||
23 | |||
24 | #define DIB0070_P1D 0x00 | ||
25 | #define DIB0070_P1F 0x01 | ||
26 | #define DIB0070_P1G 0x03 | ||
27 | #define DIB0070S_P1A 0x02 | ||
28 | |||
29 | struct dib0070_state { | ||
30 | struct i2c_adapter *i2c; | ||
31 | struct dvb_frontend *fe; | ||
32 | const struct dib0070_config *cfg; | ||
33 | u16 wbd_ff_offset; | ||
34 | u8 revision; | ||
35 | }; | ||
36 | |||
37 | static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) | ||
38 | { | ||
39 | u8 b[2]; | ||
40 | struct i2c_msg msg[2] = { | ||
41 | { .addr = state->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, | ||
42 | { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 }, | ||
43 | }; | ||
44 | if (i2c_transfer(state->i2c, msg, 2) != 2) { | ||
45 | printk(KERN_WARNING "DiB0070 I2C read failed\n"); | ||
46 | return 0; | ||
47 | } | ||
48 | return (b[0] << 8) | b[1]; | ||
49 | } | ||
50 | |||
51 | static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) | ||
52 | { | ||
53 | u8 b[3] = { reg, val >> 8, val & 0xff }; | ||
54 | struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 }; | ||
55 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | ||
56 | printk(KERN_WARNING "DiB0070 I2C write failed\n"); | ||
57 | return -EREMOTEIO; | ||
58 | } | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | #define HARD_RESET(state) do { if (state->cfg->reset) { state->cfg->reset(state->fe,1); msleep(10); state->cfg->reset(state->fe,0); msleep(10); } } while (0) | ||
63 | |||
64 | static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) | ||
65 | { | ||
66 | struct dib0070_state *st = fe->tuner_priv; | ||
67 | u16 tmp = 0; | ||
68 | tmp = dib0070_read_reg(st, 0x02) & 0x3fff; | ||
69 | |||
70 | switch(BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)) { | ||
71 | case 8000: | ||
72 | tmp |= (0 << 14); | ||
73 | break; | ||
74 | case 7000: | ||
75 | tmp |= (1 << 14); | ||
76 | break; | ||
77 | case 6000: | ||
78 | tmp |= (2 << 14); | ||
79 | break; | ||
80 | case 5000: | ||
81 | default: | ||
82 | tmp |= (3 << 14); | ||
83 | break; | ||
84 | } | ||
85 | dib0070_write_reg(st, 0x02, tmp); | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static void dib0070_captrim(struct dib0070_state *st, u16 LO4) | ||
90 | { | ||
91 | int8_t captrim, fcaptrim, step_sign, step; | ||
92 | u16 adc, adc_diff = 3000; | ||
93 | |||
94 | |||
95 | |||
96 | dib0070_write_reg(st, 0x0f, 0xed10); | ||
97 | dib0070_write_reg(st, 0x17, 0x0034); | ||
98 | |||
99 | dib0070_write_reg(st, 0x18, 0x0032); | ||
100 | msleep(2); | ||
101 | |||
102 | step = captrim = fcaptrim = 64; | ||
103 | |||
104 | do { | ||
105 | step /= 2; | ||
106 | dib0070_write_reg(st, 0x14, LO4 | captrim); | ||
107 | msleep(1); | ||
108 | adc = dib0070_read_reg(st, 0x19); | ||
109 | |||
110 | dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", captrim, adc, (u32) adc*(u32)1800/(u32)1024); | ||
111 | |||
112 | if (adc >= 400) { | ||
113 | adc -= 400; | ||
114 | step_sign = -1; | ||
115 | } else { | ||
116 | adc = 400 - adc; | ||
117 | step_sign = 1; | ||
118 | } | ||
119 | |||
120 | if (adc < adc_diff) { | ||
121 | dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", captrim, adc, adc_diff); | ||
122 | adc_diff = adc; | ||
123 | fcaptrim = captrim; | ||
124 | |||
125 | |||
126 | |||
127 | } | ||
128 | captrim += (step_sign * step); | ||
129 | } while (step >= 1); | ||
130 | |||
131 | dib0070_write_reg(st, 0x14, LO4 | fcaptrim); | ||
132 | dib0070_write_reg(st, 0x18, 0x07ff); | ||
133 | } | ||
134 | |||
135 | #define LPF 100 // define for the loop filter 100kHz by default 16-07-06 | ||
136 | #define LO4_SET_VCO_HFDIV(l, v, h) l |= ((v) << 11) | ((h) << 7) | ||
137 | #define LO4_SET_SD(l, s) l |= ((s) << 14) | ((s) << 12) | ||
138 | #define LO4_SET_CTRIM(l, c) l |= (c) << 10 | ||
139 | static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) | ||
140 | { | ||
141 | struct dib0070_state *st = fe->tuner_priv; | ||
142 | u32 freq = ch->frequency/1000 + (BAND_OF_FREQUENCY(ch->frequency/1000) == BAND_VHF ? st->cfg->freq_offset_khz_vhf : st->cfg->freq_offset_khz_uhf); | ||
143 | |||
144 | u8 band = BAND_OF_FREQUENCY(freq), c; | ||
145 | |||
146 | /*******************VCO***********************************/ | ||
147 | u16 lo4 = 0; | ||
148 | |||
149 | u8 REFDIV, PRESC = 2; | ||
150 | u32 FBDiv, Rest, FREF, VCOF_kHz; | ||
151 | u16 Num, Den; | ||
152 | /*******************FrontEnd******************************/ | ||
153 | u16 value = 0; | ||
154 | |||
155 | dprintk( "Tuning for Band: %hd (%d kHz)", band, freq); | ||
156 | |||
157 | |||
158 | dib0070_write_reg(st, 0x17, 0x30); | ||
159 | |||
160 | dib0070_set_bandwidth(fe, ch); /* c is used as HF */ | ||
161 | switch (st->revision) { | ||
162 | case DIB0070S_P1A: | ||
163 | switch (band) { | ||
164 | case BAND_LBAND: | ||
165 | LO4_SET_VCO_HFDIV(lo4, 1, 1); | ||
166 | c = 2; | ||
167 | break; | ||
168 | case BAND_SBAND: | ||
169 | LO4_SET_VCO_HFDIV(lo4, 0, 0); | ||
170 | LO4_SET_CTRIM(lo4, 1);; | ||
171 | c = 1; | ||
172 | break; | ||
173 | case BAND_UHF: | ||
174 | default: | ||
175 | if (freq < 570000) { | ||
176 | LO4_SET_VCO_HFDIV(lo4, 1, 3); | ||
177 | PRESC = 6; c = 6; | ||
178 | } else if (freq < 680000) { | ||
179 | LO4_SET_VCO_HFDIV(lo4, 0, 2); | ||
180 | c = 4; | ||
181 | } else { | ||
182 | LO4_SET_VCO_HFDIV(lo4, 1, 2); | ||
183 | c = 4; | ||
184 | } | ||
185 | break; | ||
186 | } break; | ||
187 | |||
188 | case DIB0070_P1G: | ||
189 | case DIB0070_P1F: | ||
190 | default: | ||
191 | switch (band) { | ||
192 | case BAND_FM: | ||
193 | LO4_SET_VCO_HFDIV(lo4, 0, 7); | ||
194 | c = 24; | ||
195 | break; | ||
196 | case BAND_LBAND: | ||
197 | LO4_SET_VCO_HFDIV(lo4, 1, 0); | ||
198 | c = 2; | ||
199 | break; | ||
200 | case BAND_VHF: | ||
201 | if (freq < 180000) { | ||
202 | LO4_SET_VCO_HFDIV(lo4, 0, 3); | ||
203 | c = 16; | ||
204 | } else if (freq < 190000) { | ||
205 | LO4_SET_VCO_HFDIV(lo4, 1, 3); | ||
206 | c = 16; | ||
207 | } else { | ||
208 | LO4_SET_VCO_HFDIV(lo4, 0, 6); | ||
209 | c = 12; | ||
210 | } | ||
211 | break; | ||
212 | |||
213 | case BAND_UHF: | ||
214 | default: | ||
215 | if (freq < 570000) { | ||
216 | LO4_SET_VCO_HFDIV(lo4, 1, 5); | ||
217 | c = 6; | ||
218 | } else if (freq < 700000) { | ||
219 | LO4_SET_VCO_HFDIV(lo4, 0, 1); | ||
220 | c = 4; | ||
221 | } else { | ||
222 | LO4_SET_VCO_HFDIV(lo4, 1, 1); | ||
223 | c = 4; | ||
224 | } | ||
225 | break; | ||
226 | } | ||
227 | break; | ||
228 | } | ||
229 | |||
230 | dprintk( "HFDIV code: %hd", (lo4 >> 7) & 0xf); | ||
231 | dprintk( "VCO = %hd", (lo4 >> 11) & 0x3); | ||
232 | |||
233 | |||
234 | VCOF_kHz = (c * freq) * 2; | ||
235 | dprintk( "VCOF in kHz: %d ((%hd*%d) << 1))",VCOF_kHz, c, freq); | ||
236 | |||
237 | switch (band) { | ||
238 | case BAND_VHF: | ||
239 | REFDIV = (u8) ((st->cfg->clock_khz + 9999) / 10000); | ||
240 | break; | ||
241 | case BAND_FM: | ||
242 | REFDIV = (u8) ((st->cfg->clock_khz) / 1000); | ||
243 | break; | ||
244 | default: | ||
245 | REFDIV = (u8) ( st->cfg->clock_khz / 10000); | ||
246 | break; | ||
247 | } | ||
248 | FREF = st->cfg->clock_khz / REFDIV; | ||
249 | |||
250 | dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF); | ||
251 | |||
252 | |||
253 | |||
254 | switch (st->revision) { | ||
255 | case DIB0070S_P1A: | ||
256 | FBDiv = (VCOF_kHz / PRESC / FREF); | ||
257 | Rest = (VCOF_kHz / PRESC) - FBDiv * FREF; | ||
258 | break; | ||
259 | |||
260 | case DIB0070_P1G: | ||
261 | case DIB0070_P1F: | ||
262 | default: | ||
263 | FBDiv = (freq / (FREF / 2)); | ||
264 | Rest = 2 * freq - FBDiv * FREF; | ||
265 | break; | ||
266 | } | ||
267 | |||
268 | |||
269 | if (Rest < LPF) Rest = 0; | ||
270 | else if (Rest < 2 * LPF) Rest = 2 * LPF; | ||
271 | else if (Rest > (FREF - LPF)) { Rest = 0 ; FBDiv += 1; } | ||
272 | else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF; | ||
273 | Rest = (Rest * 6528) / (FREF / 10); | ||
274 | dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest); | ||
275 | |||
276 | Num = 0; | ||
277 | Den = 1; | ||
278 | |||
279 | if (Rest > 0) { | ||
280 | LO4_SET_SD(lo4, 1); | ||
281 | Den = 255; | ||
282 | Num = (u16)Rest; | ||
283 | } | ||
284 | dprintk( "Num: %hd, Den: %hd, SD: %hd",Num, Den, (lo4 >> 12) & 0x1); | ||
285 | |||
286 | |||
287 | |||
288 | dib0070_write_reg(st, 0x11, (u16)FBDiv); | ||
289 | |||
290 | |||
291 | dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV); | ||
292 | |||
293 | |||
294 | dib0070_write_reg(st, 0x13, Num); | ||
295 | |||
296 | |||
297 | value = 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001; | ||
298 | |||
299 | switch (band) { | ||
300 | case BAND_UHF: value |= 0x4000 | 0x0800; break; | ||
301 | case BAND_LBAND: value |= 0x2000 | 0x0400; break; | ||
302 | default: value |= 0x8000 | 0x1000; break; | ||
303 | } | ||
304 | dib0070_write_reg(st, 0x20, value); | ||
305 | |||
306 | dib0070_captrim(st, lo4); | ||
307 | if (st->revision == DIB0070S_P1A) { | ||
308 | if (band == BAND_SBAND) | ||
309 | dib0070_write_reg(st, 0x15, 0x16e2); | ||
310 | else | ||
311 | dib0070_write_reg(st, 0x15, 0x56e5); | ||
312 | } | ||
313 | |||
314 | |||
315 | |||
316 | switch (band) { | ||
317 | case BAND_UHF: value = 0x7c82; break; | ||
318 | case BAND_LBAND: value = 0x7c84; break; | ||
319 | default: value = 0x7c81; break; | ||
320 | } | ||
321 | dib0070_write_reg(st, 0x0f, value); | ||
322 | dib0070_write_reg(st, 0x06, 0x3fff); | ||
323 | |||
324 | /* Front End */ | ||
325 | /* c == TUNE, value = SWITCH */ | ||
326 | c = 0; | ||
327 | value = 0; | ||
328 | switch (band) { | ||
329 | case BAND_FM: | ||
330 | c = 0; value = 1; | ||
331 | break; | ||
332 | |||
333 | case BAND_VHF: | ||
334 | if (freq <= 180000) c = 0; | ||
335 | else if (freq <= 188200) c = 1; | ||
336 | else if (freq <= 196400) c = 2; | ||
337 | else c = 3; | ||
338 | value = 1; | ||
339 | break; | ||
340 | |||
341 | case BAND_LBAND: | ||
342 | if (freq <= 1500000) c = 0; | ||
343 | else if (freq <= 1600000) c = 1; | ||
344 | else c = 3; | ||
345 | break; | ||
346 | |||
347 | case BAND_SBAND: | ||
348 | c = 7; | ||
349 | dib0070_write_reg(st, 0x1d,0xFFFF); | ||
350 | break; | ||
351 | |||
352 | case BAND_UHF: | ||
353 | default: | ||
354 | if (st->cfg->flip_chip) { | ||
355 | if (freq <= 550000) c = 0; | ||
356 | else if (freq <= 590000) c = 1; | ||
357 | else if (freq <= 666000) c = 3; | ||
358 | else c = 5; | ||
359 | } else { | ||
360 | if (freq <= 550000) c = 2; | ||
361 | else if (freq <= 650000) c = 3; | ||
362 | else if (freq <= 750000) c = 5; | ||
363 | else if (freq <= 850000) c = 6; | ||
364 | else c = 7; | ||
365 | } | ||
366 | value = 2; | ||
367 | break; | ||
368 | } | ||
369 | |||
370 | /* default: LNA_MATCH=7, BIAS=3 */ | ||
371 | dib0070_write_reg(st, 0x07, (value << 11) | (7 << 8) | (c << 3) | (3 << 0)); | ||
372 | dib0070_write_reg(st, 0x08, (c << 10) | (3 << 7) | (127)); | ||
373 | dib0070_write_reg(st, 0x0d, 0x0d80); | ||
374 | |||
375 | |||
376 | dib0070_write_reg(st, 0x18, 0x07ff); | ||
377 | dib0070_write_reg(st, 0x17, 0x0033); | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static int dib0070_wakeup(struct dvb_frontend *fe) | ||
383 | { | ||
384 | struct dib0070_state *st = fe->tuner_priv; | ||
385 | if (st->cfg->sleep) | ||
386 | st->cfg->sleep(fe, 0); | ||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static int dib0070_sleep(struct dvb_frontend *fe) | ||
391 | { | ||
392 | struct dib0070_state *st = fe->tuner_priv; | ||
393 | if (st->cfg->sleep) | ||
394 | st->cfg->sleep(fe, 1); | ||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static u16 dib0070_p1f_defaults[] = | ||
399 | |||
400 | { | ||
401 | 7, 0x02, | ||
402 | 0x0008, | ||
403 | 0x0000, | ||
404 | 0x0000, | ||
405 | 0x0000, | ||
406 | 0x0000, | ||
407 | 0x0002, | ||
408 | 0x0100, | ||
409 | |||
410 | 3, 0x0d, | ||
411 | 0x0d80, | ||
412 | 0x0001, | ||
413 | 0x0000, | ||
414 | |||
415 | 4, 0x11, | ||
416 | 0x0000, | ||
417 | 0x0103, | ||
418 | 0x0000, | ||
419 | 0x0000, | ||
420 | |||
421 | 3, 0x16, | ||
422 | 0x0004 | 0x0040, | ||
423 | 0x0030, | ||
424 | 0x07ff, | ||
425 | |||
426 | 6, 0x1b, | ||
427 | 0x4112, | ||
428 | 0xff00, | ||
429 | 0xc07f, | ||
430 | 0x0000, | ||
431 | 0x0180, | ||
432 | 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001, | ||
433 | |||
434 | 0, | ||
435 | }; | ||
436 | |||
437 | static void dib0070_wbd_calibration(struct dib0070_state *state) | ||
438 | { | ||
439 | u16 wbd_offs; | ||
440 | dib0070_write_reg(state, 0x0f, 0x6d81); | ||
441 | dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); | ||
442 | msleep(9); | ||
443 | wbd_offs = dib0070_read_reg(state, 0x19); | ||
444 | dib0070_write_reg(state, 0x20, 0); | ||
445 | state->wbd_ff_offset = ((wbd_offs * 8 * 18 / 33 + 1) / 2); | ||
446 | dprintk( "WBDStart = %d (Vargen) - FF = %hd", (u32) wbd_offs * 1800/1024, state->wbd_ff_offset); | ||
447 | } | ||
448 | |||
449 | u16 dib0070_wbd_offset(struct dvb_frontend *fe) | ||
450 | { | ||
451 | struct dib0070_state *st = fe->tuner_priv; | ||
452 | return st->wbd_ff_offset; | ||
453 | } | ||
454 | |||
455 | EXPORT_SYMBOL(dib0070_wbd_offset); | ||
456 | static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt) | ||
457 | { | ||
458 | struct dib0070_state *state = fe->tuner_priv; | ||
459 | u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); | ||
460 | dprintk( "CTRL_LO5: 0x%x", lo5); | ||
461 | return dib0070_write_reg(state, 0x15, lo5); | ||
462 | } | ||
463 | |||
464 | #define pgm_read_word(w) (*w) | ||
465 | static int dib0070_reset(struct dib0070_state *state) | ||
466 | { | ||
467 | u16 l, r, *n; | ||
468 | |||
469 | HARD_RESET(state); | ||
470 | |||
471 | |||
472 | #ifndef FORCE_SBAND_TUNER | ||
473 | if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) | ||
474 | state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; | ||
475 | else | ||
476 | #endif | ||
477 | state->revision = DIB0070S_P1A; | ||
478 | |||
479 | /* P1F or not */ | ||
480 | dprintk( "Revision: %x", state->revision); | ||
481 | |||
482 | if (state->revision == DIB0070_P1D) { | ||
483 | dprintk( "Error: this driver is not to be used meant for P1D or earlier"); | ||
484 | return -EINVAL; | ||
485 | } | ||
486 | |||
487 | n = (u16 *) dib0070_p1f_defaults; | ||
488 | l = pgm_read_word(n++); | ||
489 | while (l) { | ||
490 | r = pgm_read_word(n++); | ||
491 | do { | ||
492 | dib0070_write_reg(state, (u8)r, pgm_read_word(n++)); | ||
493 | r++; | ||
494 | } while (--l); | ||
495 | l = pgm_read_word(n++); | ||
496 | } | ||
497 | |||
498 | if (state->cfg->force_crystal_mode != 0) | ||
499 | r = state->cfg->force_crystal_mode; | ||
500 | else if (state->cfg->clock_khz >= 24000) | ||
501 | r = 1; | ||
502 | else | ||
503 | r = 2; | ||
504 | |||
505 | r |= state->cfg->osc_buffer_state << 3; | ||
506 | |||
507 | dib0070_write_reg(state, 0x10, r); | ||
508 | dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 4)); | ||
509 | |||
510 | if (state->cfg->invert_iq) { | ||
511 | r = dib0070_read_reg(state, 0x02) & 0xffdf; | ||
512 | dib0070_write_reg(state, 0x02, r | (1 << 5)); | ||
513 | } | ||
514 | |||
515 | |||
516 | if (state->revision == DIB0070S_P1A) | ||
517 | dib0070_set_ctrl_lo5(state->fe, 4, 7, 3, 1); | ||
518 | else | ||
519 | dib0070_set_ctrl_lo5(state->fe, 4, 4, 2, 0); | ||
520 | |||
521 | dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); | ||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | |||
526 | static int dib0070_release(struct dvb_frontend *fe) | ||
527 | { | ||
528 | kfree(fe->tuner_priv); | ||
529 | fe->tuner_priv = NULL; | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | static struct dvb_tuner_ops dib0070_ops = { | ||
534 | .info = { | ||
535 | .name = "DiBcom DiB0070", | ||
536 | .frequency_min = 45000000, | ||
537 | .frequency_max = 860000000, | ||
538 | .frequency_step = 1000, | ||
539 | }, | ||
540 | .release = dib0070_release, | ||
541 | |||
542 | .init = dib0070_wakeup, | ||
543 | .sleep = dib0070_sleep, | ||
544 | .set_params = dib0070_tune_digital, | ||
545 | // .get_frequency = dib0070_get_frequency, | ||
546 | // .get_bandwidth = dib0070_get_bandwidth | ||
547 | }; | ||
548 | |||
549 | struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) | ||
550 | { | ||
551 | struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL); | ||
552 | if (state == NULL) | ||
553 | return NULL; | ||
554 | |||
555 | state->cfg = cfg; | ||
556 | state->i2c = i2c; | ||
557 | state->fe = fe; | ||
558 | fe->tuner_priv = state; | ||
559 | |||
560 | if (dib0070_reset(state) != 0) | ||
561 | goto free_mem; | ||
562 | |||
563 | dib0070_wbd_calibration(state); | ||
564 | |||
565 | printk(KERN_INFO "DiB0070: successfully identified\n"); | ||
566 | memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops)); | ||
567 | |||
568 | fe->tuner_priv = state; | ||
569 | return fe; | ||
570 | |||
571 | free_mem: | ||
572 | kfree(state); | ||
573 | fe->tuner_priv = NULL; | ||
574 | return NULL; | ||
575 | } | ||
576 | EXPORT_SYMBOL(dib0070_attach); | ||
577 | |||
578 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | ||
579 | MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner"); | ||
580 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h new file mode 100644 index 000000000000..786e37d33889 --- /dev/null +++ b/drivers/media/dvb/frontends/dib0070.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner. | ||
3 | * | ||
4 | * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | */ | ||
10 | #ifndef DIB0070_H | ||
11 | #define DIB0070_H | ||
12 | |||
13 | struct dvb_frontend; | ||
14 | struct i2c_adapter; | ||
15 | |||
16 | #define DEFAULT_DIB0070_I2C_ADDRESS 0x60 | ||
17 | |||
18 | struct dib0070_config { | ||
19 | u8 i2c_address; | ||
20 | |||
21 | /* tuner pins controlled externally */ | ||
22 | int (*reset) (struct dvb_frontend *, int); | ||
23 | int (*sleep) (struct dvb_frontend *, int); | ||
24 | |||
25 | /* offset in kHz */ | ||
26 | int freq_offset_khz_uhf; | ||
27 | int freq_offset_khz_vhf; | ||
28 | |||
29 | u8 osc_buffer_state; /* 0= normal, 1= tri-state */ | ||
30 | u32 clock_khz; | ||
31 | u8 clock_pad_drive; /* (Drive + 1) * 2mA */ | ||
32 | |||
33 | u8 invert_iq; /* invert Q - in case I or Q is inverted on the board */ | ||
34 | |||
35 | u8 force_crystal_mode; /* if == 0 -> decision is made in the driver default: <24 -> 2, >=24 -> 1 */ | ||
36 | |||
37 | u8 flip_chip; | ||
38 | }; | ||
39 | |||
40 | extern struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg); | ||
41 | extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open); | ||
42 | extern u16 dib0070_wbd_offset(struct dvb_frontend *); | ||
43 | |||
44 | #endif | ||
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c index b6adea5ffeb8..136b9d2164d7 100644 --- a/drivers/media/dvb/frontends/dib3000mb.c +++ b/drivers/media/dvb/frontends/dib3000mb.c | |||
@@ -23,7 +23,6 @@ | |||
23 | 23 | ||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/init.h> | 26 | #include <linux/init.h> |
28 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
29 | #include <linux/string.h> | 28 | #include <linux/string.h> |
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c index 054d7e6d9662..edae0be063f5 100644 --- a/drivers/media/dvb/frontends/dib3000mc.c +++ b/drivers/media/dvb/frontends/dib3000mc.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for DiBcom DiB3000MC/P-demodulator. | 2 | * Driver for DiBcom DiB3000MC/P-demodulator. |
3 | * | 3 | * |
4 | * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/) | 4 | * Copyright (C) 2004-7 DiBcom (http://www.dibcom.fr/) |
5 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | 5 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) |
6 | * | 6 | * |
7 | * This code is partially based on the previous dib3000mc.c . | 7 | * This code is partially based on the previous dib3000mc.c . |
@@ -13,10 +13,6 @@ | |||
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/i2c.h> | 15 | #include <linux/i2c.h> |
16 | //#include <linux/init.h> | ||
17 | //#include <linux/delay.h> | ||
18 | //#include <linux/string.h> | ||
19 | //#include <linux/slab.h> | ||
20 | 16 | ||
21 | #include "dvb_frontend.h" | 17 | #include "dvb_frontend.h" |
22 | 18 | ||
@@ -26,7 +22,11 @@ static int debug; | |||
26 | module_param(debug, int, 0644); | 22 | module_param(debug, int, 0644); |
27 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | 23 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); |
28 | 24 | ||
29 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0) | 25 | static int buggy_sfn_workaround; |
26 | module_param(buggy_sfn_workaround, int, 0644); | ||
27 | MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)"); | ||
28 | |||
29 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); printk("\n"); } } while (0) | ||
30 | 30 | ||
31 | struct dib3000mc_state { | 31 | struct dib3000mc_state { |
32 | struct dvb_frontend demod; | 32 | struct dvb_frontend demod; |
@@ -42,6 +42,8 @@ struct dib3000mc_state { | |||
42 | fe_bandwidth_t current_bandwidth; | 42 | fe_bandwidth_t current_bandwidth; |
43 | 43 | ||
44 | u16 dev_id; | 44 | u16 dev_id; |
45 | |||
46 | u8 sfn_workaround_active :1; | ||
45 | }; | 47 | }; |
46 | 48 | ||
47 | static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg) | 49 | static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg) |
@@ -71,7 +73,6 @@ static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val) | |||
71 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | 73 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; |
72 | } | 74 | } |
73 | 75 | ||
74 | |||
75 | static int dib3000mc_identify(struct dib3000mc_state *state) | 76 | static int dib3000mc_identify(struct dib3000mc_state *state) |
76 | { | 77 | { |
77 | u16 value; | 78 | u16 value; |
@@ -92,7 +93,7 @@ static int dib3000mc_identify(struct dib3000mc_state *state) | |||
92 | return 0; | 93 | return 0; |
93 | } | 94 | } |
94 | 95 | ||
95 | static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw, u8 update_offset) | 96 | static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u32 bw, u8 update_offset) |
96 | { | 97 | { |
97 | u32 timf; | 98 | u32 timf; |
98 | 99 | ||
@@ -103,7 +104,7 @@ static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw, | |||
103 | } else | 104 | } else |
104 | timf = state->timf; | 105 | timf = state->timf; |
105 | 106 | ||
106 | timf *= (BW_INDEX_TO_KHZ(bw) / 1000); | 107 | timf *= (bw / 1000); |
107 | 108 | ||
108 | if (update_offset) { | 109 | if (update_offset) { |
109 | s16 tim_offs = dib3000mc_read_word(state, 416); | 110 | s16 tim_offs = dib3000mc_read_word(state, 416); |
@@ -111,17 +112,17 @@ static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw, | |||
111 | if (tim_offs & 0x2000) | 112 | if (tim_offs & 0x2000) |
112 | tim_offs -= 0x4000; | 113 | tim_offs -= 0x4000; |
113 | 114 | ||
114 | if (nfft == 0) | 115 | if (nfft == TRANSMISSION_MODE_2K) |
115 | tim_offs *= 4; | 116 | tim_offs *= 4; |
116 | 117 | ||
117 | timf += tim_offs; | 118 | timf += tim_offs; |
118 | state->timf = timf / (BW_INDEX_TO_KHZ(bw) / 1000); | 119 | state->timf = timf / (bw / 1000); |
119 | } | 120 | } |
120 | 121 | ||
121 | dprintk("timf: %d\n", timf); | 122 | dprintk("timf: %d\n", timf); |
122 | 123 | ||
123 | dib3000mc_write_word(state, 23, timf >> 16); | 124 | dib3000mc_write_word(state, 23, (u16) (timf >> 16)); |
124 | dib3000mc_write_word(state, 24, timf & 0xffff); | 125 | dib3000mc_write_word(state, 24, (u16) (timf ) & 0xffff); |
125 | 126 | ||
126 | return 0; | 127 | return 0; |
127 | } | 128 | } |
@@ -209,31 +210,30 @@ static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode) | |||
209 | return ret; | 210 | return ret; |
210 | } | 211 | } |
211 | 212 | ||
212 | static int dib3000mc_set_bandwidth(struct dvb_frontend *demod, u8 bw) | 213 | static int dib3000mc_set_bandwidth(struct dib3000mc_state *state, u32 bw) |
213 | { | 214 | { |
214 | struct dib3000mc_state *state = demod->demodulator_priv; | ||
215 | u16 bw_cfg[6] = { 0 }; | 215 | u16 bw_cfg[6] = { 0 }; |
216 | u16 imp_bw_cfg[3] = { 0 }; | 216 | u16 imp_bw_cfg[3] = { 0 }; |
217 | u16 reg; | 217 | u16 reg; |
218 | 218 | ||
219 | /* settings here are for 27.7MHz */ | 219 | /* settings here are for 27.7MHz */ |
220 | switch (bw) { | 220 | switch (bw) { |
221 | case BANDWIDTH_8_MHZ: | 221 | case 8000: |
222 | bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20; | 222 | bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20; |
223 | imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7; | 223 | imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7; |
224 | break; | 224 | break; |
225 | 225 | ||
226 | case BANDWIDTH_7_MHZ: | 226 | case 7000: |
227 | bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7; | 227 | bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7; |
228 | imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0; | 228 | imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0; |
229 | break; | 229 | break; |
230 | 230 | ||
231 | case BANDWIDTH_6_MHZ: | 231 | case 6000: |
232 | bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5; | 232 | bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5; |
233 | imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089; | 233 | imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089; |
234 | break; | 234 | break; |
235 | 235 | ||
236 | case 255 /* BANDWIDTH_5_MHZ */: | 236 | case 5000: |
237 | bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500; | 237 | bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500; |
238 | imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072; | 238 | imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072; |
239 | break; | 239 | break; |
@@ -257,7 +257,7 @@ static int dib3000mc_set_bandwidth(struct dvb_frontend *demod, u8 bw) | |||
257 | dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]); | 257 | dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]); |
258 | 258 | ||
259 | // Timing configuration | 259 | // Timing configuration |
260 | dib3000mc_set_timing(state, 0, bw, 0); | 260 | dib3000mc_set_timing(state, TRANSMISSION_MODE_2K, bw, 0); |
261 | 261 | ||
262 | return 0; | 262 | return 0; |
263 | } | 263 | } |
@@ -276,7 +276,7 @@ static void dib3000mc_set_impulse_noise(struct dib3000mc_state *state, u8 mode, | |||
276 | for (i = 58; i < 87; i++) | 276 | for (i = 58; i < 87; i++) |
277 | dib3000mc_write_word(state, i, impulse_noise_val[i-58]); | 277 | dib3000mc_write_word(state, i, impulse_noise_val[i-58]); |
278 | 278 | ||
279 | if (nfft == 1) { | 279 | if (nfft == TRANSMISSION_MODE_8K) { |
280 | dib3000mc_write_word(state, 58, 0x3b); | 280 | dib3000mc_write_word(state, 58, 0x3b); |
281 | dib3000mc_write_word(state, 84, 0x00); | 281 | dib3000mc_write_word(state, 84, 0x00); |
282 | dib3000mc_write_word(state, 85, 0x8200); | 282 | dib3000mc_write_word(state, 85, 0x8200); |
@@ -376,7 +376,7 @@ static int dib3000mc_init(struct dvb_frontend *demod) | |||
376 | // P_search_maxtrial=1 | 376 | // P_search_maxtrial=1 |
377 | dib3000mc_write_word(state, 5, 1); | 377 | dib3000mc_write_word(state, 5, 1); |
378 | 378 | ||
379 | dib3000mc_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); | 379 | dib3000mc_set_bandwidth(state, 8000); |
380 | 380 | ||
381 | // div_lock_mask | 381 | // div_lock_mask |
382 | dib3000mc_write_word(state, 4, 0x814); | 382 | dib3000mc_write_word(state, 4, 0x814); |
@@ -397,7 +397,7 @@ static int dib3000mc_init(struct dvb_frontend *demod) | |||
397 | dib3000mc_write_word(state, 180, 0x2FF0); | 397 | dib3000mc_write_word(state, 180, 0x2FF0); |
398 | 398 | ||
399 | // Impulse noise configuration | 399 | // Impulse noise configuration |
400 | dib3000mc_set_impulse_noise(state, 0, 1); | 400 | dib3000mc_set_impulse_noise(state, 0, TRANSMISSION_MODE_8K); |
401 | 401 | ||
402 | // output mode set-up | 402 | // output mode set-up |
403 | dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z); | 403 | dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z); |
@@ -423,13 +423,13 @@ static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam) | |||
423 | { | 423 | { |
424 | u16 cfg[4] = { 0 },reg; | 424 | u16 cfg[4] = { 0 },reg; |
425 | switch (qam) { | 425 | switch (qam) { |
426 | case 0: | 426 | case QPSK: |
427 | cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0; | 427 | cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0; |
428 | break; | 428 | break; |
429 | case 1: | 429 | case QAM_16: |
430 | cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0; | 430 | cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0; |
431 | break; | 431 | break; |
432 | case 2: | 432 | case QAM_64: |
433 | cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8; | 433 | cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8; |
434 | break; | 434 | break; |
435 | } | 435 | } |
@@ -437,11 +437,11 @@ static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam) | |||
437 | dib3000mc_write_word(state, reg, cfg[reg - 129]); | 437 | dib3000mc_write_word(state, reg, cfg[reg - 129]); |
438 | } | 438 | } |
439 | 439 | ||
440 | static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx000_ofdm_channel *chan, u16 seq) | 440 | static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dvb_frontend_parameters *ch, u16 seq) |
441 | { | 441 | { |
442 | u16 tmp; | 442 | u16 value; |
443 | 443 | dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)); | |
444 | dib3000mc_set_timing(state, chan->nfft, chan->Bw, 0); | 444 | dib3000mc_set_timing(state, ch->u.ofdm.transmission_mode, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth), 0); |
445 | 445 | ||
446 | // if (boost) | 446 | // if (boost) |
447 | // dib3000mc_write_word(state, 100, (11 << 6) + 6); | 447 | // dib3000mc_write_word(state, 100, (11 << 6) + 6); |
@@ -455,7 +455,7 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx | |||
455 | dib3000mc_write_word(state, 26, 0x6680); | 455 | dib3000mc_write_word(state, 26, 0x6680); |
456 | dib3000mc_write_word(state, 29, 0x1273); | 456 | dib3000mc_write_word(state, 29, 0x1273); |
457 | dib3000mc_write_word(state, 33, 5); | 457 | dib3000mc_write_word(state, 33, 5); |
458 | dib3000mc_set_adp_cfg(state, 1); | 458 | dib3000mc_set_adp_cfg(state, QAM_16); |
459 | dib3000mc_write_word(state, 133, 15564); | 459 | dib3000mc_write_word(state, 133, 15564); |
460 | 460 | ||
461 | dib3000mc_write_word(state, 12 , 0x0); | 461 | dib3000mc_write_word(state, 12 , 0x0); |
@@ -470,52 +470,98 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx | |||
470 | dib3000mc_write_word(state, 97,0); | 470 | dib3000mc_write_word(state, 97,0); |
471 | dib3000mc_write_word(state, 98,0); | 471 | dib3000mc_write_word(state, 98,0); |
472 | 472 | ||
473 | dib3000mc_set_impulse_noise(state, 0, chan->nfft); | 473 | dib3000mc_set_impulse_noise(state, 0, ch->u.ofdm.transmission_mode); |
474 | |||
475 | tmp = ((chan->nfft & 0x1) << 7) | (chan->guard << 5) | (chan->nqam << 3) | chan->vit_alpha; | ||
476 | dib3000mc_write_word(state, 0, tmp); | ||
477 | 474 | ||
475 | value = 0; | ||
476 | switch (ch->u.ofdm.transmission_mode) { | ||
477 | case TRANSMISSION_MODE_2K: value |= (0 << 7); break; | ||
478 | default: | ||
479 | case TRANSMISSION_MODE_8K: value |= (1 << 7); break; | ||
480 | } | ||
481 | switch (ch->u.ofdm.guard_interval) { | ||
482 | case GUARD_INTERVAL_1_32: value |= (0 << 5); break; | ||
483 | case GUARD_INTERVAL_1_16: value |= (1 << 5); break; | ||
484 | case GUARD_INTERVAL_1_4: value |= (3 << 5); break; | ||
485 | default: | ||
486 | case GUARD_INTERVAL_1_8: value |= (2 << 5); break; | ||
487 | } | ||
488 | switch (ch->u.ofdm.constellation) { | ||
489 | case QPSK: value |= (0 << 3); break; | ||
490 | case QAM_16: value |= (1 << 3); break; | ||
491 | default: | ||
492 | case QAM_64: value |= (2 << 3); break; | ||
493 | } | ||
494 | switch (HIERARCHY_1) { | ||
495 | case HIERARCHY_2: value |= 2; break; | ||
496 | case HIERARCHY_4: value |= 4; break; | ||
497 | default: | ||
498 | case HIERARCHY_1: value |= 1; break; | ||
499 | } | ||
500 | dib3000mc_write_word(state, 0, value); | ||
478 | dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4)); | 501 | dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4)); |
479 | 502 | ||
480 | tmp = (chan->vit_hrch << 4) | (chan->vit_select_hp); | 503 | value = 0; |
481 | if (!chan->vit_hrch || (chan->vit_hrch && chan->vit_select_hp)) | 504 | if (ch->u.ofdm.hierarchy_information == 1) |
482 | tmp |= chan->vit_code_rate_hp << 1; | 505 | value |= (1 << 4); |
483 | else | 506 | if (1 == 1) |
484 | tmp |= chan->vit_code_rate_lp << 1; | 507 | value |= 1; |
485 | dib3000mc_write_word(state, 181, tmp); | 508 | switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) { |
509 | case FEC_2_3: value |= (2 << 1); break; | ||
510 | case FEC_3_4: value |= (3 << 1); break; | ||
511 | case FEC_5_6: value |= (5 << 1); break; | ||
512 | case FEC_7_8: value |= (7 << 1); break; | ||
513 | default: | ||
514 | case FEC_1_2: value |= (1 << 1); break; | ||
515 | } | ||
516 | dib3000mc_write_word(state, 181, value); | ||
486 | 517 | ||
487 | // diversity synchro delay | 518 | // diversity synchro delay add 50% SFN margin |
488 | tmp = dib3000mc_read_word(state, 180) & 0x000f; | 519 | switch (ch->u.ofdm.transmission_mode) { |
489 | tmp |= ((chan->nfft == 0) ? 64 : 256) * ((1 << (chan->guard)) * 3 / 2) << 4; // add 50% SFN margin | 520 | case TRANSMISSION_MODE_8K: value = 256; break; |
490 | dib3000mc_write_word(state, 180, tmp); | 521 | case TRANSMISSION_MODE_2K: |
522 | default: value = 64; break; | ||
523 | } | ||
524 | switch (ch->u.ofdm.guard_interval) { | ||
525 | case GUARD_INTERVAL_1_16: value *= 2; break; | ||
526 | case GUARD_INTERVAL_1_8: value *= 4; break; | ||
527 | case GUARD_INTERVAL_1_4: value *= 8; break; | ||
528 | default: | ||
529 | case GUARD_INTERVAL_1_32: value *= 1; break; | ||
530 | } | ||
531 | value <<= 4; | ||
532 | value |= dib3000mc_read_word(state, 180) & 0x000f; | ||
533 | dib3000mc_write_word(state, 180, value); | ||
491 | 534 | ||
492 | // restart demod | 535 | // restart demod |
493 | tmp = dib3000mc_read_word(state, 0); | 536 | value = dib3000mc_read_word(state, 0); |
494 | dib3000mc_write_word(state, 0, tmp | (1 << 9)); | 537 | dib3000mc_write_word(state, 0, value | (1 << 9)); |
495 | dib3000mc_write_word(state, 0, tmp); | 538 | dib3000mc_write_word(state, 0, value); |
496 | 539 | ||
497 | msleep(30); | 540 | msleep(30); |
498 | 541 | ||
499 | dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, chan->nfft); | 542 | dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, ch->u.ofdm.transmission_mode); |
500 | } | 543 | } |
501 | 544 | ||
502 | static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *chan) | 545 | static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *chan) |
503 | { | 546 | { |
504 | struct dib3000mc_state *state = demod->demodulator_priv; | 547 | struct dib3000mc_state *state = demod->demodulator_priv; |
505 | u16 reg; | 548 | u16 reg; |
506 | // u32 val; | 549 | // u32 val; |
507 | struct dibx000_ofdm_channel fchan; | 550 | struct dvb_frontend_parameters schan; |
508 | 551 | ||
509 | INIT_OFDM_CHANNEL(&fchan); | 552 | schan = *chan; |
510 | fchan = *chan; | ||
511 | 553 | ||
554 | /* TODO what is that ? */ | ||
512 | 555 | ||
513 | /* a channel for autosearch */ | 556 | /* a channel for autosearch */ |
514 | fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2; | 557 | schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; |
515 | fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2; | 558 | schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32; |
516 | fchan.vit_hrch = 0; fchan.vit_select_hp = 1; | 559 | schan.u.ofdm.constellation = QAM_64; |
560 | schan.u.ofdm.code_rate_HP = FEC_2_3; | ||
561 | schan.u.ofdm.code_rate_LP = FEC_2_3; | ||
562 | schan.u.ofdm.hierarchy_information = 0; | ||
517 | 563 | ||
518 | dib3000mc_set_channel_cfg(state, &fchan, 11); | 564 | dib3000mc_set_channel_cfg(state, &schan, 11); |
519 | 565 | ||
520 | reg = dib3000mc_read_word(state, 0); | 566 | reg = dib3000mc_read_word(state, 0); |
521 | dib3000mc_write_word(state, 0, reg | (1 << 8)); | 567 | dib3000mc_write_word(state, 0, reg | (1 << 8)); |
@@ -539,7 +585,7 @@ static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod) | |||
539 | return 0; // still pending | 585 | return 0; // still pending |
540 | } | 586 | } |
541 | 587 | ||
542 | static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | 588 | static int dib3000mc_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch) |
543 | { | 589 | { |
544 | struct dib3000mc_state *state = demod->demodulator_priv; | 590 | struct dib3000mc_state *state = demod->demodulator_priv; |
545 | 591 | ||
@@ -547,11 +593,17 @@ static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channe | |||
547 | dib3000mc_set_channel_cfg(state, ch, 0); | 593 | dib3000mc_set_channel_cfg(state, ch, 0); |
548 | 594 | ||
549 | // activates isi | 595 | // activates isi |
550 | dib3000mc_write_word(state, 29, 0x1073); | 596 | if (state->sfn_workaround_active) { |
551 | 597 | dprintk("SFN workaround is active\n"); | |
552 | dib3000mc_set_adp_cfg(state, (u8)ch->nqam); | 598 | dib3000mc_write_word(state, 29, 0x1273); |
599 | dib3000mc_write_word(state, 108, 0x4000); // P_pha3_force_pha_shift | ||
600 | } else { | ||
601 | dib3000mc_write_word(state, 29, 0x1073); | ||
602 | dib3000mc_write_word(state, 108, 0x0000); // P_pha3_force_pha_shift | ||
603 | } | ||
553 | 604 | ||
554 | if (ch->nfft == 1) { | 605 | dib3000mc_set_adp_cfg(state, (u8)ch->u.ofdm.constellation); |
606 | if (ch->u.ofdm.transmission_mode == TRANSMISSION_MODE_8K) { | ||
555 | dib3000mc_write_word(state, 26, 38528); | 607 | dib3000mc_write_word(state, 26, 38528); |
556 | dib3000mc_write_word(state, 33, 8); | 608 | dib3000mc_write_word(state, 33, 8); |
557 | } else { | 609 | } else { |
@@ -560,7 +612,7 @@ static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channe | |||
560 | } | 612 | } |
561 | 613 | ||
562 | if (dib3000mc_read_word(state, 509) & 0x80) | 614 | if (dib3000mc_read_word(state, 509) & 0x80) |
563 | dib3000mc_set_timing(state, ch->nfft, ch->Bw, 1); | 615 | dib3000mc_set_timing(state, ch->u.ofdm.transmission_mode, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth), 1); |
564 | 616 | ||
565 | return 0; | 617 | return 0; |
566 | } | 618 | } |
@@ -632,13 +684,12 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe, | |||
632 | struct dvb_frontend_parameters *fep) | 684 | struct dvb_frontend_parameters *fep) |
633 | { | 685 | { |
634 | struct dib3000mc_state *state = fe->demodulator_priv; | 686 | struct dib3000mc_state *state = fe->demodulator_priv; |
635 | struct dibx000_ofdm_channel ch; | ||
636 | |||
637 | INIT_OFDM_CHANNEL(&ch); | ||
638 | FEP2DIB(fep,&ch); | ||
639 | 687 | ||
640 | state->current_bandwidth = fep->u.ofdm.bandwidth; | 688 | state->current_bandwidth = fep->u.ofdm.bandwidth; |
641 | dib3000mc_set_bandwidth(fe, fep->u.ofdm.bandwidth); | 689 | dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth)); |
690 | |||
691 | /* maybe the parameter has been changed */ | ||
692 | state->sfn_workaround_active = buggy_sfn_workaround; | ||
642 | 693 | ||
643 | if (fe->ops.tuner_ops.set_params) { | 694 | if (fe->ops.tuner_ops.set_params) { |
644 | fe->ops.tuner_ops.set_params(fe, fep); | 695 | fe->ops.tuner_ops.set_params(fe, fep); |
@@ -651,7 +702,7 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe, | |||
651 | fep->u.ofdm.code_rate_HP == FEC_AUTO) { | 702 | fep->u.ofdm.code_rate_HP == FEC_AUTO) { |
652 | int i = 100, found; | 703 | int i = 100, found; |
653 | 704 | ||
654 | dib3000mc_autosearch_start(fe, &ch); | 705 | dib3000mc_autosearch_start(fe, fep); |
655 | do { | 706 | do { |
656 | msleep(1); | 707 | msleep(1); |
657 | found = dib3000mc_autosearch_is_irq(fe); | 708 | found = dib3000mc_autosearch_is_irq(fe); |
@@ -662,13 +713,12 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe, | |||
662 | return 0; // no channel found | 713 | return 0; // no channel found |
663 | 714 | ||
664 | dib3000mc_get_frontend(fe, fep); | 715 | dib3000mc_get_frontend(fe, fep); |
665 | FEP2DIB(fep,&ch); | ||
666 | } | 716 | } |
667 | 717 | ||
668 | /* make this a config parameter */ | 718 | /* make this a config parameter */ |
669 | dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO); | 719 | dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO); |
670 | 720 | ||
671 | return dib3000mc_tune(fe, &ch); | 721 | return dib3000mc_tune(fe, fep); |
672 | } | 722 | } |
673 | 723 | ||
674 | static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat) | 724 | static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat) |
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c index f64546c6aeb5..fb18441a8c57 100644 --- a/drivers/media/dvb/frontends/dib7000m.c +++ b/drivers/media/dvb/frontends/dib7000m.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Linux-DVB Driver for DiBcom's DiB7000M and | 2 | * Linux-DVB Driver for DiBcom's DiB7000M and |
3 | * first generation DiB7000P-demodulator-family. | 3 | * first generation DiB7000P-demodulator-family. |
4 | * | 4 | * |
5 | * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/) | 5 | * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/) |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License as | 8 | * modify it under the terms of the GNU General Public License as |
@@ -19,7 +19,7 @@ static int debug; | |||
19 | module_param(debug, int, 0644); | 19 | module_param(debug, int, 0644); |
20 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | 20 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); |
21 | 21 | ||
22 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M:"); printk(args); } } while (0) | 22 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M: "); printk(args); printk("\n"); } } while (0) |
23 | 23 | ||
24 | struct dib7000m_state { | 24 | struct dib7000m_state { |
25 | struct dvb_frontend demod; | 25 | struct dvb_frontend demod; |
@@ -39,8 +39,16 @@ struct dib7000m_state { | |||
39 | fe_bandwidth_t current_bandwidth; | 39 | fe_bandwidth_t current_bandwidth; |
40 | struct dibx000_agc_config *current_agc; | 40 | struct dibx000_agc_config *current_agc; |
41 | u32 timf; | 41 | u32 timf; |
42 | u32 timf_default; | ||
43 | u32 internal_clk; | ||
44 | |||
45 | u8 div_force_off : 1; | ||
46 | u8 div_state : 1; | ||
47 | u16 div_sync_wait; | ||
42 | 48 | ||
43 | u16 revision; | 49 | u16 revision; |
50 | |||
51 | u8 agc_state; | ||
44 | }; | 52 | }; |
45 | 53 | ||
46 | enum dib7000m_power_mode { | 54 | enum dib7000m_power_mode { |
@@ -63,7 +71,7 @@ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) | |||
63 | }; | 71 | }; |
64 | 72 | ||
65 | if (i2c_transfer(state->i2c_adap, msg, 2) != 2) | 73 | if (i2c_transfer(state->i2c_adap, msg, 2) != 2) |
66 | dprintk("i2c read error on %d\n",reg); | 74 | dprintk("i2c read error on %d",reg); |
67 | 75 | ||
68 | return (rb[0] << 8) | rb[1]; | 76 | return (rb[0] << 8) | rb[1]; |
69 | } | 77 | } |
@@ -79,6 +87,25 @@ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) | |||
79 | }; | 87 | }; |
80 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | 88 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; |
81 | } | 89 | } |
90 | static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf) | ||
91 | { | ||
92 | u16 l = 0, r, *n; | ||
93 | n = buf; | ||
94 | l = *n++; | ||
95 | while (l) { | ||
96 | r = *n++; | ||
97 | |||
98 | if (state->reg_offs && (r >= 112 && r <= 331)) // compensate for 7000MC | ||
99 | r++; | ||
100 | |||
101 | do { | ||
102 | dib7000m_write_word(state, r, *n++); | ||
103 | r++; | ||
104 | } while (--l); | ||
105 | l = *n++; | ||
106 | } | ||
107 | } | ||
108 | |||
82 | static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode) | 109 | static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode) |
83 | { | 110 | { |
84 | int ret = 0; | 111 | int ret = 0; |
@@ -89,8 +116,7 @@ static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode) | |||
89 | fifo_threshold = 1792; | 116 | fifo_threshold = 1792; |
90 | smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1); | 117 | smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1); |
91 | 118 | ||
92 | dprintk("-I- Setting output mode for demod %p to %d\n", | 119 | dprintk( "setting output mode for demod %p to %d", &state->demod, mode); |
93 | &state->demod, mode); | ||
94 | 120 | ||
95 | switch (mode) { | 121 | switch (mode) { |
96 | case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock | 122 | case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock |
@@ -117,7 +143,7 @@ static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode) | |||
117 | outreg = 0; | 143 | outreg = 0; |
118 | break; | 144 | break; |
119 | default: | 145 | default: |
120 | dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); | 146 | dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod); |
121 | break; | 147 | break; |
122 | } | 148 | } |
123 | 149 | ||
@@ -129,13 +155,20 @@ static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode) | |||
129 | ret |= dib7000m_write_word(state, 1795, outreg); | 155 | ret |= dib7000m_write_word(state, 1795, outreg); |
130 | ret |= dib7000m_write_word(state, 1805, sram); | 156 | ret |= dib7000m_write_word(state, 1805, sram); |
131 | 157 | ||
158 | if (state->revision == 0x4003) { | ||
159 | u16 clk_cfg1 = dib7000m_read_word(state, 909) & 0xfffd; | ||
160 | if (mode == OUTMODE_DIVERSITY) | ||
161 | clk_cfg1 |= (1 << 1); // P_O_CLK_en | ||
162 | dib7000m_write_word(state, 909, clk_cfg1); | ||
163 | } | ||
132 | return ret; | 164 | return ret; |
133 | } | 165 | } |
134 | 166 | ||
135 | static int dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode) | 167 | static void dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode) |
136 | { | 168 | { |
137 | /* by default everything is going to be powered off */ | 169 | /* by default everything is going to be powered off */ |
138 | u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff; | 170 | u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff; |
171 | u8 offset = 0; | ||
139 | 172 | ||
140 | /* now, depending on the requested mode, we power on */ | 173 | /* now, depending on the requested mode, we power on */ |
141 | switch (mode) { | 174 | switch (mode) { |
@@ -170,16 +203,17 @@ static int dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_p | |||
170 | if (!state->cfg.mobile_mode) | 203 | if (!state->cfg.mobile_mode) |
171 | reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1); | 204 | reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1); |
172 | 205 | ||
173 | /* P_sdio_select_clk = 0 on MC */ | 206 | /* P_sdio_select_clk = 0 on MC and after*/ |
174 | if (state->revision != 0x4000) | 207 | if (state->revision != 0x4000) |
175 | reg_906 <<= 1; | 208 | reg_906 <<= 1; |
176 | 209 | ||
177 | dib7000m_write_word(state, 903, reg_903); | 210 | if (state->revision == 0x4003) |
178 | dib7000m_write_word(state, 904, reg_904); | 211 | offset = 1; |
179 | dib7000m_write_word(state, 905, reg_905); | ||
180 | dib7000m_write_word(state, 906, reg_906); | ||
181 | 212 | ||
182 | return 0; | 213 | dib7000m_write_word(state, 903 + offset, reg_903); |
214 | dib7000m_write_word(state, 904 + offset, reg_904); | ||
215 | dib7000m_write_word(state, 905 + offset, reg_905); | ||
216 | dib7000m_write_word(state, 906 + offset, reg_906); | ||
183 | } | 217 | } |
184 | 218 | ||
185 | static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no) | 219 | static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no) |
@@ -230,34 +264,55 @@ static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc | |||
230 | break; | 264 | break; |
231 | } | 265 | } |
232 | 266 | ||
233 | // dprintk("-D- 913: %x, 914: %x\n", reg_913, reg_914); | 267 | // dprintk( "913: %x, 914: %x", reg_913, reg_914); |
234 | |||
235 | ret |= dib7000m_write_word(state, 913, reg_913); | 268 | ret |= dib7000m_write_word(state, 913, reg_913); |
236 | ret |= dib7000m_write_word(state, 914, reg_914); | 269 | ret |= dib7000m_write_word(state, 914, reg_914); |
237 | 270 | ||
238 | return ret; | 271 | return ret; |
239 | } | 272 | } |
240 | 273 | ||
241 | static int dib7000m_set_bandwidth(struct dvb_frontend *demod, u8 bw_idx) | 274 | static int dib7000m_set_bandwidth(struct dib7000m_state *state, u32 bw) |
242 | { | 275 | { |
243 | struct dib7000m_state *state = demod->demodulator_priv; | ||
244 | u32 timf; | 276 | u32 timf; |
245 | 277 | ||
246 | // store the current bandwidth for later use | 278 | // store the current bandwidth for later use |
247 | state->current_bandwidth = bw_idx; | 279 | state->current_bandwidth = bw; |
248 | 280 | ||
249 | if (state->timf == 0) { | 281 | if (state->timf == 0) { |
250 | dprintk("-D- Using default timf\n"); | 282 | dprintk( "using default timf"); |
251 | timf = state->cfg.bw->timf; | 283 | timf = state->timf_default; |
252 | } else { | 284 | } else { |
253 | dprintk("-D- Using updated timf\n"); | 285 | dprintk( "using updated timf"); |
254 | timf = state->timf; | 286 | timf = state->timf; |
255 | } | 287 | } |
256 | 288 | ||
257 | timf = timf * (BW_INDEX_TO_KHZ(bw_idx) / 100) / 80; | 289 | timf = timf * (bw / 50) / 160; |
258 | 290 | ||
259 | dib7000m_write_word(state, 23, (timf >> 16) & 0xffff); | 291 | dib7000m_write_word(state, 23, (u16) ((timf >> 16) & 0xffff)); |
260 | dib7000m_write_word(state, 24, (timf ) & 0xffff); | 292 | dib7000m_write_word(state, 24, (u16) ((timf ) & 0xffff)); |
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static int dib7000m_set_diversity_in(struct dvb_frontend *demod, int onoff) | ||
298 | { | ||
299 | struct dib7000m_state *state = demod->demodulator_priv; | ||
300 | |||
301 | if (state->div_force_off) { | ||
302 | dprintk( "diversity combination deactivated - forced by COFDM parameters"); | ||
303 | onoff = 0; | ||
304 | } | ||
305 | state->div_state = (u8)onoff; | ||
306 | |||
307 | if (onoff) { | ||
308 | dib7000m_write_word(state, 263 + state->reg_offs, 6); | ||
309 | dib7000m_write_word(state, 264 + state->reg_offs, 6); | ||
310 | dib7000m_write_word(state, 266 + state->reg_offs, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0)); | ||
311 | } else { | ||
312 | dib7000m_write_word(state, 263 + state->reg_offs, 1); | ||
313 | dib7000m_write_word(state, 264 + state->reg_offs, 0); | ||
314 | dib7000m_write_word(state, 266 + state->reg_offs, 0); | ||
315 | } | ||
261 | 316 | ||
262 | return 0; | 317 | return 0; |
263 | } | 318 | } |
@@ -266,7 +321,7 @@ static int dib7000m_sad_calib(struct dib7000m_state *state) | |||
266 | { | 321 | { |
267 | 322 | ||
268 | /* internal */ | 323 | /* internal */ |
269 | // dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is written in set_bandwidth | 324 | // dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth |
270 | dib7000m_write_word(state, 929, (0 << 1) | (0 << 0)); | 325 | dib7000m_write_word(state, 929, (0 << 1) | (0 << 0)); |
271 | dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096 | 326 | dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096 |
272 | 327 | ||
@@ -281,10 +336,10 @@ static int dib7000m_sad_calib(struct dib7000m_state *state) | |||
281 | 336 | ||
282 | static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw) | 337 | static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw) |
283 | { | 338 | { |
284 | dib7000m_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff); | 339 | dib7000m_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff)); |
285 | dib7000m_write_word(state, 19, (bw->internal*1000) & 0xffff); | 340 | dib7000m_write_word(state, 19, (u16) ( (bw->internal*1000) & 0xffff)); |
286 | dib7000m_write_word(state, 21, (bw->ifreq >> 16) & 0xffff); | 341 | dib7000m_write_word(state, 21, (u16) ( (bw->ifreq >> 16) & 0xffff)); |
287 | dib7000m_write_word(state, 22, bw->ifreq & 0xffff); | 342 | dib7000m_write_word(state, 22, (u16) ( bw->ifreq & 0xffff)); |
288 | 343 | ||
289 | dib7000m_write_word(state, 928, bw->sad_cfg); | 344 | dib7000m_write_word(state, 928, bw->sad_cfg); |
290 | } | 345 | } |
@@ -325,15 +380,19 @@ static void dib7000m_reset_pll(struct dib7000m_state *state) | |||
325 | static void dib7000mc_reset_pll(struct dib7000m_state *state) | 380 | static void dib7000mc_reset_pll(struct dib7000m_state *state) |
326 | { | 381 | { |
327 | const struct dibx000_bandwidth_config *bw = state->cfg.bw; | 382 | const struct dibx000_bandwidth_config *bw = state->cfg.bw; |
383 | u16 clk_cfg1; | ||
328 | 384 | ||
329 | // clk_cfg0 | 385 | // clk_cfg0 |
330 | dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0)); | 386 | dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0)); |
331 | 387 | ||
332 | // clk_cfg1 | 388 | // clk_cfg1 |
333 | //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) | | 389 | //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) | |
334 | dib7000m_write_word(state, 908, (0 << 14) | (3 << 12) |(0 << 11) | | 390 | clk_cfg1 = (0 << 14) | (3 << 12) |(0 << 11) | |
335 | (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) | | 391 | (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) | |
336 | (bw->pll_bypass << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0)); | 392 | (1 << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0); |
393 | dib7000m_write_word(state, 908, clk_cfg1); | ||
394 | clk_cfg1 = (clk_cfg1 & 0xfff7) | (bw->pll_bypass << 3); | ||
395 | dib7000m_write_word(state, 908, clk_cfg1); | ||
337 | 396 | ||
338 | // smpl_cfg | 397 | // smpl_cfg |
339 | dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7)); | 398 | dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7)); |
@@ -344,9 +403,6 @@ static void dib7000mc_reset_pll(struct dib7000m_state *state) | |||
344 | static int dib7000m_reset_gpio(struct dib7000m_state *st) | 403 | static int dib7000m_reset_gpio(struct dib7000m_state *st) |
345 | { | 404 | { |
346 | /* reset the GPIOs */ | 405 | /* reset the GPIOs */ |
347 | dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n", | ||
348 | st->cfg.gpio_dir, st->cfg.gpio_val,st->cfg.gpio_pwm_pos); | ||
349 | |||
350 | dib7000m_write_word(st, 773, st->cfg.gpio_dir); | 406 | dib7000m_write_word(st, 773, st->cfg.gpio_dir); |
351 | dib7000m_write_word(st, 774, st->cfg.gpio_val); | 407 | dib7000m_write_word(st, 774, st->cfg.gpio_val); |
352 | 408 | ||
@@ -358,6 +414,107 @@ static int dib7000m_reset_gpio(struct dib7000m_state *st) | |||
358 | return 0; | 414 | return 0; |
359 | } | 415 | } |
360 | 416 | ||
417 | static u16 dib7000m_defaults_common[] = | ||
418 | |||
419 | { | ||
420 | // auto search configuration | ||
421 | 3, 2, | ||
422 | 0x0004, | ||
423 | 0x1000, | ||
424 | 0x0814, | ||
425 | |||
426 | 12, 6, | ||
427 | 0x001b, | ||
428 | 0x7740, | ||
429 | 0x005b, | ||
430 | 0x8d80, | ||
431 | 0x01c9, | ||
432 | 0xc380, | ||
433 | 0x0000, | ||
434 | 0x0080, | ||
435 | 0x0000, | ||
436 | 0x0090, | ||
437 | 0x0001, | ||
438 | 0xd4c0, | ||
439 | |||
440 | 1, 26, | ||
441 | 0x6680, // P_corm_thres Lock algorithms configuration | ||
442 | |||
443 | 1, 170, | ||
444 | 0x0410, // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on | ||
445 | |||
446 | 8, 173, | ||
447 | 0, | ||
448 | 0, | ||
449 | 0, | ||
450 | 0, | ||
451 | 0, | ||
452 | 0, | ||
453 | 0, | ||
454 | 0, | ||
455 | |||
456 | 1, 182, | ||
457 | 8192, // P_fft_nb_to_cut | ||
458 | |||
459 | 2, 195, | ||
460 | 0x0ccd, // P_pha3_thres | ||
461 | 0, // P_cti_use_cpe, P_cti_use_prog | ||
462 | |||
463 | 1, 205, | ||
464 | 0x200f, // P_cspu_regul, P_cspu_win_cut | ||
465 | |||
466 | 5, 214, | ||
467 | 0x023d, // P_adp_regul_cnt | ||
468 | 0x00a4, // P_adp_noise_cnt | ||
469 | 0x00a4, // P_adp_regul_ext | ||
470 | 0x7ff0, // P_adp_noise_ext | ||
471 | 0x3ccc, // P_adp_fil | ||
472 | |||
473 | 1, 226, | ||
474 | 0, // P_2d_byp_ti_num | ||
475 | |||
476 | 1, 255, | ||
477 | 0x800, // P_equal_thres_wgn | ||
478 | |||
479 | 1, 263, | ||
480 | 0x0001, | ||
481 | |||
482 | 1, 281, | ||
483 | 0x0010, // P_fec_* | ||
484 | |||
485 | 1, 294, | ||
486 | 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard | ||
487 | |||
488 | 0 | ||
489 | }; | ||
490 | |||
491 | static u16 dib7000m_defaults[] = | ||
492 | |||
493 | { | ||
494 | /* set ADC level to -16 */ | ||
495 | 11, 76, | ||
496 | (1 << 13) - 825 - 117, | ||
497 | (1 << 13) - 837 - 117, | ||
498 | (1 << 13) - 811 - 117, | ||
499 | (1 << 13) - 766 - 117, | ||
500 | (1 << 13) - 737 - 117, | ||
501 | (1 << 13) - 693 - 117, | ||
502 | (1 << 13) - 648 - 117, | ||
503 | (1 << 13) - 619 - 117, | ||
504 | (1 << 13) - 575 - 117, | ||
505 | (1 << 13) - 531 - 117, | ||
506 | (1 << 13) - 501 - 117, | ||
507 | |||
508 | // Tuner IO bank: max drive (14mA) | ||
509 | 1, 912, | ||
510 | 0x2c8a, | ||
511 | |||
512 | 1, 1817, | ||
513 | 1, | ||
514 | |||
515 | 0, | ||
516 | }; | ||
517 | |||
361 | static int dib7000m_demod_reset(struct dib7000m_state *state) | 518 | static int dib7000m_demod_reset(struct dib7000m_state *state) |
362 | { | 519 | { |
363 | dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); | 520 | dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); |
@@ -382,22 +539,47 @@ static int dib7000m_demod_reset(struct dib7000m_state *state) | |||
382 | dib7000mc_reset_pll(state); | 539 | dib7000mc_reset_pll(state); |
383 | 540 | ||
384 | if (dib7000m_reset_gpio(state) != 0) | 541 | if (dib7000m_reset_gpio(state) != 0) |
385 | dprintk("-E- GPIO reset was not successful.\n"); | 542 | dprintk( "GPIO reset was not successful."); |
386 | 543 | ||
387 | if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0) | 544 | if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0) |
388 | dprintk("-E- OUTPUT_MODE could not be resetted.\n"); | 545 | dprintk( "OUTPUT_MODE could not be reset."); |
389 | 546 | ||
390 | /* unforce divstr regardless whether i2c enumeration was done or not */ | 547 | /* unforce divstr regardless whether i2c enumeration was done or not */ |
391 | dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) ); | 548 | dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) ); |
392 | 549 | ||
393 | dib7000m_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); | 550 | dib7000m_set_bandwidth(state, 8000); |
394 | 551 | ||
395 | dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON); | 552 | dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON); |
396 | dib7000m_sad_calib(state); | 553 | dib7000m_sad_calib(state); |
397 | dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF); | 554 | dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF); |
398 | 555 | ||
556 | if (state->cfg.dvbt_mode) | ||
557 | dib7000m_write_word(state, 1796, 0x0); // select DVB-T output | ||
558 | |||
559 | if (state->cfg.mobile_mode) | ||
560 | dib7000m_write_word(state, 261 + state->reg_offs, 2); | ||
561 | else | ||
562 | dib7000m_write_word(state, 224 + state->reg_offs, 1); | ||
563 | |||
564 | // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... | ||
565 | if(state->cfg.tuner_is_baseband) | ||
566 | dib7000m_write_word(state, 36, 0x0755); | ||
567 | else | ||
568 | dib7000m_write_word(state, 36, 0x1f55); | ||
569 | |||
570 | // P_divclksel=3 P_divbitsel=1 | ||
571 | if (state->revision == 0x4000) | ||
572 | dib7000m_write_word(state, 909, (3 << 10) | (1 << 6)); | ||
573 | else | ||
574 | dib7000m_write_word(state, 909, (3 << 4) | 1); | ||
575 | |||
576 | dib7000m_write_tab(state, dib7000m_defaults_common); | ||
577 | dib7000m_write_tab(state, dib7000m_defaults); | ||
578 | |||
399 | dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY); | 579 | dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY); |
400 | 580 | ||
581 | state->internal_clk = state->cfg.bw->internal; | ||
582 | |||
401 | return 0; | 583 | return 0; |
402 | } | 584 | } |
403 | 585 | ||
@@ -427,7 +609,7 @@ static int dib7000m_agc_soft_split(struct dib7000m_state *state) | |||
427 | (agc - state->current_agc->split.min_thres) / | 609 | (agc - state->current_agc->split.min_thres) / |
428 | (state->current_agc->split.max_thres - state->current_agc->split.min_thres); | 610 | (state->current_agc->split.max_thres - state->current_agc->split.min_thres); |
429 | 611 | ||
430 | dprintk("AGC split_offset: %d\n",split_offset); | 612 | dprintk( "AGC split_offset: %d",split_offset); |
431 | 613 | ||
432 | // P_agc_force_split and P_agc_split_offset | 614 | // P_agc_force_split and P_agc_split_offset |
433 | return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset); | 615 | return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset); |
@@ -435,35 +617,26 @@ static int dib7000m_agc_soft_split(struct dib7000m_state *state) | |||
435 | 617 | ||
436 | static int dib7000m_update_lna(struct dib7000m_state *state) | 618 | static int dib7000m_update_lna(struct dib7000m_state *state) |
437 | { | 619 | { |
438 | int i; | ||
439 | u16 dyn_gain; | 620 | u16 dyn_gain; |
440 | 621 | ||
441 | // when there is no LNA to program return immediatly | 622 | if (state->cfg.update_lna) { |
442 | if (state->cfg.update_lna == NULL) | 623 | // read dyn_gain here (because it is demod-dependent and not fe) |
443 | return 0; | ||
444 | |||
445 | msleep(60); | ||
446 | for (i = 0; i < 20; i++) { | ||
447 | // read dyn_gain here (because it is demod-dependent and not tuner) | ||
448 | dyn_gain = dib7000m_read_word(state, 390); | 624 | dyn_gain = dib7000m_read_word(state, 390); |
449 | 625 | ||
450 | dprintk("agc global: %d\n", dyn_gain); | ||
451 | |||
452 | if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed | 626 | if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed |
453 | dib7000m_restart_agc(state); | 627 | dib7000m_restart_agc(state); |
454 | msleep(60); | 628 | return 1; |
455 | } else | 629 | } |
456 | break; | ||
457 | } | 630 | } |
458 | return 0; | 631 | return 0; |
459 | } | 632 | } |
460 | 633 | ||
461 | static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band) | 634 | static int dib7000m_set_agc_config(struct dib7000m_state *state, u8 band) |
462 | { | 635 | { |
463 | struct dibx000_agc_config *agc = NULL; | 636 | struct dibx000_agc_config *agc = NULL; |
464 | int i; | 637 | int i; |
465 | if (state->current_band == band) | 638 | if (state->current_band == band && state->current_agc != NULL) |
466 | return; | 639 | return 0; |
467 | state->current_band = band; | 640 | state->current_band = band; |
468 | 641 | ||
469 | for (i = 0; i < state->cfg.agc_config_count; i++) | 642 | for (i = 0; i < state->cfg.agc_config_count; i++) |
@@ -473,8 +646,8 @@ static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band) | |||
473 | } | 646 | } |
474 | 647 | ||
475 | if (agc == NULL) { | 648 | if (agc == NULL) { |
476 | dprintk("-E- No valid AGC configuration found for band 0x%02x\n",band); | 649 | dprintk( "no valid AGC configuration found for band 0x%02x",band); |
477 | return; | 650 | return -EINVAL; |
478 | } | 651 | } |
479 | 652 | ||
480 | state->current_agc = agc; | 653 | state->current_agc = agc; |
@@ -489,7 +662,7 @@ static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band) | |||
489 | dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp); | 662 | dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp); |
490 | dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp); | 663 | dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp); |
491 | 664 | ||
492 | dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", | 665 | dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d", |
493 | state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); | 666 | state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); |
494 | 667 | ||
495 | /* AGC continued */ | 668 | /* AGC continued */ |
@@ -510,7 +683,7 @@ static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band) | |||
510 | 683 | ||
511 | if (state->revision > 0x4000) { // settings for the MC | 684 | if (state->revision > 0x4000) { // settings for the MC |
512 | dib7000m_write_word(state, 71, agc->agc1_pt3); | 685 | dib7000m_write_word(state, 71, agc->agc1_pt3); |
513 | // dprintk("-D- 929: %x %d %d\n", | 686 | // dprintk( "929: %x %d %d", |
514 | // (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel); | 687 | // (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel); |
515 | dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); | 688 | dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); |
516 | } else { | 689 | } else { |
@@ -519,33 +692,160 @@ static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band) | |||
519 | for (i = 0; i < 9; i++) | 692 | for (i = 0; i < 9; i++) |
520 | dib7000m_write_word(state, 88 + i, b[i]); | 693 | dib7000m_write_word(state, 88 + i, b[i]); |
521 | } | 694 | } |
695 | return 0; | ||
522 | } | 696 | } |
523 | 697 | ||
524 | static void dib7000m_update_timf_freq(struct dib7000m_state *state) | 698 | static void dib7000m_update_timf(struct dib7000m_state *state) |
525 | { | 699 | { |
526 | u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437); | 700 | u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437); |
527 | state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100); | 701 | state->timf = timf * 160 / (state->current_bandwidth / 50); |
528 | dib7000m_write_word(state, 23, (u16) (timf >> 16)); | 702 | dib7000m_write_word(state, 23, (u16) (timf >> 16)); |
529 | dib7000m_write_word(state, 24, (u16) (timf & 0xffff)); | 703 | dib7000m_write_word(state, 24, (u16) (timf & 0xffff)); |
530 | dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf); | 704 | dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->timf_default); |
705 | } | ||
706 | |||
707 | static int dib7000m_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch) | ||
708 | { | ||
709 | struct dib7000m_state *state = demod->demodulator_priv; | ||
710 | u16 cfg_72 = dib7000m_read_word(state, 72); | ||
711 | int ret = -1; | ||
712 | u8 *agc_state = &state->agc_state; | ||
713 | u8 agc_split; | ||
714 | |||
715 | switch (state->agc_state) { | ||
716 | case 0: | ||
717 | // set power-up level: interf+analog+AGC | ||
718 | dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC); | ||
719 | dib7000m_set_adc_state(state, DIBX000_ADC_ON); | ||
720 | |||
721 | if (dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0) | ||
722 | return -1; | ||
723 | |||
724 | ret = 7; /* ADC power up */ | ||
725 | (*agc_state)++; | ||
726 | break; | ||
727 | |||
728 | case 1: | ||
729 | /* AGC initialization */ | ||
730 | if (state->cfg.agc_control) | ||
731 | state->cfg.agc_control(&state->demod, 1); | ||
732 | |||
733 | dib7000m_write_word(state, 75, 32768); | ||
734 | if (!state->current_agc->perform_agc_softsplit) { | ||
735 | /* we are using the wbd - so slow AGC startup */ | ||
736 | dib7000m_write_word(state, 103, 1 << 8); /* force 0 split on WBD and restart AGC */ | ||
737 | (*agc_state)++; | ||
738 | ret = 5; | ||
739 | } else { | ||
740 | /* default AGC startup */ | ||
741 | (*agc_state) = 4; | ||
742 | /* wait AGC rough lock time */ | ||
743 | ret = 7; | ||
744 | } | ||
745 | |||
746 | dib7000m_restart_agc(state); | ||
747 | break; | ||
748 | |||
749 | case 2: /* fast split search path after 5sec */ | ||
750 | dib7000m_write_word(state, 72, cfg_72 | (1 << 4)); /* freeze AGC loop */ | ||
751 | dib7000m_write_word(state, 103, 2 << 9); /* fast split search 0.25kHz */ | ||
752 | (*agc_state)++; | ||
753 | ret = 14; | ||
754 | break; | ||
755 | |||
756 | case 3: /* split search ended */ | ||
757 | agc_split = (u8)dib7000m_read_word(state, 392); /* store the split value for the next time */ | ||
758 | dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */ | ||
759 | |||
760 | dib7000m_write_word(state, 72, cfg_72 & ~(1 << 4)); /* std AGC loop */ | ||
761 | dib7000m_write_word(state, 103, (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */ | ||
762 | |||
763 | dib7000m_restart_agc(state); | ||
764 | |||
765 | dprintk( "SPLIT %p: %hd", demod, agc_split); | ||
766 | |||
767 | (*agc_state)++; | ||
768 | ret = 5; | ||
769 | break; | ||
770 | |||
771 | case 4: /* LNA startup */ | ||
772 | /* wait AGC accurate lock time */ | ||
773 | ret = 7; | ||
774 | |||
775 | if (dib7000m_update_lna(state)) | ||
776 | // wait only AGC rough lock time | ||
777 | ret = 5; | ||
778 | else | ||
779 | (*agc_state)++; | ||
780 | break; | ||
781 | |||
782 | case 5: | ||
783 | dib7000m_agc_soft_split(state); | ||
784 | |||
785 | if (state->cfg.agc_control) | ||
786 | state->cfg.agc_control(&state->demod, 0); | ||
787 | |||
788 | (*agc_state)++; | ||
789 | break; | ||
790 | |||
791 | default: | ||
792 | break; | ||
793 | } | ||
794 | return ret; | ||
531 | } | 795 | } |
532 | 796 | ||
533 | static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_ofdm_channel *ch, u8 seq) | 797 | static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_frontend_parameters *ch, u8 seq) |
534 | { | 798 | { |
535 | u16 value, est[4]; | 799 | u16 value, est[4]; |
536 | 800 | ||
537 | dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->RF_kHz)); | 801 | dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)); |
538 | 802 | ||
539 | /* nfft, guard, qam, alpha */ | 803 | /* nfft, guard, qam, alpha */ |
540 | dib7000m_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha)); | 804 | value = 0; |
805 | switch (ch->u.ofdm.transmission_mode) { | ||
806 | case TRANSMISSION_MODE_2K: value |= (0 << 7); break; | ||
807 | case /* 4K MODE */ 255: value |= (2 << 7); break; | ||
808 | default: | ||
809 | case TRANSMISSION_MODE_8K: value |= (1 << 7); break; | ||
810 | } | ||
811 | switch (ch->u.ofdm.guard_interval) { | ||
812 | case GUARD_INTERVAL_1_32: value |= (0 << 5); break; | ||
813 | case GUARD_INTERVAL_1_16: value |= (1 << 5); break; | ||
814 | case GUARD_INTERVAL_1_4: value |= (3 << 5); break; | ||
815 | default: | ||
816 | case GUARD_INTERVAL_1_8: value |= (2 << 5); break; | ||
817 | } | ||
818 | switch (ch->u.ofdm.constellation) { | ||
819 | case QPSK: value |= (0 << 3); break; | ||
820 | case QAM_16: value |= (1 << 3); break; | ||
821 | default: | ||
822 | case QAM_64: value |= (2 << 3); break; | ||
823 | } | ||
824 | switch (HIERARCHY_1) { | ||
825 | case HIERARCHY_2: value |= 2; break; | ||
826 | case HIERARCHY_4: value |= 4; break; | ||
827 | default: | ||
828 | case HIERARCHY_1: value |= 1; break; | ||
829 | } | ||
830 | dib7000m_write_word(state, 0, value); | ||
541 | dib7000m_write_word(state, 5, (seq << 4)); | 831 | dib7000m_write_word(state, 5, (seq << 4)); |
542 | 832 | ||
543 | /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */ | 833 | /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */ |
544 | value = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1); | 834 | value = 0; |
545 | if (ch->vit_hrch == 0 || ch->vit_select_hp == 1) | 835 | if (1 != 0) |
546 | value |= (ch->vit_code_rate_hp << 1); | 836 | value |= (1 << 6); |
547 | else | 837 | if (ch->u.ofdm.hierarchy_information == 1) |
548 | value |= (ch->vit_code_rate_lp << 1); | 838 | value |= (1 << 4); |
839 | if (1 == 1) | ||
840 | value |= 1; | ||
841 | switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) { | ||
842 | case FEC_2_3: value |= (2 << 1); break; | ||
843 | case FEC_3_4: value |= (3 << 1); break; | ||
844 | case FEC_5_6: value |= (5 << 1); break; | ||
845 | case FEC_7_8: value |= (7 << 1); break; | ||
846 | default: | ||
847 | case FEC_1_2: value |= (1 << 1); break; | ||
848 | } | ||
549 | dib7000m_write_word(state, 267 + state->reg_offs, value); | 849 | dib7000m_write_word(state, 267 + state->reg_offs, value); |
550 | 850 | ||
551 | /* offset loop parameters */ | 851 | /* offset loop parameters */ |
@@ -563,32 +863,38 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_of | |||
563 | dib7000m_write_word(state, 33, (0 << 4) | 0x5); | 863 | dib7000m_write_word(state, 33, (0 << 4) | 0x5); |
564 | 864 | ||
565 | /* P_dvsy_sync_wait */ | 865 | /* P_dvsy_sync_wait */ |
566 | switch (ch->nfft) { | 866 | switch (ch->u.ofdm.transmission_mode) { |
567 | case 1: value = 256; break; | 867 | case TRANSMISSION_MODE_8K: value = 256; break; |
568 | case 2: value = 128; break; | 868 | case /* 4K MODE */ 255: value = 128; break; |
569 | case 0: | 869 | case TRANSMISSION_MODE_2K: |
570 | default: value = 64; break; | 870 | default: value = 64; break; |
571 | } | 871 | } |
572 | value *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin | 872 | switch (ch->u.ofdm.guard_interval) { |
573 | value <<= 4; | 873 | case GUARD_INTERVAL_1_16: value *= 2; break; |
874 | case GUARD_INTERVAL_1_8: value *= 4; break; | ||
875 | case GUARD_INTERVAL_1_4: value *= 8; break; | ||
876 | default: | ||
877 | case GUARD_INTERVAL_1_32: value *= 1; break; | ||
878 | } | ||
879 | state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO | ||
574 | 880 | ||
575 | /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */ | 881 | /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */ |
576 | /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ | 882 | /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ |
577 | if (ch->intlv_native || state->revision > 0x4000) | 883 | if (1 == 1 || state->revision > 0x4000) |
578 | value |= (1 << 2) | (2 << 0); | 884 | state->div_force_off = 0; |
579 | else | 885 | else |
580 | value |= 0; | 886 | state->div_force_off = 1; |
581 | dib7000m_write_word(state, 266 + state->reg_offs, value); | 887 | dib7000m_set_diversity_in(&state->demod, state->div_state); |
582 | 888 | ||
583 | /* channel estimation fine configuration */ | 889 | /* channel estimation fine configuration */ |
584 | switch (ch->nqam) { | 890 | switch (ch->u.ofdm.constellation) { |
585 | case 2: | 891 | case QAM_64: |
586 | est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ | 892 | est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ |
587 | est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ | 893 | est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ |
588 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | 894 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ |
589 | est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ | 895 | est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ |
590 | break; | 896 | break; |
591 | case 1: | 897 | case QAM_16: |
592 | est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ | 898 | est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ |
593 | est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ | 899 | est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ |
594 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | 900 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ |
@@ -604,70 +910,48 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_of | |||
604 | for (value = 0; value < 4; value++) | 910 | for (value = 0; value < 4; value++) |
605 | dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]); | 911 | dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]); |
606 | 912 | ||
607 | // set power-up level: interf+analog+AGC | ||
608 | dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC); | ||
609 | dib7000m_set_adc_state(state, DIBX000_ADC_ON); | ||
610 | |||
611 | msleep(7); | ||
612 | |||
613 | //AGC initialization | ||
614 | if (state->cfg.agc_control) | ||
615 | state->cfg.agc_control(&state->demod, 1); | ||
616 | |||
617 | dib7000m_restart_agc(state); | ||
618 | |||
619 | // wait AGC rough lock time | ||
620 | msleep(5); | ||
621 | |||
622 | dib7000m_update_lna(state); | ||
623 | dib7000m_agc_soft_split(state); | ||
624 | |||
625 | // wait AGC accurate lock time | ||
626 | msleep(7); | ||
627 | |||
628 | if (state->cfg.agc_control) | ||
629 | state->cfg.agc_control(&state->demod, 0); | ||
630 | |||
631 | // set power-up level: autosearch | 913 | // set power-up level: autosearch |
632 | dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD); | 914 | dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD); |
633 | } | 915 | } |
634 | 916 | ||
635 | static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | 917 | static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch) |
636 | { | 918 | { |
637 | struct dib7000m_state *state = demod->demodulator_priv; | 919 | struct dib7000m_state *state = demod->demodulator_priv; |
638 | struct dibx000_ofdm_channel auto_ch; | 920 | struct dvb_frontend_parameters schan; |
639 | int ret = 0; | 921 | int ret = 0; |
640 | u32 value; | 922 | u32 value, factor; |
641 | 923 | ||
642 | INIT_OFDM_CHANNEL(&auto_ch); | 924 | schan = *ch; |
643 | auto_ch.RF_kHz = ch->RF_kHz; | 925 | |
644 | auto_ch.Bw = ch->Bw; | 926 | schan.u.ofdm.constellation = QAM_64; |
645 | auto_ch.nqam = 2; | 927 | schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32; |
646 | auto_ch.guard = 0; | 928 | schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; |
647 | auto_ch.nfft = 1; | 929 | schan.u.ofdm.code_rate_HP = FEC_2_3; |
648 | auto_ch.vit_alpha = 1; | 930 | schan.u.ofdm.code_rate_LP = FEC_3_4; |
649 | auto_ch.vit_select_hp = 1; | 931 | schan.u.ofdm.hierarchy_information = 0; |
650 | auto_ch.vit_code_rate_hp = 2; | 932 | |
651 | auto_ch.vit_code_rate_lp = 3; | 933 | dib7000m_set_channel(state, &schan, 7); |
652 | auto_ch.vit_hrch = 0; | 934 | |
653 | auto_ch.intlv_native = 1; | 935 | factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth); |
654 | 936 | if (factor >= 5000) | |
655 | dib7000m_set_channel(state, &auto_ch, 7); | 937 | factor = 1; |
938 | else | ||
939 | factor = 6; | ||
656 | 940 | ||
657 | // always use the setting for 8MHz here lock_time for 7,6 MHz are longer | 941 | // always use the setting for 8MHz here lock_time for 7,6 MHz are longer |
658 | value = 30 * state->cfg.bw->internal; | 942 | value = 30 * state->internal_clk * factor; |
659 | ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time | 943 | ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time |
660 | ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time | 944 | ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time |
661 | value = 100 * state->cfg.bw->internal; | 945 | value = 100 * state->internal_clk * factor; |
662 | ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time | 946 | ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time |
663 | ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time | 947 | ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time |
664 | value = 500 * state->cfg.bw->internal; | 948 | value = 500 * state->internal_clk * factor; |
665 | ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time | 949 | ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time |
666 | ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time | 950 | ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time |
667 | 951 | ||
668 | // start search | 952 | // start search |
669 | value = dib7000m_read_word(state, 0); | 953 | value = dib7000m_read_word(state, 0); |
670 | ret |= dib7000m_write_word(state, 0, value | (1 << 9)); | 954 | ret |= dib7000m_write_word(state, 0, (u16) (value | (1 << 9))); |
671 | 955 | ||
672 | /* clear n_irq_pending */ | 956 | /* clear n_irq_pending */ |
673 | if (state->revision == 0x4000) | 957 | if (state->revision == 0x4000) |
@@ -685,12 +969,12 @@ static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg) | |||
685 | u16 irq_pending = dib7000m_read_word(state, reg); | 969 | u16 irq_pending = dib7000m_read_word(state, reg); |
686 | 970 | ||
687 | if (irq_pending & 0x1) { // failed | 971 | if (irq_pending & 0x1) { // failed |
688 | dprintk("#\n"); | 972 | dprintk( "autosearch failed"); |
689 | return 1; | 973 | return 1; |
690 | } | 974 | } |
691 | 975 | ||
692 | if (irq_pending & 0x2) { // succeeded | 976 | if (irq_pending & 0x2) { // succeeded |
693 | dprintk("!\n"); | 977 | dprintk( "autosearch succeeded"); |
694 | return 2; | 978 | return 2; |
695 | } | 979 | } |
696 | return 0; // still pending | 980 | return 0; // still pending |
@@ -705,7 +989,7 @@ static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod) | |||
705 | return dib7000m_autosearch_irq(state, 537); | 989 | return dib7000m_autosearch_irq(state, 537); |
706 | } | 990 | } |
707 | 991 | ||
708 | static int dib7000m_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | 992 | static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch) |
709 | { | 993 | { |
710 | struct dib7000m_state *state = demod->demodulator_priv; | 994 | struct dib7000m_state *state = demod->demodulator_priv; |
711 | int ret = 0; | 995 | int ret = 0; |
@@ -722,182 +1006,103 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel | |||
722 | ret |= dib7000m_write_word(state, 898, 0x0000); | 1006 | ret |= dib7000m_write_word(state, 898, 0x0000); |
723 | msleep(45); | 1007 | msleep(45); |
724 | 1008 | ||
725 | ret |= dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD); | 1009 | dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD); |
726 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ | 1010 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ |
727 | ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); | 1011 | ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); |
728 | 1012 | ||
729 | // never achieved a lock with that bandwidth so far - wait for timfreq to update | 1013 | // never achieved a lock before - wait for timfreq to update |
730 | if (state->timf == 0) | 1014 | if (state->timf == 0) |
731 | msleep(200); | 1015 | msleep(200); |
732 | 1016 | ||
733 | //dump_reg(state); | 1017 | //dump_reg(state); |
734 | /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ | 1018 | /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ |
735 | value = (6 << 8) | 0x80; | 1019 | value = (6 << 8) | 0x80; |
736 | switch (ch->nfft) { | 1020 | switch (ch->u.ofdm.transmission_mode) { |
737 | case 0: value |= (7 << 12); break; | 1021 | case TRANSMISSION_MODE_2K: value |= (7 << 12); break; |
738 | case 1: value |= (9 << 12); break; | 1022 | case /* 4K MODE */ 255: value |= (8 << 12); break; |
739 | case 2: value |= (8 << 12); break; | 1023 | default: |
1024 | case TRANSMISSION_MODE_8K: value |= (9 << 12); break; | ||
740 | } | 1025 | } |
741 | ret |= dib7000m_write_word(state, 26, value); | 1026 | ret |= dib7000m_write_word(state, 26, value); |
742 | 1027 | ||
743 | /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ | 1028 | /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ |
744 | value = (0 << 4); | 1029 | value = (0 << 4); |
745 | switch (ch->nfft) { | 1030 | switch (ch->u.ofdm.transmission_mode) { |
746 | case 0: value |= 0x6; break; | 1031 | case TRANSMISSION_MODE_2K: value |= 0x6; break; |
747 | case 1: value |= 0x8; break; | 1032 | case /* 4K MODE */ 255: value |= 0x7; break; |
748 | case 2: value |= 0x7; break; | 1033 | default: |
1034 | case TRANSMISSION_MODE_8K: value |= 0x8; break; | ||
749 | } | 1035 | } |
750 | ret |= dib7000m_write_word(state, 32, value); | 1036 | ret |= dib7000m_write_word(state, 32, value); |
751 | 1037 | ||
752 | /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ | 1038 | /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ |
753 | value = (0 << 4); | 1039 | value = (0 << 4); |
754 | switch (ch->nfft) { | 1040 | switch (ch->u.ofdm.transmission_mode) { |
755 | case 0: value |= 0x6; break; | 1041 | case TRANSMISSION_MODE_2K: value |= 0x6; break; |
756 | case 1: value |= 0x8; break; | 1042 | case /* 4K MODE */ 255: value |= 0x7; break; |
757 | case 2: value |= 0x7; break; | 1043 | default: |
1044 | case TRANSMISSION_MODE_8K: value |= 0x8; break; | ||
758 | } | 1045 | } |
759 | ret |= dib7000m_write_word(state, 33, value); | 1046 | ret |= dib7000m_write_word(state, 33, value); |
760 | 1047 | ||
761 | // we achieved a lock - it's time to update the osc freq | 1048 | // we achieved a lock - it's time to update the timf freq |
762 | if ((dib7000m_read_word(state, 535) >> 6) & 0x1) | 1049 | if ((dib7000m_read_word(state, 535) >> 6) & 0x1) |
763 | dib7000m_update_timf_freq(state); | 1050 | dib7000m_update_timf(state); |
764 | 1051 | ||
1052 | dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)); | ||
765 | return ret; | 1053 | return ret; |
766 | } | 1054 | } |
767 | 1055 | ||
768 | static int dib7000m_init(struct dvb_frontend *demod) | 1056 | static int dib7000m_wakeup(struct dvb_frontend *demod) |
769 | { | 1057 | { |
770 | struct dib7000m_state *state = demod->demodulator_priv; | 1058 | struct dib7000m_state *state = demod->demodulator_priv; |
771 | int ret = 0; | ||
772 | u8 o = state->reg_offs; | ||
773 | 1059 | ||
774 | dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); | 1060 | dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); |
775 | 1061 | ||
776 | if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) | 1062 | if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) |
777 | dprintk("-E- could not start Slow ADC\n"); | 1063 | dprintk( "could not start Slow ADC"); |
778 | |||
779 | if (state->cfg.dvbt_mode) | ||
780 | dib7000m_write_word(state, 1796, 0x0); // select DVB-T output | ||
781 | |||
782 | if (state->cfg.mobile_mode) | ||
783 | ret |= dib7000m_write_word(state, 261 + o, 2); | ||
784 | else | ||
785 | ret |= dib7000m_write_word(state, 224 + o, 1); | ||
786 | |||
787 | ret |= dib7000m_write_word(state, 173 + o, 0); | ||
788 | ret |= dib7000m_write_word(state, 174 + o, 0); | ||
789 | ret |= dib7000m_write_word(state, 175 + o, 0); | ||
790 | ret |= dib7000m_write_word(state, 176 + o, 0); | ||
791 | ret |= dib7000m_write_word(state, 177 + o, 0); | ||
792 | ret |= dib7000m_write_word(state, 178 + o, 0); | ||
793 | ret |= dib7000m_write_word(state, 179 + o, 0); | ||
794 | ret |= dib7000m_write_word(state, 180 + o, 0); | ||
795 | |||
796 | // P_corm_thres Lock algorithms configuration | ||
797 | ret |= dib7000m_write_word(state, 26, 0x6680); | ||
798 | |||
799 | // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on | ||
800 | ret |= dib7000m_write_word(state, 170 + o, 0x0410); | ||
801 | // P_fft_nb_to_cut | ||
802 | ret |= dib7000m_write_word(state, 182 + o, 8192); | ||
803 | // P_pha3_thres | ||
804 | ret |= dib7000m_write_word(state, 195 + o, 0x0ccd); | ||
805 | // P_cti_use_cpe, P_cti_use_prog | ||
806 | ret |= dib7000m_write_word(state, 196 + o, 0); | ||
807 | // P_cspu_regul, P_cspu_win_cut | ||
808 | ret |= dib7000m_write_word(state, 205 + o, 0x200f); | ||
809 | // P_adp_regul_cnt | ||
810 | ret |= dib7000m_write_word(state, 214 + o, 0x023d); | ||
811 | // P_adp_noise_cnt | ||
812 | ret |= dib7000m_write_word(state, 215 + o, 0x00a4); | ||
813 | // P_adp_regul_ext | ||
814 | ret |= dib7000m_write_word(state, 216 + o, 0x00a4); | ||
815 | // P_adp_noise_ext | ||
816 | ret |= dib7000m_write_word(state, 217 + o, 0x7ff0); | ||
817 | // P_adp_fil | ||
818 | ret |= dib7000m_write_word(state, 218 + o, 0x3ccc); | ||
819 | |||
820 | // P_2d_byp_ti_num | ||
821 | ret |= dib7000m_write_word(state, 226 + o, 0); | ||
822 | |||
823 | // P_fec_* | ||
824 | ret |= dib7000m_write_word(state, 281 + o, 0x0010); | ||
825 | // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard | ||
826 | ret |= dib7000m_write_word(state, 294 + o,0x0062); | ||
827 | |||
828 | // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... | ||
829 | if(state->cfg.tuner_is_baseband) | ||
830 | ret |= dib7000m_write_word(state, 36, 0x0755); | ||
831 | else | ||
832 | ret |= dib7000m_write_word(state, 36, 0x1f55); | ||
833 | |||
834 | // auto search configuration | ||
835 | ret |= dib7000m_write_word(state, 2, 0x0004); | ||
836 | ret |= dib7000m_write_word(state, 3, 0x1000); | ||
837 | ret |= dib7000m_write_word(state, 4, 0x0814); | ||
838 | ret |= dib7000m_write_word(state, 6, 0x001b); | ||
839 | ret |= dib7000m_write_word(state, 7, 0x7740); | ||
840 | ret |= dib7000m_write_word(state, 8, 0x005b); | ||
841 | ret |= dib7000m_write_word(state, 9, 0x8d80); | ||
842 | ret |= dib7000m_write_word(state, 10, 0x01c9); | ||
843 | ret |= dib7000m_write_word(state, 11, 0xc380); | ||
844 | ret |= dib7000m_write_word(state, 12, 0x0000); | ||
845 | ret |= dib7000m_write_word(state, 13, 0x0080); | ||
846 | ret |= dib7000m_write_word(state, 14, 0x0000); | ||
847 | ret |= dib7000m_write_word(state, 15, 0x0090); | ||
848 | ret |= dib7000m_write_word(state, 16, 0x0001); | ||
849 | ret |= dib7000m_write_word(state, 17, 0xd4c0); | ||
850 | ret |= dib7000m_write_word(state, 263 + o,0x0001); | ||
851 | |||
852 | // P_divclksel=3 P_divbitsel=1 | ||
853 | if (state->revision == 0x4000) | ||
854 | dib7000m_write_word(state, 909, (3 << 10) | (1 << 6)); | ||
855 | else | ||
856 | dib7000m_write_word(state, 909, (3 << 4) | 1); | ||
857 | |||
858 | // Tuner IO bank: max drive (14mA) | ||
859 | ret |= dib7000m_write_word(state, 912 ,0x2c8a); | ||
860 | 1064 | ||
861 | ret |= dib7000m_write_word(state, 1817, 1); | 1065 | return 0; |
862 | |||
863 | return ret; | ||
864 | } | 1066 | } |
865 | 1067 | ||
866 | static int dib7000m_sleep(struct dvb_frontend *demod) | 1068 | static int dib7000m_sleep(struct dvb_frontend *demod) |
867 | { | 1069 | { |
868 | struct dib7000m_state *st = demod->demodulator_priv; | 1070 | struct dib7000m_state *st = demod->demodulator_priv; |
869 | dib7000m_set_output_mode(st, OUTMODE_HIGH_Z); | 1071 | dib7000m_set_output_mode(st, OUTMODE_HIGH_Z); |
870 | return dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY) | | 1072 | dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY); |
871 | dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) | | 1073 | return dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) | |
872 | dib7000m_set_adc_state(st, DIBX000_ADC_OFF); | 1074 | dib7000m_set_adc_state(st, DIBX000_ADC_OFF); |
873 | } | 1075 | } |
874 | 1076 | ||
875 | static int dib7000m_identify(struct dib7000m_state *state) | 1077 | static int dib7000m_identify(struct dib7000m_state *state) |
876 | { | 1078 | { |
877 | u16 value; | 1079 | u16 value; |
1080 | |||
878 | if ((value = dib7000m_read_word(state, 896)) != 0x01b3) { | 1081 | if ((value = dib7000m_read_word(state, 896)) != 0x01b3) { |
879 | dprintk("-E- DiB7000M: wrong Vendor ID (read=0x%x)\n",value); | 1082 | dprintk( "wrong Vendor ID (0x%x)",value); |
880 | return -EREMOTEIO; | 1083 | return -EREMOTEIO; |
881 | } | 1084 | } |
882 | 1085 | ||
883 | state->revision = dib7000m_read_word(state, 897); | 1086 | state->revision = dib7000m_read_word(state, 897); |
884 | if (state->revision != 0x4000 && | 1087 | if (state->revision != 0x4000 && |
885 | state->revision != 0x4001 && | 1088 | state->revision != 0x4001 && |
886 | state->revision != 0x4002) { | 1089 | state->revision != 0x4002 && |
887 | dprintk("-E- DiB7000M: wrong Device ID (%x)\n",value); | 1090 | state->revision != 0x4003) { |
1091 | dprintk( "wrong Device ID (0x%x)",value); | ||
888 | return -EREMOTEIO; | 1092 | return -EREMOTEIO; |
889 | } | 1093 | } |
890 | 1094 | ||
891 | /* protect this driver to be used with 7000PC */ | 1095 | /* protect this driver to be used with 7000PC */ |
892 | if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) { | 1096 | if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) { |
893 | dprintk("-E- DiB7000M: this driver does not work with DiB7000PC\n"); | 1097 | dprintk( "this driver does not work with DiB7000PC"); |
894 | return -EREMOTEIO; | 1098 | return -EREMOTEIO; |
895 | } | 1099 | } |
896 | 1100 | ||
897 | switch (state->revision) { | 1101 | switch (state->revision) { |
898 | case 0x4000: dprintk("-I- found DiB7000MA/PA/MB/PB\n"); break; | 1102 | case 0x4000: dprintk( "found DiB7000MA/PA/MB/PB"); break; |
899 | case 0x4001: state->reg_offs = 1; dprintk("-I- found DiB7000HC\n"); break; | 1103 | case 0x4001: state->reg_offs = 1; dprintk( "found DiB7000HC"); break; |
900 | case 0x4002: state->reg_offs = 1; dprintk("-I- found DiB7000MC\n"); break; | 1104 | case 0x4002: state->reg_offs = 1; dprintk( "found DiB7000MC"); break; |
1105 | case 0x4003: state->reg_offs = 1; dprintk( "found DiB9000"); break; | ||
901 | } | 1106 | } |
902 | 1107 | ||
903 | return 0; | 1108 | return 0; |
@@ -966,41 +1171,45 @@ static int dib7000m_set_frontend(struct dvb_frontend* fe, | |||
966 | struct dvb_frontend_parameters *fep) | 1171 | struct dvb_frontend_parameters *fep) |
967 | { | 1172 | { |
968 | struct dib7000m_state *state = fe->demodulator_priv; | 1173 | struct dib7000m_state *state = fe->demodulator_priv; |
969 | struct dibx000_ofdm_channel ch; | 1174 | int time; |
970 | |||
971 | INIT_OFDM_CHANNEL(&ch); | ||
972 | FEP2DIB(fep,&ch); | ||
973 | 1175 | ||
974 | state->current_bandwidth = fep->u.ofdm.bandwidth; | 1176 | state->current_bandwidth = fep->u.ofdm.bandwidth; |
975 | dib7000m_set_bandwidth(fe, fep->u.ofdm.bandwidth); | 1177 | dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth)); |
976 | 1178 | ||
977 | if (fe->ops.tuner_ops.set_params) | 1179 | if (fe->ops.tuner_ops.set_params) |
978 | fe->ops.tuner_ops.set_params(fe, fep); | 1180 | fe->ops.tuner_ops.set_params(fe, fep); |
979 | 1181 | ||
1182 | /* start up the AGC */ | ||
1183 | state->agc_state = 0; | ||
1184 | do { | ||
1185 | time = dib7000m_agc_startup(fe, fep); | ||
1186 | if (time != -1) | ||
1187 | msleep(time); | ||
1188 | } while (time != -1); | ||
1189 | |||
980 | if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || | 1190 | if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || |
981 | fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || | 1191 | fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || |
982 | fep->u.ofdm.constellation == QAM_AUTO || | 1192 | fep->u.ofdm.constellation == QAM_AUTO || |
983 | fep->u.ofdm.code_rate_HP == FEC_AUTO) { | 1193 | fep->u.ofdm.code_rate_HP == FEC_AUTO) { |
984 | int i = 800, found; | 1194 | int i = 800, found; |
985 | 1195 | ||
986 | dib7000m_autosearch_start(fe, &ch); | 1196 | dib7000m_autosearch_start(fe, fep); |
987 | do { | 1197 | do { |
988 | msleep(1); | 1198 | msleep(1); |
989 | found = dib7000m_autosearch_is_irq(fe); | 1199 | found = dib7000m_autosearch_is_irq(fe); |
990 | } while (found == 0 && i--); | 1200 | } while (found == 0 && i--); |
991 | 1201 | ||
992 | dprintk("autosearch returns: %d\n",found); | 1202 | dprintk("autosearch returns: %d",found); |
993 | if (found == 0 || found == 1) | 1203 | if (found == 0 || found == 1) |
994 | return 0; // no channel found | 1204 | return 0; // no channel found |
995 | 1205 | ||
996 | dib7000m_get_frontend(fe, fep); | 1206 | dib7000m_get_frontend(fe, fep); |
997 | FEP2DIB(fep, &ch); | ||
998 | } | 1207 | } |
999 | 1208 | ||
1000 | /* make this a config parameter */ | 1209 | /* make this a config parameter */ |
1001 | dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO); | 1210 | dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO); |
1002 | 1211 | ||
1003 | return dib7000m_tune(fe, &ch); | 1212 | return dib7000m_tune(fe, fep); |
1004 | } | 1213 | } |
1005 | 1214 | ||
1006 | static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat) | 1215 | static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat) |
@@ -1087,7 +1296,7 @@ int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau | |||
1087 | if (dib7000m_identify(&st) != 0) { | 1296 | if (dib7000m_identify(&st) != 0) { |
1088 | st.i2c_addr = default_addr; | 1297 | st.i2c_addr = default_addr; |
1089 | if (dib7000m_identify(&st) != 0) { | 1298 | if (dib7000m_identify(&st) != 0) { |
1090 | dprintk("DiB7000M #%d: not identified\n", k); | 1299 | dprintk("DiB7000M #%d: not identified", k); |
1091 | return -EIO; | 1300 | return -EIO; |
1092 | } | 1301 | } |
1093 | } | 1302 | } |
@@ -1100,7 +1309,7 @@ int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau | |||
1100 | /* set new i2c address and force divstart */ | 1309 | /* set new i2c address and force divstart */ |
1101 | dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2); | 1310 | dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2); |
1102 | 1311 | ||
1103 | dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); | 1312 | dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr); |
1104 | } | 1313 | } |
1105 | 1314 | ||
1106 | for (k = 0; k < no_of_demods; k++) { | 1315 | for (k = 0; k < no_of_demods; k++) { |
@@ -1135,6 +1344,8 @@ struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, | |||
1135 | demod->demodulator_priv = st; | 1344 | demod->demodulator_priv = st; |
1136 | memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); | 1345 | memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); |
1137 | 1346 | ||
1347 | st->timf_default = cfg->bw->timf; | ||
1348 | |||
1138 | if (dib7000m_identify(st) != 0) | 1349 | if (dib7000m_identify(st) != 0) |
1139 | goto error; | 1350 | goto error; |
1140 | 1351 | ||
@@ -1172,7 +1383,7 @@ static struct dvb_frontend_ops dib7000m_ops = { | |||
1172 | 1383 | ||
1173 | .release = dib7000m_release, | 1384 | .release = dib7000m_release, |
1174 | 1385 | ||
1175 | .init = dib7000m_init, | 1386 | .init = dib7000m_wakeup, |
1176 | .sleep = dib7000m_sleep, | 1387 | .sleep = dib7000m_sleep, |
1177 | 1388 | ||
1178 | .set_frontend = dib7000m_set_frontend, | 1389 | .set_frontend = dib7000m_set_frontend, |
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index aece458cfe12..f45bcfc51cf8 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC). | 2 | * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC). |
3 | * | 3 | * |
4 | * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/) | 4 | * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as | 7 | * modify it under the terms of the GNU General Public License as |
@@ -18,7 +18,11 @@ static int debug; | |||
18 | module_param(debug, int, 0644); | 18 | module_param(debug, int, 0644); |
19 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | 19 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); |
20 | 20 | ||
21 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P:"); printk(args); } } while (0) | 21 | static int buggy_sfn_workaround; |
22 | module_param(buggy_sfn_workaround, int, 0644); | ||
23 | MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)"); | ||
24 | |||
25 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P: "); printk(args); printk("\n"); } } while (0) | ||
22 | 26 | ||
23 | struct dib7000p_state { | 27 | struct dib7000p_state { |
24 | struct dvb_frontend demod; | 28 | struct dvb_frontend demod; |
@@ -36,12 +40,21 @@ struct dib7000p_state { | |||
36 | struct dibx000_agc_config *current_agc; | 40 | struct dibx000_agc_config *current_agc; |
37 | u32 timf; | 41 | u32 timf; |
38 | 42 | ||
43 | u8 div_force_off : 1; | ||
44 | u8 div_state : 1; | ||
45 | u16 div_sync_wait; | ||
46 | |||
47 | u8 agc_state; | ||
48 | |||
39 | u16 gpio_dir; | 49 | u16 gpio_dir; |
40 | u16 gpio_val; | 50 | u16 gpio_val; |
51 | |||
52 | u8 sfn_workaround_active :1; | ||
41 | }; | 53 | }; |
42 | 54 | ||
43 | enum dib7000p_power_mode { | 55 | enum dib7000p_power_mode { |
44 | DIB7000P_POWER_ALL = 0, | 56 | DIB7000P_POWER_ALL = 0, |
57 | DIB7000P_POWER_ANALOG_ADC, | ||
45 | DIB7000P_POWER_INTERFACE_ONLY, | 58 | DIB7000P_POWER_INTERFACE_ONLY, |
46 | }; | 59 | }; |
47 | 60 | ||
@@ -55,7 +68,7 @@ static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) | |||
55 | }; | 68 | }; |
56 | 69 | ||
57 | if (i2c_transfer(state->i2c_adap, msg, 2) != 2) | 70 | if (i2c_transfer(state->i2c_adap, msg, 2) != 2) |
58 | dprintk("i2c read error on %d\n",reg); | 71 | dprintk("i2c read error on %d",reg); |
59 | 72 | ||
60 | return (rb[0] << 8) | rb[1]; | 73 | return (rb[0] << 8) | rb[1]; |
61 | } | 74 | } |
@@ -71,6 +84,22 @@ static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) | |||
71 | }; | 84 | }; |
72 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | 85 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; |
73 | } | 86 | } |
87 | static void dib7000p_write_tab(struct dib7000p_state *state, u16 *buf) | ||
88 | { | ||
89 | u16 l = 0, r, *n; | ||
90 | n = buf; | ||
91 | l = *n++; | ||
92 | while (l) { | ||
93 | r = *n++; | ||
94 | |||
95 | do { | ||
96 | dib7000p_write_word(state, r, *n++); | ||
97 | r++; | ||
98 | } while (--l); | ||
99 | l = *n++; | ||
100 | } | ||
101 | } | ||
102 | |||
74 | static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode) | 103 | static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode) |
75 | { | 104 | { |
76 | int ret = 0; | 105 | int ret = 0; |
@@ -80,7 +109,7 @@ static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode) | |||
80 | fifo_threshold = 1792; | 109 | fifo_threshold = 1792; |
81 | smo_mode = (dib7000p_read_word(state, 235) & 0x0010) | (1 << 1); | 110 | smo_mode = (dib7000p_read_word(state, 235) & 0x0010) | (1 << 1); |
82 | 111 | ||
83 | dprintk("-I- Setting output mode for demod %p to %d\n", | 112 | dprintk( "setting output mode for demod %p to %d", |
84 | &state->demod, mode); | 113 | &state->demod, mode); |
85 | 114 | ||
86 | switch (mode) { | 115 | switch (mode) { |
@@ -104,11 +133,14 @@ static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode) | |||
104 | fifo_threshold = 512; | 133 | fifo_threshold = 512; |
105 | outreg = (1 << 10) | (5 << 6); | 134 | outreg = (1 << 10) | (5 << 6); |
106 | break; | 135 | break; |
136 | case OUTMODE_ANALOG_ADC: | ||
137 | outreg = (1 << 10) | (3 << 6); | ||
138 | break; | ||
107 | case OUTMODE_HIGH_Z: // disable | 139 | case OUTMODE_HIGH_Z: // disable |
108 | outreg = 0; | 140 | outreg = 0; |
109 | break; | 141 | break; |
110 | default: | 142 | default: |
111 | dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); | 143 | dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod); |
112 | break; | 144 | break; |
113 | } | 145 | } |
114 | 146 | ||
@@ -122,6 +154,30 @@ static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode) | |||
122 | return ret; | 154 | return ret; |
123 | } | 155 | } |
124 | 156 | ||
157 | static int dib7000p_set_diversity_in(struct dvb_frontend *demod, int onoff) | ||
158 | { | ||
159 | struct dib7000p_state *state = demod->demodulator_priv; | ||
160 | |||
161 | if (state->div_force_off) { | ||
162 | dprintk( "diversity combination deactivated - forced by COFDM parameters"); | ||
163 | onoff = 0; | ||
164 | } | ||
165 | state->div_state = (u8)onoff; | ||
166 | |||
167 | if (onoff) { | ||
168 | dib7000p_write_word(state, 204, 6); | ||
169 | dib7000p_write_word(state, 205, 16); | ||
170 | /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ | ||
171 | dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0)); | ||
172 | } else { | ||
173 | dib7000p_write_word(state, 204, 1); | ||
174 | dib7000p_write_word(state, 205, 0); | ||
175 | dib7000p_write_word(state, 207, 0); | ||
176 | } | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
125 | static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode) | 181 | static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode) |
126 | { | 182 | { |
127 | /* by default everything is powered off */ | 183 | /* by default everything is powered off */ |
@@ -134,10 +190,21 @@ static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_p | |||
134 | case DIB7000P_POWER_ALL: | 190 | case DIB7000P_POWER_ALL: |
135 | reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff; | 191 | reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff; |
136 | break; | 192 | break; |
193 | |||
194 | case DIB7000P_POWER_ANALOG_ADC: | ||
195 | /* dem, cfg, iqc, sad, agc */ | ||
196 | reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9)); | ||
197 | /* nud */ | ||
198 | reg_776 &= ~((1 << 0)); | ||
199 | /* Dout */ | ||
200 | reg_1280 &= ~((1 << 11)); | ||
201 | /* fall through wanted to enable the interfaces */ | ||
202 | |||
137 | /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */ | 203 | /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */ |
138 | case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */ | 204 | case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */ |
139 | reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10)); | 205 | reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10)); |
140 | break; | 206 | break; |
207 | |||
141 | /* TODO following stuff is just converted from the dib7000-driver - check when is used what */ | 208 | /* TODO following stuff is just converted from the dib7000-driver - check when is used what */ |
142 | } | 209 | } |
143 | 210 | ||
@@ -188,34 +255,31 @@ static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_ad | |||
188 | break; | 255 | break; |
189 | } | 256 | } |
190 | 257 | ||
191 | // dprintk("908: %x, 909: %x\n", reg_908, reg_909); | 258 | // dprintk( "908: %x, 909: %x\n", reg_908, reg_909); |
192 | 259 | ||
193 | dib7000p_write_word(state, 908, reg_908); | 260 | dib7000p_write_word(state, 908, reg_908); |
194 | dib7000p_write_word(state, 909, reg_909); | 261 | dib7000p_write_word(state, 909, reg_909); |
195 | } | 262 | } |
196 | 263 | ||
197 | static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx) | 264 | static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw) |
198 | { | 265 | { |
199 | struct dib7000p_state *state = demod->demodulator_priv; | ||
200 | u32 timf; | 266 | u32 timf; |
201 | 267 | ||
202 | // store the current bandwidth for later use | 268 | // store the current bandwidth for later use |
203 | state->current_bandwidth = BW_Idx; | 269 | state->current_bandwidth = bw; |
204 | 270 | ||
205 | if (state->timf == 0) { | 271 | if (state->timf == 0) { |
206 | dprintk("-D- Using default timf\n"); | 272 | dprintk( "using default timf"); |
207 | timf = state->cfg.bw->timf; | 273 | timf = state->cfg.bw->timf; |
208 | } else { | 274 | } else { |
209 | dprintk("-D- Using updated timf\n"); | 275 | dprintk( "using updated timf"); |
210 | timf = state->timf; | 276 | timf = state->timf; |
211 | } | 277 | } |
212 | 278 | ||
213 | timf = timf * (BW_INDEX_TO_KHZ(BW_Idx) / 100) / 80; | 279 | timf = timf * (bw / 50) / 160; |
214 | |||
215 | dprintk("timf: %d\n",timf); | ||
216 | 280 | ||
217 | dib7000p_write_word(state, 23, (timf >> 16) & 0xffff); | 281 | dib7000p_write_word(state, 23, (u16) ((timf >> 16) & 0xffff)); |
218 | dib7000p_write_word(state, 24, (timf ) & 0xffff); | 282 | dib7000p_write_word(state, 24, (u16) ((timf ) & 0xffff)); |
219 | 283 | ||
220 | return 0; | 284 | return 0; |
221 | } | 285 | } |
@@ -223,7 +287,7 @@ static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx) | |||
223 | static int dib7000p_sad_calib(struct dib7000p_state *state) | 287 | static int dib7000p_sad_calib(struct dib7000p_state *state) |
224 | { | 288 | { |
225 | /* internal */ | 289 | /* internal */ |
226 | // dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is written in set_bandwidth | 290 | // dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth |
227 | dib7000p_write_word(state, 73, (0 << 1) | (0 << 0)); | 291 | dib7000p_write_word(state, 73, (0 << 1) | (0 << 0)); |
228 | dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096 | 292 | dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096 |
229 | 293 | ||
@@ -236,18 +300,37 @@ static int dib7000p_sad_calib(struct dib7000p_state *state) | |||
236 | return 0; | 300 | return 0; |
237 | } | 301 | } |
238 | 302 | ||
303 | int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value) | ||
304 | { | ||
305 | struct dib7000p_state *state = demod->demodulator_priv; | ||
306 | if (value > 4095) | ||
307 | value = 4095; | ||
308 | state->wbd_ref = value; | ||
309 | return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value); | ||
310 | } | ||
311 | |||
312 | EXPORT_SYMBOL(dib7000p_set_wbd_ref); | ||
239 | static void dib7000p_reset_pll(struct dib7000p_state *state) | 313 | static void dib7000p_reset_pll(struct dib7000p_state *state) |
240 | { | 314 | { |
241 | struct dibx000_bandwidth_config *bw = &state->cfg.bw[0]; | 315 | struct dibx000_bandwidth_config *bw = &state->cfg.bw[0]; |
316 | u16 clk_cfg0; | ||
317 | |||
318 | /* force PLL bypass */ | ||
319 | clk_cfg0 = (1 << 15) | ((bw->pll_ratio & 0x3f) << 9) | | ||
320 | (bw->modulo << 7) | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | | ||
321 | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0); | ||
242 | 322 | ||
323 | dib7000p_write_word(state, 900, clk_cfg0); | ||
324 | |||
325 | /* P_pll_cfg */ | ||
243 | dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset); | 326 | dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset); |
244 | dib7000p_write_word(state, 900, ((bw->pll_ratio & 0x3f) << 9) | (bw->pll_bypass << 15) | (bw->modulo << 7) | (bw->ADClkSrc << 6) | | 327 | clk_cfg0 = (bw->pll_bypass << 15) | (clk_cfg0 & 0x7fff); |
245 | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0)); | 328 | dib7000p_write_word(state, 900, clk_cfg0); |
246 | 329 | ||
247 | dib7000p_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff); | 330 | dib7000p_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff)); |
248 | dib7000p_write_word(state, 19, (bw->internal*1000 ) & 0xffff); | 331 | dib7000p_write_word(state, 19, (u16) ( (bw->internal*1000 ) & 0xffff)); |
249 | dib7000p_write_word(state, 21, (bw->ifreq >> 16) & 0xffff); | 332 | dib7000p_write_word(state, 21, (u16) ( (bw->ifreq >> 16) & 0xffff)); |
250 | dib7000p_write_word(state, 22, (bw->ifreq ) & 0xffff); | 333 | dib7000p_write_word(state, 22, (u16) ( (bw->ifreq ) & 0xffff)); |
251 | 334 | ||
252 | dib7000p_write_word(state, 72, bw->sad_cfg); | 335 | dib7000p_write_word(state, 72, bw->sad_cfg); |
253 | } | 336 | } |
@@ -255,7 +338,7 @@ static void dib7000p_reset_pll(struct dib7000p_state *state) | |||
255 | static int dib7000p_reset_gpio(struct dib7000p_state *st) | 338 | static int dib7000p_reset_gpio(struct dib7000p_state *st) |
256 | { | 339 | { |
257 | /* reset the GPIOs */ | 340 | /* reset the GPIOs */ |
258 | dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos); | 341 | dprintk( "gpio dir: %x: val: %x, pwm_pos: %x",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos); |
259 | 342 | ||
260 | dib7000p_write_word(st, 1029, st->gpio_dir); | 343 | dib7000p_write_word(st, 1029, st->gpio_dir); |
261 | dib7000p_write_word(st, 1030, st->gpio_val); | 344 | dib7000p_write_word(st, 1030, st->gpio_val); |
@@ -268,6 +351,120 @@ static int dib7000p_reset_gpio(struct dib7000p_state *st) | |||
268 | return 0; | 351 | return 0; |
269 | } | 352 | } |
270 | 353 | ||
354 | static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val) | ||
355 | { | ||
356 | st->gpio_dir = dib7000p_read_word(st, 1029); | ||
357 | st->gpio_dir &= ~(1 << num); /* reset the direction bit */ | ||
358 | st->gpio_dir |= (dir & 0x1) << num; /* set the new direction */ | ||
359 | dib7000p_write_word(st, 1029, st->gpio_dir); | ||
360 | |||
361 | st->gpio_val = dib7000p_read_word(st, 1030); | ||
362 | st->gpio_val &= ~(1 << num); /* reset the direction bit */ | ||
363 | st->gpio_val |= (val & 0x01) << num; /* set the new value */ | ||
364 | dib7000p_write_word(st, 1030, st->gpio_val); | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val) | ||
370 | { | ||
371 | struct dib7000p_state *state = demod->demodulator_priv; | ||
372 | return dib7000p_cfg_gpio(state, num, dir, val); | ||
373 | } | ||
374 | |||
375 | EXPORT_SYMBOL(dib7000p_set_gpio); | ||
376 | static u16 dib7000p_defaults[] = | ||
377 | |||
378 | { | ||
379 | // auto search configuration | ||
380 | 3, 2, | ||
381 | 0x0004, | ||
382 | 0x1000, | ||
383 | 0x0814, /* Equal Lock */ | ||
384 | |||
385 | 12, 6, | ||
386 | 0x001b, | ||
387 | 0x7740, | ||
388 | 0x005b, | ||
389 | 0x8d80, | ||
390 | 0x01c9, | ||
391 | 0xc380, | ||
392 | 0x0000, | ||
393 | 0x0080, | ||
394 | 0x0000, | ||
395 | 0x0090, | ||
396 | 0x0001, | ||
397 | 0xd4c0, | ||
398 | |||
399 | 1, 26, | ||
400 | 0x6680, // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26 | ||
401 | |||
402 | /* set ADC level to -16 */ | ||
403 | 11, 79, | ||
404 | (1 << 13) - 825 - 117, | ||
405 | (1 << 13) - 837 - 117, | ||
406 | (1 << 13) - 811 - 117, | ||
407 | (1 << 13) - 766 - 117, | ||
408 | (1 << 13) - 737 - 117, | ||
409 | (1 << 13) - 693 - 117, | ||
410 | (1 << 13) - 648 - 117, | ||
411 | (1 << 13) - 619 - 117, | ||
412 | (1 << 13) - 575 - 117, | ||
413 | (1 << 13) - 531 - 117, | ||
414 | (1 << 13) - 501 - 117, | ||
415 | |||
416 | 1, 142, | ||
417 | 0x0410, // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16 | ||
418 | |||
419 | /* disable power smoothing */ | ||
420 | 8, 145, | ||
421 | 0, | ||
422 | 0, | ||
423 | 0, | ||
424 | 0, | ||
425 | 0, | ||
426 | 0, | ||
427 | 0, | ||
428 | 0, | ||
429 | |||
430 | 1, 154, | ||
431 | 1 << 13, // P_fft_freq_dir=1, P_fft_nb_to_cut=0 | ||
432 | |||
433 | 1, 168, | ||
434 | 0x0ccd, // P_pha3_thres, default 0x3000 | ||
435 | |||
436 | // 1, 169, | ||
437 | // 0x0010, // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010 | ||
438 | |||
439 | 1, 183, | ||
440 | 0x200f, // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005 | ||
441 | |||
442 | 5, 187, | ||
443 | 0x023d, // P_adp_regul_cnt=573, default: 410 | ||
444 | 0x00a4, // P_adp_noise_cnt= | ||
445 | 0x00a4, // P_adp_regul_ext | ||
446 | 0x7ff0, // P_adp_noise_ext | ||
447 | 0x3ccc, // P_adp_fil | ||
448 | |||
449 | 1, 198, | ||
450 | 0x800, // P_equal_thres_wgn | ||
451 | |||
452 | 1, 222, | ||
453 | 0x0010, // P_fec_ber_rs_len=2 | ||
454 | |||
455 | 1, 235, | ||
456 | 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard | ||
457 | |||
458 | 2, 901, | ||
459 | 0x0006, // P_clk_cfg1 | ||
460 | (3 << 10) | (1 << 6), // P_divclksel=3 P_divbitsel=1 | ||
461 | |||
462 | 1, 905, | ||
463 | 0x2c8e, // Tuner IO bank: max drive (14mA) + divout pads max drive | ||
464 | |||
465 | 0, | ||
466 | }; | ||
467 | |||
271 | static int dib7000p_demod_reset(struct dib7000p_state *state) | 468 | static int dib7000p_demod_reset(struct dib7000p_state *state) |
272 | { | 469 | { |
273 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); | 470 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); |
@@ -292,111 +489,307 @@ static int dib7000p_demod_reset(struct dib7000p_state *state) | |||
292 | dib7000p_reset_pll(state); | 489 | dib7000p_reset_pll(state); |
293 | 490 | ||
294 | if (dib7000p_reset_gpio(state) != 0) | 491 | if (dib7000p_reset_gpio(state) != 0) |
295 | dprintk("-E- GPIO reset was not successful.\n"); | 492 | dprintk( "GPIO reset was not successful."); |
296 | 493 | ||
297 | if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0) | 494 | if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0) |
298 | dprintk("-E- OUTPUT_MODE could not be resetted.\n"); | 495 | dprintk( "OUTPUT_MODE could not be reset."); |
299 | 496 | ||
300 | /* unforce divstr regardless whether i2c enumeration was done or not */ | 497 | /* unforce divstr regardless whether i2c enumeration was done or not */ |
301 | dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) ); | 498 | dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) ); |
302 | 499 | ||
500 | dib7000p_set_bandwidth(state, 8000); | ||
501 | |||
502 | dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON); | ||
503 | dib7000p_sad_calib(state); | ||
504 | dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_OFF); | ||
505 | |||
506 | // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ... | ||
507 | if(state->cfg.tuner_is_baseband) | ||
508 | dib7000p_write_word(state, 36,0x0755); | ||
509 | else | ||
510 | dib7000p_write_word(state, 36,0x1f55); | ||
511 | |||
512 | dib7000p_write_tab(state, dib7000p_defaults); | ||
513 | |||
303 | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); | 514 | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); |
304 | 515 | ||
516 | |||
305 | return 0; | 517 | return 0; |
306 | } | 518 | } |
307 | 519 | ||
520 | static void dib7000p_pll_clk_cfg(struct dib7000p_state *state) | ||
521 | { | ||
522 | u16 tmp = 0; | ||
523 | tmp = dib7000p_read_word(state, 903); | ||
524 | dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll | ||
525 | tmp = dib7000p_read_word(state, 900); | ||
526 | dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock | ||
527 | } | ||
528 | |||
308 | static void dib7000p_restart_agc(struct dib7000p_state *state) | 529 | static void dib7000p_restart_agc(struct dib7000p_state *state) |
309 | { | 530 | { |
310 | // P_restart_iqc & P_restart_agc | 531 | // P_restart_iqc & P_restart_agc |
311 | dib7000p_write_word(state, 770, 0x0c00); | 532 | dib7000p_write_word(state, 770, (1 << 11) | (1 << 9)); |
312 | dib7000p_write_word(state, 770, 0x0000); | 533 | dib7000p_write_word(state, 770, 0x0000); |
313 | } | 534 | } |
314 | 535 | ||
315 | static void dib7000p_update_lna(struct dib7000p_state *state) | 536 | static int dib7000p_update_lna(struct dib7000p_state *state) |
316 | { | 537 | { |
317 | int i; | ||
318 | u16 dyn_gain; | 538 | u16 dyn_gain; |
319 | 539 | ||
320 | // when there is no LNA to program return immediatly | 540 | // when there is no LNA to program return immediatly |
321 | if (state->cfg.update_lna == NULL) | 541 | if (state->cfg.update_lna) { |
322 | return; | 542 | // read dyn_gain here (because it is demod-dependent and not fe) |
323 | |||
324 | for (i = 0; i < 5; i++) { | ||
325 | // read dyn_gain here (because it is demod-dependent and not tuner) | ||
326 | dyn_gain = dib7000p_read_word(state, 394); | 543 | dyn_gain = dib7000p_read_word(state, 394); |
327 | |||
328 | if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed | 544 | if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed |
329 | dib7000p_restart_agc(state); | 545 | dib7000p_restart_agc(state); |
330 | msleep(5); | 546 | return 1; |
331 | } else | 547 | } |
548 | } | ||
549 | |||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | static int dib7000p_set_agc_config(struct dib7000p_state *state, u8 band) | ||
554 | { | ||
555 | struct dibx000_agc_config *agc = NULL; | ||
556 | int i; | ||
557 | if (state->current_band == band && state->current_agc != NULL) | ||
558 | return 0; | ||
559 | state->current_band = band; | ||
560 | |||
561 | for (i = 0; i < state->cfg.agc_config_count; i++) | ||
562 | if (state->cfg.agc[i].band_caps & band) { | ||
563 | agc = &state->cfg.agc[i]; | ||
332 | break; | 564 | break; |
565 | } | ||
566 | |||
567 | if (agc == NULL) { | ||
568 | dprintk( "no valid AGC configuration found for band 0x%02x",band); | ||
569 | return -EINVAL; | ||
333 | } | 570 | } |
571 | |||
572 | state->current_agc = agc; | ||
573 | |||
574 | /* AGC */ | ||
575 | dib7000p_write_word(state, 75 , agc->setup ); | ||
576 | dib7000p_write_word(state, 76 , agc->inv_gain ); | ||
577 | dib7000p_write_word(state, 77 , agc->time_stabiliz ); | ||
578 | dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock); | ||
579 | |||
580 | // Demod AGC loop configuration | ||
581 | dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp); | ||
582 | dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp); | ||
583 | |||
584 | /* AGC continued */ | ||
585 | dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d", | ||
586 | state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); | ||
587 | |||
588 | if (state->wbd_ref != 0) | ||
589 | dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref); | ||
590 | else | ||
591 | dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref); | ||
592 | |||
593 | dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8)); | ||
594 | |||
595 | dib7000p_write_word(state, 107, agc->agc1_max); | ||
596 | dib7000p_write_word(state, 108, agc->agc1_min); | ||
597 | dib7000p_write_word(state, 109, agc->agc2_max); | ||
598 | dib7000p_write_word(state, 110, agc->agc2_min); | ||
599 | dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2); | ||
600 | dib7000p_write_word(state, 112, agc->agc1_pt3); | ||
601 | dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2); | ||
602 | dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2); | ||
603 | dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); | ||
604 | return 0; | ||
334 | } | 605 | } |
335 | 606 | ||
336 | static void dib7000p_pll_clk_cfg(struct dib7000p_state *state) | 607 | static int dib7000p_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch) |
337 | { | 608 | { |
338 | u16 tmp = 0; | 609 | struct dib7000p_state *state = demod->demodulator_priv; |
339 | tmp = dib7000p_read_word(state, 903); | 610 | int ret = -1; |
340 | dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll | 611 | u8 *agc_state = &state->agc_state; |
341 | tmp = dib7000p_read_word(state, 900); | 612 | u8 agc_split; |
342 | dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock | 613 | |
614 | switch (state->agc_state) { | ||
615 | case 0: | ||
616 | // set power-up level: interf+analog+AGC | ||
617 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); | ||
618 | dib7000p_set_adc_state(state, DIBX000_ADC_ON); | ||
619 | dib7000p_pll_clk_cfg(state); | ||
620 | |||
621 | if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0) | ||
622 | return -1; | ||
623 | |||
624 | ret = 7; | ||
625 | (*agc_state)++; | ||
626 | break; | ||
627 | |||
628 | case 1: | ||
629 | // AGC initialization | ||
630 | if (state->cfg.agc_control) | ||
631 | state->cfg.agc_control(&state->demod, 1); | ||
632 | |||
633 | dib7000p_write_word(state, 78, 32768); | ||
634 | if (!state->current_agc->perform_agc_softsplit) { | ||
635 | /* we are using the wbd - so slow AGC startup */ | ||
636 | /* force 0 split on WBD and restart AGC */ | ||
637 | dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8)); | ||
638 | (*agc_state)++; | ||
639 | ret = 5; | ||
640 | } else { | ||
641 | /* default AGC startup */ | ||
642 | (*agc_state) = 4; | ||
643 | /* wait AGC rough lock time */ | ||
644 | ret = 7; | ||
645 | } | ||
646 | |||
647 | dib7000p_restart_agc(state); | ||
648 | break; | ||
649 | |||
650 | case 2: /* fast split search path after 5sec */ | ||
651 | dib7000p_write_word(state, 75, state->current_agc->setup | (1 << 4)); /* freeze AGC loop */ | ||
652 | dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8)); /* fast split search 0.25kHz */ | ||
653 | (*agc_state)++; | ||
654 | ret = 14; | ||
655 | break; | ||
656 | |||
657 | case 3: /* split search ended */ | ||
658 | agc_split = (u8)dib7000p_read_word(state, 396); /* store the split value for the next time */ | ||
659 | dib7000p_write_word(state, 78, dib7000p_read_word(state, 394)); /* set AGC gain start value */ | ||
660 | |||
661 | dib7000p_write_word(state, 75, state->current_agc->setup); /* std AGC loop */ | ||
662 | dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */ | ||
663 | |||
664 | dib7000p_restart_agc(state); | ||
665 | |||
666 | dprintk( "SPLIT %p: %hd", demod, agc_split); | ||
667 | |||
668 | (*agc_state)++; | ||
669 | ret = 5; | ||
670 | break; | ||
671 | |||
672 | case 4: /* LNA startup */ | ||
673 | // wait AGC accurate lock time | ||
674 | ret = 7; | ||
675 | |||
676 | if (dib7000p_update_lna(state)) | ||
677 | // wait only AGC rough lock time | ||
678 | ret = 5; | ||
679 | else // nothing was done, go to the next state | ||
680 | (*agc_state)++; | ||
681 | break; | ||
682 | |||
683 | case 5: | ||
684 | if (state->cfg.agc_control) | ||
685 | state->cfg.agc_control(&state->demod, 0); | ||
686 | (*agc_state)++; | ||
687 | break; | ||
688 | default: | ||
689 | break; | ||
690 | } | ||
691 | return ret; | ||
343 | } | 692 | } |
344 | 693 | ||
345 | static void dib7000p_update_timf_freq(struct dib7000p_state *state) | 694 | static void dib7000p_update_timf(struct dib7000p_state *state) |
346 | { | 695 | { |
347 | u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428); | 696 | u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428); |
348 | state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100); | 697 | state->timf = timf * 160 / (state->current_bandwidth / 50); |
349 | dib7000p_write_word(state, 23, (u16) (timf >> 16)); | 698 | dib7000p_write_word(state, 23, (u16) (timf >> 16)); |
350 | dib7000p_write_word(state, 24, (u16) (timf & 0xffff)); | 699 | dib7000p_write_word(state, 24, (u16) (timf & 0xffff)); |
351 | dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf); | 700 | dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->cfg.bw->timf); |
701 | |||
352 | } | 702 | } |
353 | 703 | ||
354 | static void dib7000p_set_channel(struct dib7000p_state *state, struct dibx000_ofdm_channel *ch, u8 seq) | 704 | static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_frontend_parameters *ch, u8 seq) |
355 | { | 705 | { |
356 | u16 tmp, est[4]; // reg_26, reg_32, reg_33, reg_187, reg_188, reg_189, reg_190, reg_207, reg_208; | 706 | u16 value, est[4]; |
707 | |||
708 | dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)); | ||
357 | 709 | ||
358 | /* nfft, guard, qam, alpha */ | 710 | /* nfft, guard, qam, alpha */ |
359 | dib7000p_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha)); | 711 | value = 0; |
712 | switch (ch->u.ofdm.transmission_mode) { | ||
713 | case TRANSMISSION_MODE_2K: value |= (0 << 7); break; | ||
714 | case /* 4K MODE */ 255: value |= (2 << 7); break; | ||
715 | default: | ||
716 | case TRANSMISSION_MODE_8K: value |= (1 << 7); break; | ||
717 | } | ||
718 | switch (ch->u.ofdm.guard_interval) { | ||
719 | case GUARD_INTERVAL_1_32: value |= (0 << 5); break; | ||
720 | case GUARD_INTERVAL_1_16: value |= (1 << 5); break; | ||
721 | case GUARD_INTERVAL_1_4: value |= (3 << 5); break; | ||
722 | default: | ||
723 | case GUARD_INTERVAL_1_8: value |= (2 << 5); break; | ||
724 | } | ||
725 | switch (ch->u.ofdm.constellation) { | ||
726 | case QPSK: value |= (0 << 3); break; | ||
727 | case QAM_16: value |= (1 << 3); break; | ||
728 | default: | ||
729 | case QAM_64: value |= (2 << 3); break; | ||
730 | } | ||
731 | switch (HIERARCHY_1) { | ||
732 | case HIERARCHY_2: value |= 2; break; | ||
733 | case HIERARCHY_4: value |= 4; break; | ||
734 | default: | ||
735 | case HIERARCHY_1: value |= 1; break; | ||
736 | } | ||
737 | dib7000p_write_word(state, 0, value); | ||
360 | dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */ | 738 | dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */ |
361 | 739 | ||
362 | /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */ | 740 | /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */ |
363 | tmp = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1); | 741 | value = 0; |
364 | if (ch->vit_hrch == 0 || ch->vit_select_hp == 1) | 742 | if (1 != 0) |
365 | tmp |= (ch->vit_code_rate_hp << 1); | 743 | value |= (1 << 6); |
366 | else | 744 | if (ch->u.ofdm.hierarchy_information == 1) |
367 | tmp |= (ch->vit_code_rate_lp << 1); | 745 | value |= (1 << 4); |
368 | dib7000p_write_word(state, 208, tmp); | 746 | if (1 == 1) |
747 | value |= 1; | ||
748 | switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) { | ||
749 | case FEC_2_3: value |= (2 << 1); break; | ||
750 | case FEC_3_4: value |= (3 << 1); break; | ||
751 | case FEC_5_6: value |= (5 << 1); break; | ||
752 | case FEC_7_8: value |= (7 << 1); break; | ||
753 | default: | ||
754 | case FEC_1_2: value |= (1 << 1); break; | ||
755 | } | ||
756 | dib7000p_write_word(state, 208, value); | ||
757 | |||
758 | /* offset loop parameters */ | ||
759 | dib7000p_write_word(state, 26, 0x6680); // timf(6xxx) | ||
760 | dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3) | ||
761 | dib7000p_write_word(state, 29, 0x1273); // isi | ||
762 | dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5) | ||
369 | 763 | ||
370 | /* P_dvsy_sync_wait */ | 764 | /* P_dvsy_sync_wait */ |
371 | switch (ch->nfft) { | 765 | switch (ch->u.ofdm.transmission_mode) { |
372 | case 1: tmp = 256; break; | 766 | case TRANSMISSION_MODE_8K: value = 256; break; |
373 | case 2: tmp = 128; break; | 767 | case /* 4K MODE */ 255: value = 128; break; |
374 | case 0: | 768 | case TRANSMISSION_MODE_2K: |
375 | default: tmp = 64; break; | 769 | default: value = 64; break; |
376 | } | 770 | } |
377 | tmp *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin | 771 | switch (ch->u.ofdm.guard_interval) { |
378 | tmp <<= 4; | 772 | case GUARD_INTERVAL_1_16: value *= 2; break; |
379 | 773 | case GUARD_INTERVAL_1_8: value *= 4; break; | |
380 | /* deactive the possibility of diversity reception if extended interleave */ | 774 | case GUARD_INTERVAL_1_4: value *= 8; break; |
381 | /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ | 775 | default: |
382 | if (ch->intlv_native || ch->nfft == 1) | 776 | case GUARD_INTERVAL_1_32: value *= 1; break; |
383 | tmp |= (1 << 2) | (2 << 0); | 777 | } |
384 | dib7000p_write_word(state, 207, tmp); | 778 | state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO |
385 | 779 | ||
386 | dib7000p_write_word(state, 26, 0x6680); // timf(6xxx) | 780 | /* deactive the possibility of diversity reception if extended interleaver */ |
387 | dib7000p_write_word(state, 29, 0x1273); // isi inh1273 on1073 | 781 | state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K; |
388 | dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3) | 782 | dib7000p_set_diversity_in(&state->demod, state->div_state); |
389 | dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5) | ||
390 | 783 | ||
391 | /* channel estimation fine configuration */ | 784 | /* channel estimation fine configuration */ |
392 | switch (ch->nqam) { | 785 | switch (ch->u.ofdm.constellation) { |
393 | case 2: | 786 | case QAM_64: |
394 | est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ | 787 | est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ |
395 | est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ | 788 | est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ |
396 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | 789 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ |
397 | est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ | 790 | est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ |
398 | break; | 791 | break; |
399 | case 1: | 792 | case QAM_16: |
400 | est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ | 793 | est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ |
401 | est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ | 794 | est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ |
402 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | 795 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ |
@@ -409,66 +802,45 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dibx000_of | |||
409 | est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ | 802 | est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ |
410 | break; | 803 | break; |
411 | } | 804 | } |
412 | for (tmp = 0; tmp < 4; tmp++) | 805 | for (value = 0; value < 4; value++) |
413 | dib7000p_write_word(state, 187 + tmp, est[tmp]); | 806 | dib7000p_write_word(state, 187 + value, est[value]); |
414 | |||
415 | // set power-up level: interf+analog+AGC | ||
416 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); | ||
417 | dib7000p_set_adc_state(state, DIBX000_ADC_ON); | ||
418 | dib7000p_pll_clk_cfg(state); | ||
419 | msleep(7); | ||
420 | |||
421 | // AGC initialization | ||
422 | if (state->cfg.agc_control) | ||
423 | state->cfg.agc_control(&state->demod, 1); | ||
424 | |||
425 | dib7000p_restart_agc(state); | ||
426 | |||
427 | // wait AGC rough lock time | ||
428 | msleep(5); | ||
429 | |||
430 | dib7000p_update_lna(state); | ||
431 | |||
432 | // wait AGC accurate lock time | ||
433 | msleep(7); | ||
434 | if (state->cfg.agc_control) | ||
435 | state->cfg.agc_control(&state->demod, 0); | ||
436 | } | 807 | } |
437 | 808 | ||
438 | static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | 809 | static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch) |
439 | { | 810 | { |
440 | struct dib7000p_state *state = demod->demodulator_priv; | 811 | struct dib7000p_state *state = demod->demodulator_priv; |
441 | struct dibx000_ofdm_channel auto_ch; | 812 | struct dvb_frontend_parameters schan; |
442 | u32 value; | 813 | u32 value, factor; |
443 | 814 | ||
444 | INIT_OFDM_CHANNEL(&auto_ch); | 815 | schan = *ch; |
445 | auto_ch.RF_kHz = ch->RF_kHz; | 816 | schan.u.ofdm.constellation = QAM_64; |
446 | auto_ch.Bw = ch->Bw; | 817 | schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32; |
447 | auto_ch.nqam = 2; | 818 | schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; |
448 | auto_ch.guard = 0; | 819 | schan.u.ofdm.code_rate_HP = FEC_2_3; |
449 | auto_ch.nfft = 1; | 820 | schan.u.ofdm.code_rate_LP = FEC_3_4; |
450 | auto_ch.vit_alpha = 1; | 821 | schan.u.ofdm.hierarchy_information = 0; |
451 | auto_ch.vit_select_hp = 1; | 822 | |
452 | auto_ch.vit_code_rate_hp = 2; | 823 | dib7000p_set_channel(state, &schan, 7); |
453 | auto_ch.vit_code_rate_lp = 3; | 824 | |
454 | auto_ch.vit_hrch = 0; | 825 | factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth); |
455 | auto_ch.intlv_native = 1; | 826 | if (factor >= 5000) |
456 | 827 | factor = 1; | |
457 | dib7000p_set_channel(state, &auto_ch, 7); | 828 | else |
829 | factor = 6; | ||
458 | 830 | ||
459 | // always use the setting for 8MHz here lock_time for 7,6 MHz are longer | 831 | // always use the setting for 8MHz here lock_time for 7,6 MHz are longer |
460 | value = 30 * state->cfg.bw->internal; | 832 | value = 30 * state->cfg.bw->internal * factor; |
461 | dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time | 833 | dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time |
462 | dib7000p_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time | 834 | dib7000p_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time |
463 | value = 100 * state->cfg.bw->internal; | 835 | value = 100 * state->cfg.bw->internal * factor; |
464 | dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time | 836 | dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time |
465 | dib7000p_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time | 837 | dib7000p_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time |
466 | value = 500 * state->cfg.bw->internal; | 838 | value = 500 * state->cfg.bw->internal * factor; |
467 | dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time | 839 | dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time |
468 | dib7000p_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time | 840 | dib7000p_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time |
469 | 841 | ||
470 | value = dib7000p_read_word(state, 0); | 842 | value = dib7000p_read_word(state, 0); |
471 | dib7000p_write_word(state, 0, (1 << 9) | value); | 843 | dib7000p_write_word(state, 0, (u16) ((1 << 9) | value)); |
472 | dib7000p_read_word(state, 1284); | 844 | dib7000p_read_word(state, 1284); |
473 | dib7000p_write_word(state, 0, (u16) value); | 845 | dib7000p_write_word(state, 0, (u16) value); |
474 | 846 | ||
@@ -489,7 +861,95 @@ static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod) | |||
489 | return 0; // still pending | 861 | return 0; // still pending |
490 | } | 862 | } |
491 | 863 | ||
492 | static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | 864 | static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 bw) |
865 | { | ||
866 | static s16 notch[]={16143, 14402, 12238, 9713, 6902, 3888, 759, -2392}; | ||
867 | static u8 sine [] ={0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22, | ||
868 | 24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51, | ||
869 | 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80, | ||
870 | 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105, | ||
871 | 107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126, | ||
872 | 128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146, | ||
873 | 147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165, | ||
874 | 166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182, | ||
875 | 183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, | ||
876 | 199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212, | ||
877 | 213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224, | ||
878 | 225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235, | ||
879 | 235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243, | ||
880 | 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249, | ||
881 | 250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254, | ||
882 | 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
883 | 255, 255, 255, 255, 255, 255}; | ||
884 | |||
885 | u32 xtal = state->cfg.bw->xtal_hz / 1000; | ||
886 | int f_rel = ( (rf_khz + xtal/2) / xtal) * xtal - rf_khz; | ||
887 | int k; | ||
888 | int coef_re[8],coef_im[8]; | ||
889 | int bw_khz = bw; | ||
890 | u32 pha; | ||
891 | |||
892 | dprintk( "relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal); | ||
893 | |||
894 | |||
895 | if (f_rel < -bw_khz/2 || f_rel > bw_khz/2) | ||
896 | return; | ||
897 | |||
898 | bw_khz /= 100; | ||
899 | |||
900 | dib7000p_write_word(state, 142 ,0x0610); | ||
901 | |||
902 | for (k = 0; k < 8; k++) { | ||
903 | pha = ((f_rel * (k+1) * 112 * 80/bw_khz) /1000) & 0x3ff; | ||
904 | |||
905 | if (pha==0) { | ||
906 | coef_re[k] = 256; | ||
907 | coef_im[k] = 0; | ||
908 | } else if(pha < 256) { | ||
909 | coef_re[k] = sine[256-(pha&0xff)]; | ||
910 | coef_im[k] = sine[pha&0xff]; | ||
911 | } else if (pha == 256) { | ||
912 | coef_re[k] = 0; | ||
913 | coef_im[k] = 256; | ||
914 | } else if (pha < 512) { | ||
915 | coef_re[k] = -sine[pha&0xff]; | ||
916 | coef_im[k] = sine[256 - (pha&0xff)]; | ||
917 | } else if (pha == 512) { | ||
918 | coef_re[k] = -256; | ||
919 | coef_im[k] = 0; | ||
920 | } else if (pha < 768) { | ||
921 | coef_re[k] = -sine[256-(pha&0xff)]; | ||
922 | coef_im[k] = -sine[pha&0xff]; | ||
923 | } else if (pha == 768) { | ||
924 | coef_re[k] = 0; | ||
925 | coef_im[k] = -256; | ||
926 | } else { | ||
927 | coef_re[k] = sine[pha&0xff]; | ||
928 | coef_im[k] = -sine[256 - (pha&0xff)]; | ||
929 | } | ||
930 | |||
931 | coef_re[k] *= notch[k]; | ||
932 | coef_re[k] += (1<<14); | ||
933 | if (coef_re[k] >= (1<<24)) | ||
934 | coef_re[k] = (1<<24) - 1; | ||
935 | coef_re[k] /= (1<<15); | ||
936 | |||
937 | coef_im[k] *= notch[k]; | ||
938 | coef_im[k] += (1<<14); | ||
939 | if (coef_im[k] >= (1<<24)) | ||
940 | coef_im[k] = (1<<24)-1; | ||
941 | coef_im[k] /= (1<<15); | ||
942 | |||
943 | dprintk( "PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]); | ||
944 | |||
945 | dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff)); | ||
946 | dib7000p_write_word(state, 144, coef_im[k] & 0x3ff); | ||
947 | dib7000p_write_word(state, 143, (1 << 14) | (k << 10) | (coef_re[k] & 0x3ff)); | ||
948 | } | ||
949 | dib7000p_write_word(state,143 ,0); | ||
950 | } | ||
951 | |||
952 | static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch) | ||
493 | { | 953 | { |
494 | struct dib7000p_state *state = demod->demodulator_priv; | 954 | struct dib7000p_state *state = demod->demodulator_priv; |
495 | u16 tmp = 0; | 955 | u16 tmp = 0; |
@@ -505,7 +965,15 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel | |||
505 | msleep(45); | 965 | msleep(45); |
506 | 966 | ||
507 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ | 967 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ |
508 | dib7000p_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); | 968 | tmp = (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3); |
969 | if (state->sfn_workaround_active) { | ||
970 | dprintk( "SFN workaround is active"); | ||
971 | tmp |= (1 << 9); | ||
972 | dib7000p_write_word(state, 166, 0x4000); // P_pha3_force_pha_shift | ||
973 | } else { | ||
974 | dib7000p_write_word(state, 166, 0x0000); // P_pha3_force_pha_shift | ||
975 | } | ||
976 | dib7000p_write_word(state, 29, tmp); | ||
509 | 977 | ||
510 | // never achieved a lock with that bandwidth so far - wait for osc-freq to update | 978 | // never achieved a lock with that bandwidth so far - wait for osc-freq to update |
511 | if (state->timf == 0) | 979 | if (state->timf == 0) |
@@ -515,28 +983,31 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel | |||
515 | 983 | ||
516 | /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ | 984 | /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ |
517 | tmp = (6 << 8) | 0x80; | 985 | tmp = (6 << 8) | 0x80; |
518 | switch (ch->nfft) { | 986 | switch (ch->u.ofdm.transmission_mode) { |
519 | case 0: tmp |= (7 << 12); break; | 987 | case TRANSMISSION_MODE_2K: tmp |= (7 << 12); break; |
520 | case 1: tmp |= (9 << 12); break; | 988 | case /* 4K MODE */ 255: tmp |= (8 << 12); break; |
521 | case 2: tmp |= (8 << 12); break; | 989 | default: |
990 | case TRANSMISSION_MODE_8K: tmp |= (9 << 12); break; | ||
522 | } | 991 | } |
523 | dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */ | 992 | dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */ |
524 | 993 | ||
525 | /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ | 994 | /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ |
526 | tmp = (0 << 4); | 995 | tmp = (0 << 4); |
527 | switch (ch->nfft) { | 996 | switch (ch->u.ofdm.transmission_mode) { |
528 | case 0: tmp |= 0x6; break; | 997 | case TRANSMISSION_MODE_2K: tmp |= 0x6; break; |
529 | case 1: tmp |= 0x8; break; | 998 | case /* 4K MODE */ 255: tmp |= 0x7; break; |
530 | case 2: tmp |= 0x7; break; | 999 | default: |
1000 | case TRANSMISSION_MODE_8K: tmp |= 0x8; break; | ||
531 | } | 1001 | } |
532 | dib7000p_write_word(state, 32, tmp); | 1002 | dib7000p_write_word(state, 32, tmp); |
533 | 1003 | ||
534 | /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ | 1004 | /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ |
535 | tmp = (0 << 4); | 1005 | tmp = (0 << 4); |
536 | switch (ch->nfft) { | 1006 | switch (ch->u.ofdm.transmission_mode) { |
537 | case 0: tmp |= 0x6; break; | 1007 | case TRANSMISSION_MODE_2K: tmp |= 0x6; break; |
538 | case 1: tmp |= 0x8; break; | 1008 | case /* 4K MODE */ 255: tmp |= 0x7; break; |
539 | case 2: tmp |= 0x7; break; | 1009 | default: |
1010 | case TRANSMISSION_MODE_8K: tmp |= 0x8; break; | ||
540 | } | 1011 | } |
541 | dib7000p_write_word(state, 33, tmp); | 1012 | dib7000p_write_word(state, 33, tmp); |
542 | 1013 | ||
@@ -552,131 +1023,21 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel | |||
552 | 1023 | ||
553 | // we achieved a lock - it's time to update the osc freq | 1024 | // we achieved a lock - it's time to update the osc freq |
554 | if ((tmp >> 6) & 0x1) | 1025 | if ((tmp >> 6) & 0x1) |
555 | dib7000p_update_timf_freq(state); | 1026 | dib7000p_update_timf(state); |
556 | 1027 | ||
1028 | if (state->cfg.spur_protect) | ||
1029 | dib7000p_spur_protect(state, ch->frequency/1000, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)); | ||
1030 | |||
1031 | dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)); | ||
557 | return 0; | 1032 | return 0; |
558 | } | 1033 | } |
559 | 1034 | ||
560 | static int dib7000p_init(struct dvb_frontend *demod) | 1035 | static int dib7000p_wakeup(struct dvb_frontend *demod) |
561 | { | 1036 | { |
562 | struct dibx000_agc_config *agc; | ||
563 | struct dib7000p_state *state = demod->demodulator_priv; | 1037 | struct dib7000p_state *state = demod->demodulator_priv; |
564 | int ret = 0; | ||
565 | |||
566 | // Demodulator default configuration | ||
567 | agc = state->cfg.agc; | ||
568 | |||
569 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); | 1038 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); |
570 | dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON); | 1039 | dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON); |
571 | 1040 | return 0; | |
572 | /* AGC */ | ||
573 | ret |= dib7000p_write_word(state, 75 , agc->setup ); | ||
574 | ret |= dib7000p_write_word(state, 76 , agc->inv_gain ); | ||
575 | ret |= dib7000p_write_word(state, 77 , agc->time_stabiliz ); | ||
576 | ret |= dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock); | ||
577 | |||
578 | // Demod AGC loop configuration | ||
579 | ret |= dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp); | ||
580 | ret |= dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp); | ||
581 | |||
582 | /* AGC continued */ | ||
583 | dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", | ||
584 | state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); | ||
585 | |||
586 | if (state->wbd_ref != 0) | ||
587 | ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref); | ||
588 | else | ||
589 | ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref); | ||
590 | |||
591 | ret |= dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); | ||
592 | |||
593 | ret |= dib7000p_write_word(state, 107, agc->agc1_max); | ||
594 | ret |= dib7000p_write_word(state, 108, agc->agc1_min); | ||
595 | ret |= dib7000p_write_word(state, 109, agc->agc2_max); | ||
596 | ret |= dib7000p_write_word(state, 110, agc->agc2_min); | ||
597 | ret |= dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); | ||
598 | ret |= dib7000p_write_word(state, 112, agc->agc1_pt3); | ||
599 | ret |= dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2); | ||
600 | ret |= dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2); | ||
601 | ret |= dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); | ||
602 | |||
603 | /* disable power smoothing */ | ||
604 | ret |= dib7000p_write_word(state, 145, 0); | ||
605 | ret |= dib7000p_write_word(state, 146, 0); | ||
606 | ret |= dib7000p_write_word(state, 147, 0); | ||
607 | ret |= dib7000p_write_word(state, 148, 0); | ||
608 | ret |= dib7000p_write_word(state, 149, 0); | ||
609 | ret |= dib7000p_write_word(state, 150, 0); | ||
610 | ret |= dib7000p_write_word(state, 151, 0); | ||
611 | ret |= dib7000p_write_word(state, 152, 0); | ||
612 | |||
613 | // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26 | ||
614 | ret |= dib7000p_write_word(state, 26 ,0x6680); | ||
615 | |||
616 | // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16 | ||
617 | ret |= dib7000p_write_word(state, 142,0x0410); | ||
618 | // P_fft_freq_dir=1, P_fft_nb_to_cut=0 | ||
619 | ret |= dib7000p_write_word(state, 154,1 << 13); | ||
620 | // P_pha3_thres, default 0x3000 | ||
621 | ret |= dib7000p_write_word(state, 168,0x0ccd); | ||
622 | // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010 | ||
623 | //ret |= dib7000p_write_word(state, 169,0x0010); | ||
624 | // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005 | ||
625 | ret |= dib7000p_write_word(state, 183,0x200f); | ||
626 | // P_adp_regul_cnt=573, default: 410 | ||
627 | ret |= dib7000p_write_word(state, 187,0x023d); | ||
628 | // P_adp_noise_cnt= | ||
629 | ret |= dib7000p_write_word(state, 188,0x00a4); | ||
630 | // P_adp_regul_ext | ||
631 | ret |= dib7000p_write_word(state, 189,0x00a4); | ||
632 | // P_adp_noise_ext | ||
633 | ret |= dib7000p_write_word(state, 190,0x7ff0); | ||
634 | // P_adp_fil | ||
635 | ret |= dib7000p_write_word(state, 191,0x3ccc); | ||
636 | |||
637 | ret |= dib7000p_write_word(state, 222,0x0010); | ||
638 | // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard | ||
639 | ret |= dib7000p_write_word(state, 235,0x0062); | ||
640 | |||
641 | // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ... | ||
642 | if(state->cfg.tuner_is_baseband) | ||
643 | ret |= dib7000p_write_word(state, 36,0x0755); | ||
644 | else | ||
645 | ret |= dib7000p_write_word(state, 36,0x1f55); | ||
646 | |||
647 | // auto search configuration | ||
648 | ret |= dib7000p_write_word(state, 2 ,0x0004); | ||
649 | ret |= dib7000p_write_word(state, 3 ,0x1000); | ||
650 | |||
651 | /* Equal Lock */ | ||
652 | ret |= dib7000p_write_word(state, 4 ,0x0814); | ||
653 | |||
654 | ret |= dib7000p_write_word(state, 6 ,0x001b); | ||
655 | ret |= dib7000p_write_word(state, 7 ,0x7740); | ||
656 | ret |= dib7000p_write_word(state, 8 ,0x005b); | ||
657 | ret |= dib7000p_write_word(state, 9 ,0x8d80); | ||
658 | ret |= dib7000p_write_word(state, 10 ,0x01c9); | ||
659 | ret |= dib7000p_write_word(state, 11 ,0xc380); | ||
660 | ret |= dib7000p_write_word(state, 12 ,0x0000); | ||
661 | ret |= dib7000p_write_word(state, 13 ,0x0080); | ||
662 | ret |= dib7000p_write_word(state, 14 ,0x0000); | ||
663 | ret |= dib7000p_write_word(state, 15 ,0x0090); | ||
664 | ret |= dib7000p_write_word(state, 16 ,0x0001); | ||
665 | ret |= dib7000p_write_word(state, 17 ,0xd4c0); | ||
666 | |||
667 | // P_clk_cfg1 | ||
668 | ret |= dib7000p_write_word(state, 901, 0x0006); | ||
669 | |||
670 | // P_divclksel=3 P_divbitsel=1 | ||
671 | ret |= dib7000p_write_word(state, 902, (3 << 10) | (1 << 6)); | ||
672 | |||
673 | // Tuner IO bank: max drive (14mA) + divout pads max drive | ||
674 | ret |= dib7000p_write_word(state, 905, 0x2c8e); | ||
675 | |||
676 | ret |= dib7000p_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); | ||
677 | dib7000p_sad_calib(state); | ||
678 | |||
679 | return ret; | ||
680 | } | 1041 | } |
681 | 1042 | ||
682 | static int dib7000p_sleep(struct dvb_frontend *demod) | 1043 | static int dib7000p_sleep(struct dvb_frontend *demod) |
@@ -688,16 +1049,16 @@ static int dib7000p_sleep(struct dvb_frontend *demod) | |||
688 | static int dib7000p_identify(struct dib7000p_state *st) | 1049 | static int dib7000p_identify(struct dib7000p_state *st) |
689 | { | 1050 | { |
690 | u16 value; | 1051 | u16 value; |
691 | dprintk("-I- DiB7000PC: checking demod on I2C address: %d (%x)\n", | 1052 | dprintk( "checking demod on I2C address: %d (%x)", |
692 | st->i2c_addr, st->i2c_addr); | 1053 | st->i2c_addr, st->i2c_addr); |
693 | 1054 | ||
694 | if ((value = dib7000p_read_word(st, 768)) != 0x01b3) { | 1055 | if ((value = dib7000p_read_word(st, 768)) != 0x01b3) { |
695 | dprintk("-E- DiB7000PC: wrong Vendor ID (read=0x%x)\n",value); | 1056 | dprintk( "wrong Vendor ID (read=0x%x)",value); |
696 | return -EREMOTEIO; | 1057 | return -EREMOTEIO; |
697 | } | 1058 | } |
698 | 1059 | ||
699 | if ((value = dib7000p_read_word(st, 769)) != 0x4000) { | 1060 | if ((value = dib7000p_read_word(st, 769)) != 0x4000) { |
700 | dprintk("-E- DiB7000PC: wrong Device ID (%x)\n",value); | 1061 | dprintk( "wrong Device ID (%x)",value); |
701 | return -EREMOTEIO; | 1062 | return -EREMOTEIO; |
702 | } | 1063 | } |
703 | 1064 | ||
@@ -767,41 +1128,48 @@ static int dib7000p_set_frontend(struct dvb_frontend* fe, | |||
767 | struct dvb_frontend_parameters *fep) | 1128 | struct dvb_frontend_parameters *fep) |
768 | { | 1129 | { |
769 | struct dib7000p_state *state = fe->demodulator_priv; | 1130 | struct dib7000p_state *state = fe->demodulator_priv; |
770 | struct dibx000_ofdm_channel ch; | 1131 | int time; |
771 | |||
772 | INIT_OFDM_CHANNEL(&ch); | ||
773 | FEP2DIB(fep,&ch); | ||
774 | 1132 | ||
775 | state->current_bandwidth = fep->u.ofdm.bandwidth; | 1133 | state->current_bandwidth = fep->u.ofdm.bandwidth; |
776 | dib7000p_set_bandwidth(fe, fep->u.ofdm.bandwidth); | 1134 | dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth)); |
1135 | |||
1136 | /* maybe the parameter has been changed */ | ||
1137 | state->sfn_workaround_active = buggy_sfn_workaround; | ||
777 | 1138 | ||
778 | if (fe->ops.tuner_ops.set_params) | 1139 | if (fe->ops.tuner_ops.set_params) |
779 | fe->ops.tuner_ops.set_params(fe, fep); | 1140 | fe->ops.tuner_ops.set_params(fe, fep); |
780 | 1141 | ||
1142 | /* start up the AGC */ | ||
1143 | state->agc_state = 0; | ||
1144 | do { | ||
1145 | time = dib7000p_agc_startup(fe, fep); | ||
1146 | if (time != -1) | ||
1147 | msleep(time); | ||
1148 | } while (time != -1); | ||
1149 | |||
781 | if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || | 1150 | if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || |
782 | fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || | 1151 | fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || |
783 | fep->u.ofdm.constellation == QAM_AUTO || | 1152 | fep->u.ofdm.constellation == QAM_AUTO || |
784 | fep->u.ofdm.code_rate_HP == FEC_AUTO) { | 1153 | fep->u.ofdm.code_rate_HP == FEC_AUTO) { |
785 | int i = 800, found; | 1154 | int i = 800, found; |
786 | 1155 | ||
787 | dib7000p_autosearch_start(fe, &ch); | 1156 | dib7000p_autosearch_start(fe, fep); |
788 | do { | 1157 | do { |
789 | msleep(1); | 1158 | msleep(1); |
790 | found = dib7000p_autosearch_is_irq(fe); | 1159 | found = dib7000p_autosearch_is_irq(fe); |
791 | } while (found == 0 && i--); | 1160 | } while (found == 0 && i--); |
792 | 1161 | ||
793 | dprintk("autosearch returns: %d\n",found); | 1162 | dprintk("autosearch returns: %d",found); |
794 | if (found == 0 || found == 1) | 1163 | if (found == 0 || found == 1) |
795 | return 0; // no channel found | 1164 | return 0; // no channel found |
796 | 1165 | ||
797 | dib7000p_get_frontend(fe, fep); | 1166 | dib7000p_get_frontend(fe, fep); |
798 | FEP2DIB(fep, &ch); | ||
799 | } | 1167 | } |
800 | 1168 | ||
801 | /* make this a config parameter */ | 1169 | /* make this a config parameter */ |
802 | dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO); | 1170 | dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO); |
803 | 1171 | ||
804 | return dib7000p_tune(fe, &ch); | 1172 | return dib7000p_tune(fe, fep); |
805 | } | 1173 | } |
806 | 1174 | ||
807 | static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat) | 1175 | static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat) |
@@ -879,7 +1247,7 @@ int dib7000pc_detection(struct i2c_adapter *i2c_adap) | |||
879 | 1247 | ||
880 | if (i2c_transfer(i2c_adap, msg, 2) == 2) | 1248 | if (i2c_transfer(i2c_adap, msg, 2) == 2) |
881 | if (rx[0] == 0x01 && rx[1] == 0xb3) { | 1249 | if (rx[0] == 0x01 && rx[1] == 0xb3) { |
882 | dprintk("-D- DiB7000PC detected\n"); | 1250 | dprintk("-D- DiB7000PC detected"); |
883 | return 1; | 1251 | return 1; |
884 | } | 1252 | } |
885 | 1253 | ||
@@ -887,11 +1255,11 @@ int dib7000pc_detection(struct i2c_adapter *i2c_adap) | |||
887 | 1255 | ||
888 | if (i2c_transfer(i2c_adap, msg, 2) == 2) | 1256 | if (i2c_transfer(i2c_adap, msg, 2) == 2) |
889 | if (rx[0] == 0x01 && rx[1] == 0xb3) { | 1257 | if (rx[0] == 0x01 && rx[1] == 0xb3) { |
890 | dprintk("-D- DiB7000PC detected\n"); | 1258 | dprintk("-D- DiB7000PC detected"); |
891 | return 1; | 1259 | return 1; |
892 | } | 1260 | } |
893 | 1261 | ||
894 | dprintk("-D- DiB7000PC not detected\n"); | 1262 | dprintk("-D- DiB7000PC not detected"); |
895 | return 0; | 1263 | return 0; |
896 | } | 1264 | } |
897 | EXPORT_SYMBOL(dib7000pc_detection); | 1265 | EXPORT_SYMBOL(dib7000pc_detection); |
@@ -929,7 +1297,7 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau | |||
929 | /* set new i2c address and force divstart */ | 1297 | /* set new i2c address and force divstart */ |
930 | dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2); | 1298 | dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2); |
931 | 1299 | ||
932 | dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); | 1300 | dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr); |
933 | } | 1301 | } |
934 | 1302 | ||
935 | for (k = 0; k < no_of_demods; k++) { | 1303 | for (k = 0; k < no_of_demods; k++) { |
@@ -1000,7 +1368,7 @@ static struct dvb_frontend_ops dib7000p_ops = { | |||
1000 | 1368 | ||
1001 | .release = dib7000p_release, | 1369 | .release = dib7000p_release, |
1002 | 1370 | ||
1003 | .init = dib7000p_init, | 1371 | .init = dib7000p_wakeup, |
1004 | .sleep = dib7000p_sleep, | 1372 | .sleep = dib7000p_sleep, |
1005 | 1373 | ||
1006 | .set_frontend = dib7000p_set_frontend, | 1374 | .set_frontend = dib7000p_set_frontend, |
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h index 79465cf1aced..eefcac8b5244 100644 --- a/drivers/media/dvb/frontends/dib7000p.h +++ b/drivers/media/dvb/frontends/dib7000p.h | |||
@@ -9,6 +9,7 @@ struct dib7000p_config { | |||
9 | u8 tuner_is_baseband; | 9 | u8 tuner_is_baseband; |
10 | int (*update_lna) (struct dvb_frontend *, u16 agc_global); | 10 | int (*update_lna) (struct dvb_frontend *, u16 agc_global); |
11 | 11 | ||
12 | u8 agc_config_count; | ||
12 | struct dibx000_agc_config *agc; | 13 | struct dibx000_agc_config *agc; |
13 | struct dibx000_bandwidth_config *bw; | 14 | struct dibx000_bandwidth_config *bw; |
14 | 15 | ||
@@ -27,20 +28,19 @@ struct dib7000p_config { | |||
27 | 28 | ||
28 | u8 quartz_direct; | 29 | u8 quartz_direct; |
29 | 30 | ||
31 | u8 spur_protect; | ||
32 | |||
30 | int (*agc_control) (struct dvb_frontend *, u8 before); | 33 | int (*agc_control) (struct dvb_frontend *, u8 before); |
31 | }; | 34 | }; |
32 | 35 | ||
33 | #define DEFAULT_DIB7000P_I2C_ADDRESS 18 | 36 | #define DEFAULT_DIB7000P_I2C_ADDRESS 18 |
34 | 37 | ||
35 | extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg); | 38 | extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg); |
39 | extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]); | ||
40 | |||
36 | extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); | 41 | extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); |
37 | extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); | 42 | extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); |
38 | 43 | extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); | |
39 | /* TODO | 44 | extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value); |
40 | extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val); | ||
41 | extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod); | ||
42 | extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff); | ||
43 | extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod); | ||
44 | */ | ||
45 | 45 | ||
46 | #endif | 46 | #endif |
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h index a1df604366c3..5e17275afd25 100644 --- a/drivers/media/dvb/frontends/dibx000_common.h +++ b/drivers/media/dvb/frontends/dibx000_common.h | |||
@@ -111,6 +111,8 @@ struct dibx000_bandwidth_config { | |||
111 | 111 | ||
112 | u32 ifreq; | 112 | u32 ifreq; |
113 | u32 timf; | 113 | u32 timf; |
114 | |||
115 | u32 xtal_hz; | ||
114 | }; | 116 | }; |
115 | 117 | ||
116 | enum dibx000_adc_states { | 118 | enum dibx000_adc_states { |
@@ -122,56 +124,17 @@ enum dibx000_adc_states { | |||
122 | DIBX000_VBG_DISABLE, | 124 | DIBX000_VBG_DISABLE, |
123 | }; | 125 | }; |
124 | 126 | ||
125 | #define BW_INDEX_TO_KHZ(v) ( (v) == BANDWIDTH_8_MHZ ? 8000 : \ | 127 | #define BANDWIDTH_TO_KHZ(v) ( (v) == BANDWIDTH_8_MHZ ? 8000 : \ |
126 | (v) == BANDWIDTH_7_MHZ ? 7000 : \ | 128 | (v) == BANDWIDTH_7_MHZ ? 7000 : \ |
127 | (v) == BANDWIDTH_6_MHZ ? 6000 : 8000 ) | 129 | (v) == BANDWIDTH_6_MHZ ? 6000 : 8000 ) |
128 | 130 | ||
129 | /* Chip output mode. */ | 131 | /* Chip output mode. */ |
130 | #define OUTMODE_HIGH_Z 0 | 132 | #define OUTMODE_HIGH_Z 0 |
131 | #define OUTMODE_MPEG2_PAR_GATED_CLK 1 | 133 | #define OUTMODE_MPEG2_PAR_GATED_CLK 1 |
132 | #define OUTMODE_MPEG2_PAR_CONT_CLK 2 | 134 | #define OUTMODE_MPEG2_PAR_CONT_CLK 2 |
133 | #define OUTMODE_MPEG2_SERIAL 7 | 135 | #define OUTMODE_MPEG2_SERIAL 7 |
134 | #define OUTMODE_DIVERSITY 4 | 136 | #define OUTMODE_DIVERSITY 4 |
135 | #define OUTMODE_MPEG2_FIFO 5 | 137 | #define OUTMODE_MPEG2_FIFO 5 |
136 | 138 | #define OUTMODE_ANALOG_ADC 6 | |
137 | /* I hope I can get rid of the following kludge in the near future */ | ||
138 | struct dibx000_ofdm_channel { | ||
139 | u32 RF_kHz; | ||
140 | u8 Bw; | ||
141 | s16 nfft; | ||
142 | s16 guard; | ||
143 | s16 nqam; | ||
144 | s16 vit_hrch; | ||
145 | s16 vit_select_hp; | ||
146 | s16 vit_alpha; | ||
147 | s16 vit_code_rate_hp; | ||
148 | s16 vit_code_rate_lp; | ||
149 | u8 intlv_native; | ||
150 | }; | ||
151 | |||
152 | #define FEP2DIB(fep,ch) \ | ||
153 | (ch)->RF_kHz = (fep)->frequency / 1000; \ | ||
154 | (ch)->Bw = (fep)->u.ofdm.bandwidth; \ | ||
155 | (ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \ | ||
156 | (ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \ | ||
157 | (ch)->nqam = (fep)->u.ofdm.constellation == QAM_AUTO ? -1 : (fep)->u.ofdm.constellation == QAM_64 ? 2 : (fep)->u.ofdm.constellation; \ | ||
158 | (ch)->vit_hrch = 0; /* linux-dvb is not prepared for HIERARCHICAL TRANSMISSION */ \ | ||
159 | (ch)->vit_select_hp = 1; \ | ||
160 | (ch)->vit_alpha = 1; \ | ||
161 | (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \ | ||
162 | (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; \ | ||
163 | (ch)->intlv_native = 1; | ||
164 | |||
165 | #define INIT_OFDM_CHANNEL(ch) do {\ | ||
166 | (ch)->Bw = 0; \ | ||
167 | (ch)->nfft = -1; \ | ||
168 | (ch)->guard = -1; \ | ||
169 | (ch)->nqam = -1; \ | ||
170 | (ch)->vit_hrch = -1; \ | ||
171 | (ch)->vit_select_hp = -1; \ | ||
172 | (ch)->vit_alpha = -1; \ | ||
173 | (ch)->vit_code_rate_hp = -1; \ | ||
174 | (ch)->vit_code_rate_lp = -1; \ | ||
175 | } while (0) | ||
176 | 139 | ||
177 | #endif | 140 | #endif |
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 11f7d5939bd9..8c8d7342d0b3 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c | |||
@@ -24,12 +24,48 @@ | |||
24 | 24 | ||
25 | #include "dvb-pll.h" | 25 | #include "dvb-pll.h" |
26 | 26 | ||
27 | struct dvb_pll_priv { | ||
28 | /* pll number */ | ||
29 | int nr; | ||
30 | |||
31 | /* i2c details */ | ||
32 | int pll_i2c_address; | ||
33 | struct i2c_adapter *i2c; | ||
34 | |||
35 | /* the PLL descriptor */ | ||
36 | struct dvb_pll_desc *pll_desc; | ||
37 | |||
38 | /* cached frequency/bandwidth */ | ||
39 | u32 frequency; | ||
40 | u32 bandwidth; | ||
41 | }; | ||
42 | |||
43 | #define DVB_PLL_MAX 64 | ||
44 | |||
45 | static unsigned int dvb_pll_devcount; | ||
46 | |||
47 | static int debug = 0; | ||
48 | module_param(debug, int, 0644); | ||
49 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
50 | |||
51 | static unsigned int input[DVB_PLL_MAX] = { [ 0 ... (DVB_PLL_MAX-1) ] = 0 }; | ||
52 | module_param_array(input, int, NULL, 0644); | ||
53 | MODULE_PARM_DESC(input,"specify rf input choice, 0 for autoselect (default)"); | ||
54 | |||
55 | static unsigned int id[DVB_PLL_MAX] = | ||
56 | { [ 0 ... (DVB_PLL_MAX-1) ] = DVB_PLL_UNDEFINED }; | ||
57 | module_param_array(id, int, NULL, 0644); | ||
58 | MODULE_PARM_DESC(id, "force pll id to use (DEBUG ONLY)"); | ||
59 | |||
60 | /* ----------------------------------------------------------- */ | ||
61 | |||
27 | struct dvb_pll_desc { | 62 | struct dvb_pll_desc { |
28 | char *name; | 63 | char *name; |
29 | u32 min; | 64 | u32 min; |
30 | u32 max; | 65 | u32 max; |
31 | u32 iffreq; | 66 | u32 iffreq; |
32 | void (*set)(u8 *buf, const struct dvb_frontend_parameters *params); | 67 | void (*set)(struct dvb_frontend *fe, u8 *buf, |
68 | const struct dvb_frontend_parameters *params); | ||
33 | u8 *initdata; | 69 | u8 *initdata; |
34 | u8 *sleepdata; | 70 | u8 *sleepdata; |
35 | int count; | 71 | int count; |
@@ -89,7 +125,7 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7610 = { | |||
89 | }, | 125 | }, |
90 | }; | 126 | }; |
91 | 127 | ||
92 | static void thomson_dtt759x_bw(u8 *buf, | 128 | static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf, |
93 | const struct dvb_frontend_parameters *params) | 129 | const struct dvb_frontend_parameters *params) |
94 | { | 130 | { |
95 | if (BANDWIDTH_7_MHZ == params->u.ofdm.bandwidth) | 131 | if (BANDWIDTH_7_MHZ == params->u.ofdm.bandwidth) |
@@ -210,7 +246,8 @@ static struct dvb_pll_desc dvb_pll_env57h1xd5 = { | |||
210 | /* Philips TDA6650/TDA6651 | 246 | /* Philips TDA6650/TDA6651 |
211 | * used in Panasonic ENV77H11D5 | 247 | * used in Panasonic ENV77H11D5 |
212 | */ | 248 | */ |
213 | static void tda665x_bw(u8 *buf, const struct dvb_frontend_parameters *params) | 249 | static void tda665x_bw(struct dvb_frontend *fe, u8 *buf, |
250 | const struct dvb_frontend_parameters *params) | ||
214 | { | 251 | { |
215 | if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) | 252 | if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) |
216 | buf[3] |= 0x08; | 253 | buf[3] |= 0x08; |
@@ -243,7 +280,8 @@ static struct dvb_pll_desc dvb_pll_tda665x = { | |||
243 | /* Infineon TUA6034 | 280 | /* Infineon TUA6034 |
244 | * used in LG TDTP E102P | 281 | * used in LG TDTP E102P |
245 | */ | 282 | */ |
246 | static void tua6034_bw(u8 *buf, const struct dvb_frontend_parameters *params) | 283 | static void tua6034_bw(struct dvb_frontend *fe, u8 *buf, |
284 | const struct dvb_frontend_parameters *params) | ||
247 | { | 285 | { |
248 | if (BANDWIDTH_7_MHZ != params->u.ofdm.bandwidth) | 286 | if (BANDWIDTH_7_MHZ != params->u.ofdm.bandwidth) |
249 | buf[3] |= 0x08; | 287 | buf[3] |= 0x08; |
@@ -283,7 +321,8 @@ static struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = { | |||
283 | /* Philips FMD1216ME | 321 | /* Philips FMD1216ME |
284 | * used in Medion Hybrid PCMCIA card and USB Box | 322 | * used in Medion Hybrid PCMCIA card and USB Box |
285 | */ | 323 | */ |
286 | static void fmd1216me_bw(u8 *buf, const struct dvb_frontend_parameters *params) | 324 | static void fmd1216me_bw(struct dvb_frontend *fe, u8 *buf, |
325 | const struct dvb_frontend_parameters *params) | ||
287 | { | 326 | { |
288 | if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ && | 327 | if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ && |
289 | params->frequency >= 158870000) | 328 | params->frequency >= 158870000) |
@@ -313,7 +352,8 @@ static struct dvb_pll_desc dvb_pll_fmd1216me = { | |||
313 | /* ALPS TDED4 | 352 | /* ALPS TDED4 |
314 | * used in Nebula-Cards and USB boxes | 353 | * used in Nebula-Cards and USB boxes |
315 | */ | 354 | */ |
316 | static void tded4_bw(u8 *buf, const struct dvb_frontend_parameters *params) | 355 | static void tded4_bw(struct dvb_frontend *fe, u8 *buf, |
356 | const struct dvb_frontend_parameters *params) | ||
317 | { | 357 | { |
318 | if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) | 358 | if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) |
319 | buf[3] |= 0x04; | 359 | buf[3] |= 0x04; |
@@ -354,16 +394,35 @@ static struct dvb_pll_desc dvb_pll_tdhu2 = { | |||
354 | /* Philips TUV1236D | 394 | /* Philips TUV1236D |
355 | * used in ATI HDTV Wonder | 395 | * used in ATI HDTV Wonder |
356 | */ | 396 | */ |
357 | static void tuv1236d_rf(u8 *buf, const struct dvb_frontend_parameters *params) | 397 | static void tuv1236d_rf(struct dvb_frontend *fe, u8 *buf, |
398 | const struct dvb_frontend_parameters *params) | ||
358 | { | 399 | { |
359 | switch (params->u.vsb.modulation) { | 400 | struct dvb_pll_priv *priv = fe->tuner_priv; |
360 | case QAM_64: | 401 | unsigned int new_rf = input[priv->nr]; |
361 | case QAM_256: | 402 | |
403 | if ((new_rf == 0) || (new_rf > 2)) { | ||
404 | switch (params->u.vsb.modulation) { | ||
405 | case QAM_64: | ||
406 | case QAM_256: | ||
407 | new_rf = 1; | ||
408 | break; | ||
409 | case VSB_8: | ||
410 | default: | ||
411 | new_rf = 2; | ||
412 | } | ||
413 | } | ||
414 | |||
415 | switch (new_rf) { | ||
416 | case 1: | ||
362 | buf[3] |= 0x08; | 417 | buf[3] |= 0x08; |
363 | break; | 418 | break; |
364 | case VSB_8: | 419 | case 2: |
365 | default: | ||
366 | buf[3] &= ~0x08; | 420 | buf[3] &= ~0x08; |
421 | break; | ||
422 | default: | ||
423 | printk(KERN_WARNING | ||
424 | "%s: unhandled rf input selection: %d", | ||
425 | __FUNCTION__, new_rf); | ||
367 | } | 426 | } |
368 | } | 427 | } |
369 | 428 | ||
@@ -420,7 +479,8 @@ static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = { | |||
420 | /* | 479 | /* |
421 | * Philips TD1316 Tuner. | 480 | * Philips TD1316 Tuner. |
422 | */ | 481 | */ |
423 | static void td1316_bw(u8 *buf, const struct dvb_frontend_parameters *params) | 482 | static void td1316_bw(struct dvb_frontend *fe, u8 *buf, |
483 | const struct dvb_frontend_parameters *params) | ||
424 | { | 484 | { |
425 | u8 band; | 485 | u8 band; |
426 | 486 | ||
@@ -474,7 +534,8 @@ static struct dvb_pll_desc dvb_pll_thomson_fe6600 = { | |||
474 | } | 534 | } |
475 | }; | 535 | }; |
476 | 536 | ||
477 | static void opera1_bw(u8 *buf, const struct dvb_frontend_parameters *params) | 537 | static void opera1_bw(struct dvb_frontend *fe, u8 *buf, |
538 | const struct dvb_frontend_parameters *params) | ||
478 | { | 539 | { |
479 | if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) | 540 | if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) |
480 | buf[2] |= 0x08; | 541 | buf[2] |= 0x08; |
@@ -546,30 +607,13 @@ static struct dvb_pll_desc *pll_list[] = { | |||
546 | }; | 607 | }; |
547 | 608 | ||
548 | /* ----------------------------------------------------------- */ | 609 | /* ----------------------------------------------------------- */ |
549 | |||
550 | struct dvb_pll_priv { | ||
551 | /* i2c details */ | ||
552 | int pll_i2c_address; | ||
553 | struct i2c_adapter *i2c; | ||
554 | |||
555 | /* the PLL descriptor */ | ||
556 | struct dvb_pll_desc *pll_desc; | ||
557 | |||
558 | /* cached frequency/bandwidth */ | ||
559 | u32 frequency; | ||
560 | u32 bandwidth; | ||
561 | }; | ||
562 | |||
563 | /* ----------------------------------------------------------- */ | ||
564 | /* code */ | 610 | /* code */ |
565 | 611 | ||
566 | static int debug = 0; | 612 | static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf, |
567 | module_param(debug, int, 0644); | ||
568 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
569 | |||
570 | static int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, | ||
571 | const struct dvb_frontend_parameters *params) | 613 | const struct dvb_frontend_parameters *params) |
572 | { | 614 | { |
615 | struct dvb_pll_priv *priv = fe->tuner_priv; | ||
616 | struct dvb_pll_desc *desc = priv->pll_desc; | ||
573 | u32 div; | 617 | u32 div; |
574 | int i; | 618 | int i; |
575 | 619 | ||
@@ -597,7 +641,7 @@ static int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, | |||
597 | buf[3] = desc->entries[i].cb; | 641 | buf[3] = desc->entries[i].cb; |
598 | 642 | ||
599 | if (desc->set) | 643 | if (desc->set) |
600 | desc->set(buf, params); | 644 | desc->set(fe, buf, params); |
601 | 645 | ||
602 | if (debug) | 646 | if (debug) |
603 | printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", | 647 | printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", |
@@ -654,7 +698,7 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, | |||
654 | if (priv->i2c == NULL) | 698 | if (priv->i2c == NULL) |
655 | return -EINVAL; | 699 | return -EINVAL; |
656 | 700 | ||
657 | if ((result = dvb_pll_configure(priv->pll_desc, buf, params)) < 0) | 701 | if ((result = dvb_pll_configure(fe, buf, params)) < 0) |
658 | return result; | 702 | return result; |
659 | else | 703 | else |
660 | frequency = result; | 704 | frequency = result; |
@@ -682,7 +726,7 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe, | |||
682 | if (buf_len < 5) | 726 | if (buf_len < 5) |
683 | return -EINVAL; | 727 | return -EINVAL; |
684 | 728 | ||
685 | if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params)) < 0) | 729 | if ((result = dvb_pll_configure(fe, buf+1, params)) < 0) |
686 | return result; | 730 | return result; |
687 | else | 731 | else |
688 | frequency = result; | 732 | frequency = result; |
@@ -755,6 +799,10 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, | |||
755 | int ret; | 799 | int ret; |
756 | struct dvb_pll_desc *desc; | 800 | struct dvb_pll_desc *desc; |
757 | 801 | ||
802 | if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) && | ||
803 | (id[dvb_pll_devcount] < ARRAY_SIZE(pll_list))) | ||
804 | pll_desc_id = id[dvb_pll_devcount]; | ||
805 | |||
758 | BUG_ON(pll_desc_id < 1 || pll_desc_id >= ARRAY_SIZE(pll_list)); | 806 | BUG_ON(pll_desc_id < 1 || pll_desc_id >= ARRAY_SIZE(pll_list)); |
759 | 807 | ||
760 | desc = pll_list[pll_desc_id]; | 808 | desc = pll_list[pll_desc_id]; |
@@ -777,6 +825,7 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, | |||
777 | priv->pll_i2c_address = pll_addr; | 825 | priv->pll_i2c_address = pll_addr; |
778 | priv->i2c = i2c; | 826 | priv->i2c = i2c; |
779 | priv->pll_desc = desc; | 827 | priv->pll_desc = desc; |
828 | priv->nr = dvb_pll_devcount++; | ||
780 | 829 | ||
781 | memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, | 830 | memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, |
782 | sizeof(struct dvb_tuner_ops)); | 831 | sizeof(struct dvb_tuner_ops)); |
@@ -791,6 +840,30 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, | |||
791 | fe->ops.tuner_ops.sleep = NULL; | 840 | fe->ops.tuner_ops.sleep = NULL; |
792 | 841 | ||
793 | fe->tuner_priv = priv; | 842 | fe->tuner_priv = priv; |
843 | |||
844 | if ((debug) || (id[priv->nr] == pll_desc_id)) { | ||
845 | printk("dvb-pll[%d]", priv->nr); | ||
846 | if (i2c != NULL) | ||
847 | printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr); | ||
848 | printk(": id# %d (%s) attached, %s\n", pll_desc_id, desc->name, | ||
849 | id[priv->nr] == pll_desc_id ? | ||
850 | "insmod option" : "autodetected"); | ||
851 | } | ||
852 | if ((debug) || (input[priv->nr] > 0)) { | ||
853 | printk("dvb-pll[%d]", priv->nr); | ||
854 | if (i2c != NULL) | ||
855 | printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr); | ||
856 | printk(": tuner rf input will be "); | ||
857 | switch (input[priv->nr]) { | ||
858 | case 0: | ||
859 | printk("autoselected\n"); | ||
860 | break; | ||
861 | default: | ||
862 | printk("set to input %d (insmod option)\n", | ||
863 | input[priv->nr]); | ||
864 | } | ||
865 | } | ||
866 | |||
794 | return fe; | 867 | return fe; |
795 | } | 868 | } |
796 | EXPORT_SYMBOL(dvb_pll_attach); | 869 | EXPORT_SYMBOL(dvb_pll_attach); |
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c index 6271b1e7f6ab..fed09dfb2b7c 100644 --- a/drivers/media/dvb/frontends/dvb_dummy_fe.c +++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c | |||
@@ -20,7 +20,6 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/moduleparam.h> | ||
24 | #include <linux/init.h> | 23 | #include <linux/init.h> |
25 | #include <linux/string.h> | 24 | #include <linux/string.h> |
26 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
diff --git a/drivers/media/dvb/frontends/isl6421.c b/drivers/media/dvb/frontends/isl6421.c index c967148a5945..684c8ec166cb 100644 --- a/drivers/media/dvb/frontends/isl6421.c +++ b/drivers/media/dvb/frontends/isl6421.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/moduleparam.h> | ||
33 | #include <linux/string.h> | 32 | #include <linux/string.h> |
34 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
35 | 34 | ||
diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c index 1aeacb1c4af7..443d9045d4c9 100644 --- a/drivers/media/dvb/frontends/l64781.c +++ b/drivers/media/dvb/frontends/l64781.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/string.h> | 26 | #include <linux/string.h> |
28 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
29 | #include "dvb_frontend.h" | 28 | #include "dvb_frontend.h" |
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index e25286e2d431..bdc9fa88b86a 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c | |||
@@ -35,7 +35,6 @@ | |||
35 | 35 | ||
36 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | #include <linux/moduleparam.h> | ||
39 | #include <linux/init.h> | 38 | #include <linux/init.h> |
40 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
41 | #include <linux/string.h> | 40 | #include <linux/string.h> |
diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c index 2d2f58c26226..76f935d9755a 100644 --- a/drivers/media/dvb/frontends/lnbp21.c +++ b/drivers/media/dvb/frontends/lnbp21.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/string.h> | 31 | #include <linux/string.h> |
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
34 | 33 | ||
diff --git a/drivers/media/dvb/frontends/mt2060.c b/drivers/media/dvb/frontends/mt2060.c index 450fad8d9b65..1305b0e63ce5 100644 --- a/drivers/media/dvb/frontends/mt2060.c +++ b/drivers/media/dvb/frontends/mt2060.c | |||
@@ -22,7 +22,6 @@ | |||
22 | /* In that file, frequencies are expressed in kiloHertz to avoid 32 bits overflows */ | 22 | /* In that file, frequencies are expressed in kiloHertz to avoid 32 bits overflows */ |
23 | 23 | ||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/dvb/frontend.h> | 26 | #include <linux/dvb/frontend.h> |
28 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
diff --git a/drivers/media/dvb/frontends/mt2131.c b/drivers/media/dvb/frontends/mt2131.c new file mode 100644 index 000000000000..4b93931de4e1 --- /dev/null +++ b/drivers/media/dvb/frontends/mt2131.c | |||
@@ -0,0 +1,314 @@ | |||
1 | /* | ||
2 | * Driver for Microtune MT2131 "QAM/8VSB single chip tuner" | ||
3 | * | ||
4 | * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/dvb/frontend.h> | ||
25 | #include <linux/i2c.h> | ||
26 | |||
27 | #include "dvb_frontend.h" | ||
28 | |||
29 | #include "mt2131.h" | ||
30 | #include "mt2131_priv.h" | ||
31 | |||
32 | static int debug; | ||
33 | module_param(debug, int, 0644); | ||
34 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | ||
35 | |||
36 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | ||
37 | printk(KERN_INFO "%s: " fmt, "mt2131", ## arg) | ||
38 | |||
39 | static u8 mt2131_config1[] = { | ||
40 | 0x01, | ||
41 | 0x50, 0x00, 0x50, 0x80, 0x00, 0x49, 0xfa, 0x88, | ||
42 | 0x08, 0x77, 0x41, 0x04, 0x00, 0x00, 0x00, 0x32, | ||
43 | 0x7f, 0xda, 0x4c, 0x00, 0x10, 0xaa, 0x78, 0x80, | ||
44 | 0xff, 0x68, 0xa0, 0xff, 0xdd, 0x00, 0x00 | ||
45 | }; | ||
46 | |||
47 | static u8 mt2131_config2[] = { | ||
48 | 0x10, | ||
49 | 0x7f, 0xc8, 0x0a, 0x5f, 0x00, 0x04 | ||
50 | }; | ||
51 | |||
52 | static int mt2131_readreg(struct mt2131_priv *priv, u8 reg, u8 *val) | ||
53 | { | ||
54 | struct i2c_msg msg[2] = { | ||
55 | { .addr = priv->cfg->i2c_address, .flags = 0, | ||
56 | .buf = ®, .len = 1 }, | ||
57 | { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, | ||
58 | .buf = val, .len = 1 }, | ||
59 | }; | ||
60 | |||
61 | if (i2c_transfer(priv->i2c, msg, 2) != 2) { | ||
62 | printk(KERN_WARNING "mt2131 I2C read failed\n"); | ||
63 | return -EREMOTEIO; | ||
64 | } | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static int mt2131_writereg(struct mt2131_priv *priv, u8 reg, u8 val) | ||
69 | { | ||
70 | u8 buf[2] = { reg, val }; | ||
71 | struct i2c_msg msg = { .addr = priv->cfg->i2c_address, .flags = 0, | ||
72 | .buf = buf, .len = 2 }; | ||
73 | |||
74 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | ||
75 | printk(KERN_WARNING "mt2131 I2C write failed\n"); | ||
76 | return -EREMOTEIO; | ||
77 | } | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static int mt2131_writeregs(struct mt2131_priv *priv,u8 *buf, u8 len) | ||
82 | { | ||
83 | struct i2c_msg msg = { .addr = priv->cfg->i2c_address, | ||
84 | .flags = 0, .buf = buf, .len = len }; | ||
85 | |||
86 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | ||
87 | printk(KERN_WARNING "mt2131 I2C write failed (len=%i)\n", | ||
88 | (int)len); | ||
89 | return -EREMOTEIO; | ||
90 | } | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static int mt2131_set_params(struct dvb_frontend *fe, | ||
95 | struct dvb_frontend_parameters *params) | ||
96 | { | ||
97 | struct mt2131_priv *priv; | ||
98 | int ret=0, i; | ||
99 | u32 freq; | ||
100 | u8 if_band_center; | ||
101 | u32 f_lo1, f_lo2; | ||
102 | u32 div1, num1, div2, num2; | ||
103 | u8 b[8]; | ||
104 | u8 lockval = 0; | ||
105 | |||
106 | priv = fe->tuner_priv; | ||
107 | if (fe->ops.info.type == FE_OFDM) | ||
108 | priv->bandwidth = params->u.ofdm.bandwidth; | ||
109 | else | ||
110 | priv->bandwidth = 0; | ||
111 | |||
112 | freq = params->frequency / 1000; // Hz -> kHz | ||
113 | dprintk(1, "%s() freq=%d\n", __FUNCTION__, freq); | ||
114 | |||
115 | f_lo1 = freq + MT2131_IF1 * 1000; | ||
116 | f_lo1 = (f_lo1 / 250) * 250; | ||
117 | f_lo2 = f_lo1 - freq - MT2131_IF2; | ||
118 | |||
119 | priv->frequency = (f_lo1 - f_lo2 - MT2131_IF2) * 1000, | ||
120 | |||
121 | /* Frequency LO1 = 16MHz * (DIV1 + NUM1/8192 ) */ | ||
122 | num1 = f_lo1 * 64 / (MT2131_FREF / 128); | ||
123 | div1 = num1 / 8192; | ||
124 | num1 &= 0x1fff; | ||
125 | |||
126 | /* Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 ) */ | ||
127 | num2 = f_lo2 * 64 / (MT2131_FREF / 128); | ||
128 | div2 = num2 / 8192; | ||
129 | num2 &= 0x1fff; | ||
130 | |||
131 | if (freq <= 82500) if_band_center = 0x00; else | ||
132 | if (freq <= 137500) if_band_center = 0x01; else | ||
133 | if (freq <= 192500) if_band_center = 0x02; else | ||
134 | if (freq <= 247500) if_band_center = 0x03; else | ||
135 | if (freq <= 302500) if_band_center = 0x04; else | ||
136 | if (freq <= 357500) if_band_center = 0x05; else | ||
137 | if (freq <= 412500) if_band_center = 0x06; else | ||
138 | if (freq <= 467500) if_band_center = 0x07; else | ||
139 | if (freq <= 522500) if_band_center = 0x08; else | ||
140 | if (freq <= 577500) if_band_center = 0x09; else | ||
141 | if (freq <= 632500) if_band_center = 0x0A; else | ||
142 | if (freq <= 687500) if_band_center = 0x0B; else | ||
143 | if (freq <= 742500) if_band_center = 0x0C; else | ||
144 | if (freq <= 797500) if_band_center = 0x0D; else | ||
145 | if (freq <= 852500) if_band_center = 0x0E; else | ||
146 | if (freq <= 907500) if_band_center = 0x0F; else | ||
147 | if (freq <= 962500) if_band_center = 0x10; else | ||
148 | if (freq <= 1017500) if_band_center = 0x11; else | ||
149 | if (freq <= 1072500) if_band_center = 0x12; else if_band_center = 0x13; | ||
150 | |||
151 | b[0] = 1; | ||
152 | b[1] = (num1 >> 5) & 0xFF; | ||
153 | b[2] = (num1 & 0x1F); | ||
154 | b[3] = div1; | ||
155 | b[4] = (num2 >> 5) & 0xFF; | ||
156 | b[5] = num2 & 0x1F; | ||
157 | b[6] = div2; | ||
158 | |||
159 | dprintk(1, "IF1: %dMHz IF2: %dMHz\n", MT2131_IF1, MT2131_IF2); | ||
160 | dprintk(1, "PLL freq=%dkHz band=%d\n", (int)freq, (int)if_band_center); | ||
161 | dprintk(1, "PLL f_lo1=%dkHz f_lo2=%dkHz\n", (int)f_lo1, (int)f_lo2); | ||
162 | dprintk(1, "PLL div1=%d num1=%d div2=%d num2=%d\n", | ||
163 | (int)div1, (int)num1, (int)div2, (int)num2); | ||
164 | dprintk(1, "PLL [1..6]: %2x %2x %2x %2x %2x %2x\n", | ||
165 | (int)b[1], (int)b[2], (int)b[3], (int)b[4], (int)b[5], | ||
166 | (int)b[6]); | ||
167 | |||
168 | ret = mt2131_writeregs(priv,b,7); | ||
169 | if (ret < 0) | ||
170 | return ret; | ||
171 | |||
172 | mt2131_writereg(priv, 0x0b, if_band_center); | ||
173 | |||
174 | /* Wait for lock */ | ||
175 | i = 0; | ||
176 | do { | ||
177 | mt2131_readreg(priv, 0x08, &lockval); | ||
178 | if ((lockval & 0x88) == 0x88) | ||
179 | break; | ||
180 | msleep(4); | ||
181 | i++; | ||
182 | } while (i < 10); | ||
183 | |||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
188 | { | ||
189 | struct mt2131_priv *priv = fe->tuner_priv; | ||
190 | dprintk(1, "%s()\n", __FUNCTION__); | ||
191 | *frequency = priv->frequency; | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | ||
196 | { | ||
197 | struct mt2131_priv *priv = fe->tuner_priv; | ||
198 | dprintk(1, "%s()\n", __FUNCTION__); | ||
199 | *bandwidth = priv->bandwidth; | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static int mt2131_get_status(struct dvb_frontend *fe, u32 *status) | ||
204 | { | ||
205 | struct mt2131_priv *priv = fe->tuner_priv; | ||
206 | u8 lock_status = 0; | ||
207 | u8 afc_status = 0; | ||
208 | |||
209 | *status = 0; | ||
210 | |||
211 | mt2131_readreg(priv, 0x08, &lock_status); | ||
212 | if ((lock_status & 0x88) == 0x88) | ||
213 | *status = TUNER_STATUS_LOCKED; | ||
214 | |||
215 | mt2131_readreg(priv, 0x09, &afc_status); | ||
216 | dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n", | ||
217 | __FUNCTION__, lock_status, afc_status); | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static int mt2131_init(struct dvb_frontend *fe) | ||
223 | { | ||
224 | struct mt2131_priv *priv = fe->tuner_priv; | ||
225 | int ret; | ||
226 | dprintk(1, "%s()\n", __FUNCTION__); | ||
227 | |||
228 | if ((ret = mt2131_writeregs(priv, mt2131_config1, | ||
229 | sizeof(mt2131_config1))) < 0) | ||
230 | return ret; | ||
231 | |||
232 | mt2131_writereg(priv, 0x0b, 0x09); | ||
233 | mt2131_writereg(priv, 0x15, 0x47); | ||
234 | mt2131_writereg(priv, 0x07, 0xf2); | ||
235 | mt2131_writereg(priv, 0x0b, 0x01); | ||
236 | |||
237 | if ((ret = mt2131_writeregs(priv, mt2131_config2, | ||
238 | sizeof(mt2131_config2))) < 0) | ||
239 | return ret; | ||
240 | |||
241 | return ret; | ||
242 | } | ||
243 | |||
244 | static int mt2131_release(struct dvb_frontend *fe) | ||
245 | { | ||
246 | dprintk(1, "%s()\n", __FUNCTION__); | ||
247 | kfree(fe->tuner_priv); | ||
248 | fe->tuner_priv = NULL; | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static const struct dvb_tuner_ops mt2131_tuner_ops = { | ||
253 | .info = { | ||
254 | .name = "Microtune MT2131", | ||
255 | .frequency_min = 48000000, | ||
256 | .frequency_max = 860000000, | ||
257 | .frequency_step = 50000, | ||
258 | }, | ||
259 | |||
260 | .release = mt2131_release, | ||
261 | .init = mt2131_init, | ||
262 | |||
263 | .set_params = mt2131_set_params, | ||
264 | .get_frequency = mt2131_get_frequency, | ||
265 | .get_bandwidth = mt2131_get_bandwidth, | ||
266 | .get_status = mt2131_get_status | ||
267 | }; | ||
268 | |||
269 | struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe, | ||
270 | struct i2c_adapter *i2c, | ||
271 | struct mt2131_config *cfg, u16 if1) | ||
272 | { | ||
273 | struct mt2131_priv *priv = NULL; | ||
274 | u8 id = 0; | ||
275 | |||
276 | dprintk(1, "%s()\n", __FUNCTION__); | ||
277 | |||
278 | priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL); | ||
279 | if (priv == NULL) | ||
280 | return NULL; | ||
281 | |||
282 | priv->cfg = cfg; | ||
283 | priv->bandwidth = 6000000; /* 6MHz */ | ||
284 | priv->i2c = i2c; | ||
285 | |||
286 | if (mt2131_readreg(priv, 0, &id) != 0) { | ||
287 | kfree(priv); | ||
288 | return NULL; | ||
289 | } | ||
290 | if ( (id != 0x3E) && (id != 0x3F) ) { | ||
291 | printk(KERN_ERR "MT2131: Device not found at addr 0x%02x\n", | ||
292 | cfg->i2c_address); | ||
293 | kfree(priv); | ||
294 | return NULL; | ||
295 | } | ||
296 | |||
297 | printk(KERN_INFO "MT2131: successfully identified at address 0x%02x\n", | ||
298 | cfg->i2c_address); | ||
299 | memcpy(&fe->ops.tuner_ops, &mt2131_tuner_ops, | ||
300 | sizeof(struct dvb_tuner_ops)); | ||
301 | |||
302 | fe->tuner_priv = priv; | ||
303 | return fe; | ||
304 | } | ||
305 | EXPORT_SYMBOL(mt2131_attach); | ||
306 | |||
307 | MODULE_AUTHOR("Steven Toth"); | ||
308 | MODULE_DESCRIPTION("Microtune MT2131 silicon tuner driver"); | ||
309 | MODULE_LICENSE("GPL"); | ||
310 | |||
311 | /* | ||
312 | * Local variables: | ||
313 | * c-basic-offset: 8 | ||
314 | */ | ||
diff --git a/drivers/media/dvb/frontends/mt2131.h b/drivers/media/dvb/frontends/mt2131.h new file mode 100644 index 000000000000..1e4ffe7dc8c8 --- /dev/null +++ b/drivers/media/dvb/frontends/mt2131.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * Driver for Microtune MT2131 "QAM/8VSB single chip tuner" | ||
3 | * | ||
4 | * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __MT2131_H__ | ||
23 | #define __MT2131_H__ | ||
24 | |||
25 | struct dvb_frontend; | ||
26 | struct i2c_adapter; | ||
27 | |||
28 | struct mt2131_config { | ||
29 | u8 i2c_address; | ||
30 | u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */ | ||
31 | }; | ||
32 | |||
33 | #if defined(CONFIG_DVB_TUNER_MT2131) || (defined(CONFIG_DVB_TUNER_MT2131_MODULE) && defined(MODULE)) | ||
34 | extern struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe, | ||
35 | struct i2c_adapter *i2c, | ||
36 | struct mt2131_config *cfg, | ||
37 | u16 if1); | ||
38 | #else | ||
39 | static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe, | ||
40 | struct i2c_adapter *i2c, | ||
41 | struct mt2131_config *cfg, | ||
42 | u16 if1) | ||
43 | { | ||
44 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | ||
45 | return NULL; | ||
46 | } | ||
47 | #endif /* CONFIG_DVB_TUNER_MT2131 */ | ||
48 | |||
49 | #endif /* __MT2131_H__ */ | ||
50 | |||
51 | /* | ||
52 | * Local variables: | ||
53 | * c-basic-offset: 8 | ||
54 | */ | ||
diff --git a/drivers/media/dvb/frontends/mt2131_priv.h b/drivers/media/dvb/frontends/mt2131_priv.h new file mode 100644 index 000000000000..e930759c2c00 --- /dev/null +++ b/drivers/media/dvb/frontends/mt2131_priv.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * Driver for Microtune MT2131 "QAM/8VSB single chip tuner" | ||
3 | * | ||
4 | * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __MT2131_PRIV_H__ | ||
23 | #define __MT2131_PRIV_H__ | ||
24 | |||
25 | /* Regs */ | ||
26 | #define MT2131_PWR 0x07 | ||
27 | #define MT2131_UPC_1 0x0b | ||
28 | #define MT2131_AGC_RL 0x10 | ||
29 | #define MT2131_MISC_2 0x15 | ||
30 | |||
31 | /* frequency values in KHz */ | ||
32 | #define MT2131_IF1 1220 | ||
33 | #define MT2131_IF2 44000 | ||
34 | #define MT2131_FREF 16000 | ||
35 | |||
36 | struct mt2131_priv { | ||
37 | struct mt2131_config *cfg; | ||
38 | struct i2c_adapter *i2c; | ||
39 | |||
40 | u32 frequency; | ||
41 | u32 bandwidth; | ||
42 | }; | ||
43 | |||
44 | #endif /* __MT2131_PRIV_H__ */ | ||
45 | |||
46 | /* | ||
47 | * Local variables: | ||
48 | * c-basic-offset: 8 | ||
49 | */ | ||
diff --git a/drivers/media/dvb/frontends/mt2266.c b/drivers/media/dvb/frontends/mt2266.c new file mode 100644 index 000000000000..03fe8265745f --- /dev/null +++ b/drivers/media/dvb/frontends/mt2266.c | |||
@@ -0,0 +1,287 @@ | |||
1 | /* | ||
2 | * Driver for Microtune MT2266 "Direct conversion low power broadband tuner" | ||
3 | * | ||
4 | * Copyright (c) 2007 Olivier DANET <odanet@caramail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/dvb/frontend.h> | ||
20 | #include <linux/i2c.h> | ||
21 | |||
22 | #include "dvb_frontend.h" | ||
23 | #include "mt2266.h" | ||
24 | |||
25 | #define I2C_ADDRESS 0x60 | ||
26 | |||
27 | #define REG_PART_REV 0 | ||
28 | #define REG_TUNE 1 | ||
29 | #define REG_BAND 6 | ||
30 | #define REG_BANDWIDTH 8 | ||
31 | #define REG_LOCK 0x12 | ||
32 | |||
33 | #define PART_REV 0x85 | ||
34 | |||
35 | struct mt2266_priv { | ||
36 | struct mt2266_config *cfg; | ||
37 | struct i2c_adapter *i2c; | ||
38 | |||
39 | u32 frequency; | ||
40 | u32 bandwidth; | ||
41 | }; | ||
42 | |||
43 | /* Here, frequencies are expressed in kiloHertz to avoid 32 bits overflows */ | ||
44 | |||
45 | static int debug; | ||
46 | module_param(debug, int, 0644); | ||
47 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | ||
48 | |||
49 | #define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2266: " args); printk("\n"); }} while (0) | ||
50 | |||
51 | // Reads a single register | ||
52 | static int mt2266_readreg(struct mt2266_priv *priv, u8 reg, u8 *val) | ||
53 | { | ||
54 | struct i2c_msg msg[2] = { | ||
55 | { .addr = priv->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, | ||
56 | { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 }, | ||
57 | }; | ||
58 | if (i2c_transfer(priv->i2c, msg, 2) != 2) { | ||
59 | printk(KERN_WARNING "MT2266 I2C read failed\n"); | ||
60 | return -EREMOTEIO; | ||
61 | } | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | // Writes a single register | ||
66 | static int mt2266_writereg(struct mt2266_priv *priv, u8 reg, u8 val) | ||
67 | { | ||
68 | u8 buf[2] = { reg, val }; | ||
69 | struct i2c_msg msg = { | ||
70 | .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2 | ||
71 | }; | ||
72 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | ||
73 | printk(KERN_WARNING "MT2266 I2C write failed\n"); | ||
74 | return -EREMOTEIO; | ||
75 | } | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | // Writes a set of consecutive registers | ||
80 | static int mt2266_writeregs(struct mt2266_priv *priv,u8 *buf, u8 len) | ||
81 | { | ||
82 | struct i2c_msg msg = { | ||
83 | .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len | ||
84 | }; | ||
85 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | ||
86 | printk(KERN_WARNING "MT2266 I2C write failed (len=%i)\n",(int)len); | ||
87 | return -EREMOTEIO; | ||
88 | } | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | // Initialisation sequences | ||
93 | static u8 mt2266_init1[] = { | ||
94 | REG_TUNE, | ||
95 | 0x00, 0x00, 0x28, 0x00, 0x52, 0x99, 0x3f }; | ||
96 | |||
97 | static u8 mt2266_init2[] = { | ||
98 | 0x17, 0x6d, 0x71, 0x61, 0xc0, 0xbf, 0xff, 0xdc, 0x00, 0x0a, | ||
99 | 0xd4, 0x03, 0x64, 0x64, 0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14, 0x01, 0x01, 0x01, 0x01, | ||
100 | 0x01, 0x01, 0x7f, 0x5e, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x77, 0x0f, 0x2d }; | ||
101 | |||
102 | static u8 mt2266_init_8mhz[] = { | ||
103 | REG_BANDWIDTH, | ||
104 | 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }; | ||
105 | |||
106 | static u8 mt2266_init_7mhz[] = { | ||
107 | REG_BANDWIDTH, | ||
108 | 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32 }; | ||
109 | |||
110 | static u8 mt2266_init_6mhz[] = { | ||
111 | REG_BANDWIDTH, | ||
112 | 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7 }; | ||
113 | |||
114 | #define FREF 30000 // Quartz oscillator 30 MHz | ||
115 | |||
116 | static int mt2266_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | ||
117 | { | ||
118 | struct mt2266_priv *priv; | ||
119 | int ret=0; | ||
120 | u32 freq; | ||
121 | u32 tune; | ||
122 | u8 lnaband; | ||
123 | u8 b[10]; | ||
124 | int i; | ||
125 | |||
126 | priv = fe->tuner_priv; | ||
127 | |||
128 | mt2266_writereg(priv,0x17,0x6d); | ||
129 | mt2266_writereg(priv,0x1c,0xff); | ||
130 | |||
131 | freq = params->frequency / 1000; // Hz -> kHz | ||
132 | priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; | ||
133 | priv->frequency = freq * 1000; | ||
134 | tune=2 * freq * (8192/16) / (FREF/16); | ||
135 | |||
136 | if (freq <= 495000) lnaband = 0xEE; else | ||
137 | if (freq <= 525000) lnaband = 0xDD; else | ||
138 | if (freq <= 550000) lnaband = 0xCC; else | ||
139 | if (freq <= 580000) lnaband = 0xBB; else | ||
140 | if (freq <= 605000) lnaband = 0xAA; else | ||
141 | if (freq <= 630000) lnaband = 0x99; else | ||
142 | if (freq <= 655000) lnaband = 0x88; else | ||
143 | if (freq <= 685000) lnaband = 0x77; else | ||
144 | if (freq <= 710000) lnaband = 0x66; else | ||
145 | if (freq <= 735000) lnaband = 0x55; else | ||
146 | if (freq <= 765000) lnaband = 0x44; else | ||
147 | if (freq <= 802000) lnaband = 0x33; else | ||
148 | if (freq <= 840000) lnaband = 0x22; else lnaband = 0x11; | ||
149 | |||
150 | msleep(100); | ||
151 | mt2266_writeregs(priv,(params->u.ofdm.bandwidth==BANDWIDTH_6_MHZ)?mt2266_init_6mhz: | ||
152 | (params->u.ofdm.bandwidth==BANDWIDTH_7_MHZ)?mt2266_init_7mhz: | ||
153 | mt2266_init_8mhz,sizeof(mt2266_init_8mhz)); | ||
154 | |||
155 | b[0] = REG_TUNE; | ||
156 | b[1] = (tune >> 8) & 0x1F; | ||
157 | b[2] = tune & 0xFF; | ||
158 | b[3] = tune >> 13; | ||
159 | mt2266_writeregs(priv,b,4); | ||
160 | |||
161 | dprintk("set_parms: tune=%d band=%d",(int)tune,(int)lnaband); | ||
162 | dprintk("set_parms: [1..3]: %2x %2x %2x",(int)b[1],(int)b[2],(int)b[3]); | ||
163 | |||
164 | b[0] = 0x05; | ||
165 | b[1] = 0x62; | ||
166 | b[2] = lnaband; | ||
167 | mt2266_writeregs(priv,b,3); | ||
168 | |||
169 | //Waits for pll lock or timeout | ||
170 | i = 0; | ||
171 | do { | ||
172 | mt2266_readreg(priv,REG_LOCK,b); | ||
173 | if ((b[0] & 0x40)==0x40) | ||
174 | break; | ||
175 | msleep(10); | ||
176 | i++; | ||
177 | } while (i<10); | ||
178 | dprintk("Lock when i=%i",(int)i); | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | static void mt2266_calibrate(struct mt2266_priv *priv) | ||
183 | { | ||
184 | mt2266_writereg(priv,0x11,0x03); | ||
185 | mt2266_writereg(priv,0x11,0x01); | ||
186 | |||
187 | mt2266_writeregs(priv,mt2266_init1,sizeof(mt2266_init1)); | ||
188 | mt2266_writeregs(priv,mt2266_init2,sizeof(mt2266_init2)); | ||
189 | |||
190 | mt2266_writereg(priv,0x33,0x5e); | ||
191 | mt2266_writereg(priv,0x10,0x10); | ||
192 | mt2266_writereg(priv,0x10,0x00); | ||
193 | |||
194 | mt2266_writeregs(priv,mt2266_init_8mhz,sizeof(mt2266_init_8mhz)); | ||
195 | |||
196 | msleep(25); | ||
197 | mt2266_writereg(priv,0x17,0x6d); | ||
198 | mt2266_writereg(priv,0x1c,0x00); | ||
199 | msleep(75); | ||
200 | mt2266_writereg(priv,0x17,0x6d); | ||
201 | mt2266_writereg(priv,0x1c,0xff); | ||
202 | } | ||
203 | |||
204 | static int mt2266_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
205 | { | ||
206 | struct mt2266_priv *priv = fe->tuner_priv; | ||
207 | *frequency = priv->frequency; | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static int mt2266_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | ||
212 | { | ||
213 | struct mt2266_priv *priv = fe->tuner_priv; | ||
214 | *bandwidth = priv->bandwidth; | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int mt2266_init(struct dvb_frontend *fe) | ||
219 | { | ||
220 | struct mt2266_priv *priv = fe->tuner_priv; | ||
221 | mt2266_writereg(priv,0x17,0x6d); | ||
222 | mt2266_writereg(priv,0x1c,0xff); | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int mt2266_sleep(struct dvb_frontend *fe) | ||
227 | { | ||
228 | struct mt2266_priv *priv = fe->tuner_priv; | ||
229 | mt2266_writereg(priv,0x17,0x6d); | ||
230 | mt2266_writereg(priv,0x1c,0x00); | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int mt2266_release(struct dvb_frontend *fe) | ||
235 | { | ||
236 | kfree(fe->tuner_priv); | ||
237 | fe->tuner_priv = NULL; | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static const struct dvb_tuner_ops mt2266_tuner_ops = { | ||
242 | .info = { | ||
243 | .name = "Microtune MT2266", | ||
244 | .frequency_min = 470000000, | ||
245 | .frequency_max = 860000000, | ||
246 | .frequency_step = 50000, | ||
247 | }, | ||
248 | .release = mt2266_release, | ||
249 | .init = mt2266_init, | ||
250 | .sleep = mt2266_sleep, | ||
251 | .set_params = mt2266_set_params, | ||
252 | .get_frequency = mt2266_get_frequency, | ||
253 | .get_bandwidth = mt2266_get_bandwidth | ||
254 | }; | ||
255 | |||
256 | struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg) | ||
257 | { | ||
258 | struct mt2266_priv *priv = NULL; | ||
259 | u8 id = 0; | ||
260 | |||
261 | priv = kzalloc(sizeof(struct mt2266_priv), GFP_KERNEL); | ||
262 | if (priv == NULL) | ||
263 | return NULL; | ||
264 | |||
265 | priv->cfg = cfg; | ||
266 | priv->i2c = i2c; | ||
267 | |||
268 | if (mt2266_readreg(priv,0,&id) != 0) { | ||
269 | kfree(priv); | ||
270 | return NULL; | ||
271 | } | ||
272 | if (id != PART_REV) { | ||
273 | kfree(priv); | ||
274 | return NULL; | ||
275 | } | ||
276 | printk(KERN_INFO "MT2266: successfully identified\n"); | ||
277 | memcpy(&fe->ops.tuner_ops, &mt2266_tuner_ops, sizeof(struct dvb_tuner_ops)); | ||
278 | |||
279 | fe->tuner_priv = priv; | ||
280 | mt2266_calibrate(priv); | ||
281 | return fe; | ||
282 | } | ||
283 | EXPORT_SYMBOL(mt2266_attach); | ||
284 | |||
285 | MODULE_AUTHOR("Olivier DANET"); | ||
286 | MODULE_DESCRIPTION("Microtune MT2266 silicon tuner driver"); | ||
287 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/mt2266.h b/drivers/media/dvb/frontends/mt2266.h new file mode 100644 index 000000000000..f31dd613ad37 --- /dev/null +++ b/drivers/media/dvb/frontends/mt2266.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * Driver for Microtune MT2266 "Direct conversion low power broadband tuner" | ||
3 | * | ||
4 | * Copyright (c) 2007 Olivier DANET <odanet@caramail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #ifndef MT2266_H | ||
18 | #define MT2266_H | ||
19 | |||
20 | struct dvb_frontend; | ||
21 | struct i2c_adapter; | ||
22 | |||
23 | struct mt2266_config { | ||
24 | u8 i2c_address; | ||
25 | }; | ||
26 | |||
27 | #if defined(CONFIG_DVB_TUNER_MT2266) || (defined(CONFIG_DVB_TUNER_MT2266_MODULE) && defined(MODULE)) | ||
28 | extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg); | ||
29 | #else | ||
30 | static inline struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg) | ||
31 | { | ||
32 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | ||
33 | return NULL; | ||
34 | } | ||
35 | #endif // CONFIG_DVB_TUNER_MT2266 | ||
36 | |||
37 | #endif | ||
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index 1ef821825641..0606b9a5b616 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/string.h> | 31 | #include <linux/string.h> |
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
34 | 33 | ||
diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c index 87e31ca7e108..5dd9b731f6f2 100644 --- a/drivers/media/dvb/frontends/mt352.c +++ b/drivers/media/dvb/frontends/mt352.c | |||
@@ -32,7 +32,6 @@ | |||
32 | 32 | ||
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/moduleparam.h> | ||
36 | #include <linux/init.h> | 35 | #include <linux/init.h> |
37 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
38 | #include <linux/string.h> | 37 | #include <linux/string.h> |
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index ddc84899cf86..fcf964fe1d6b 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <linux/kernel.h> | 44 | #include <linux/kernel.h> |
45 | #include <linux/init.h> | 45 | #include <linux/init.h> |
46 | #include <linux/module.h> | 46 | #include <linux/module.h> |
47 | #include <linux/moduleparam.h> | ||
48 | #include <linux/slab.h> | 47 | #include <linux/slab.h> |
49 | #include <linux/string.h> | 48 | #include <linux/string.h> |
50 | 49 | ||
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c index 3cc8b444b8f2..b314a1f2deed 100644 --- a/drivers/media/dvb/frontends/or51132.c +++ b/drivers/media/dvb/frontends/or51132.c | |||
@@ -36,7 +36,6 @@ | |||
36 | 36 | ||
37 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
39 | #include <linux/moduleparam.h> | ||
40 | #include <linux/init.h> | 39 | #include <linux/init.h> |
41 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
42 | #include <linux/string.h> | 41 | #include <linux/string.h> |
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c index f46d5a46683a..f02bd9445955 100644 --- a/drivers/media/dvb/frontends/or51211.c +++ b/drivers/media/dvb/frontends/or51211.c | |||
@@ -32,7 +32,6 @@ | |||
32 | 32 | ||
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/moduleparam.h> | ||
36 | #include <linux/device.h> | 35 | #include <linux/device.h> |
37 | #include <linux/firmware.h> | 36 | #include <linux/firmware.h> |
38 | #include <linux/string.h> | 37 | #include <linux/string.h> |
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c new file mode 100644 index 000000000000..30e8a705fad4 --- /dev/null +++ b/drivers/media/dvb/frontends/s5h1409.c | |||
@@ -0,0 +1,729 @@ | |||
1 | /* | ||
2 | Samsung S5H1409 VSB/QAM demodulator driver | ||
3 | |||
4 | Copyright (C) 2006 Steven Toth <stoth@hauppauge.com> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | |||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/string.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include "dvb_frontend.h" | ||
29 | #include "dvb-pll.h" | ||
30 | #include "s5h1409.h" | ||
31 | |||
32 | struct s5h1409_state { | ||
33 | |||
34 | struct i2c_adapter* i2c; | ||
35 | |||
36 | /* configuration settings */ | ||
37 | const struct s5h1409_config* config; | ||
38 | |||
39 | struct dvb_frontend frontend; | ||
40 | |||
41 | /* previous uncorrected block counter */ | ||
42 | fe_modulation_t current_modulation; | ||
43 | |||
44 | u32 current_frequency; | ||
45 | }; | ||
46 | |||
47 | static int debug = 0; | ||
48 | #define dprintk if (debug) printk | ||
49 | |||
50 | /* Register values to initialise the demod, this will set VSB by default */ | ||
51 | static struct init_tab { | ||
52 | u8 reg; | ||
53 | u16 data; | ||
54 | } init_tab[] = { | ||
55 | { 0x00, 0x0071, }, | ||
56 | { 0x01, 0x3213, }, | ||
57 | { 0x09, 0x0025, }, | ||
58 | { 0x1c, 0x001d, }, | ||
59 | { 0x1f, 0x002d, }, | ||
60 | { 0x20, 0x001d, }, | ||
61 | { 0x22, 0x0022, }, | ||
62 | { 0x23, 0x0020, }, | ||
63 | { 0x29, 0x110f, }, | ||
64 | { 0x2a, 0x10b4, }, | ||
65 | { 0x2b, 0x10ae, }, | ||
66 | { 0x2c, 0x0031, }, | ||
67 | { 0x31, 0x010d, }, | ||
68 | { 0x32, 0x0100, }, | ||
69 | { 0x44, 0x0510, }, | ||
70 | { 0x54, 0x0104, }, | ||
71 | { 0x58, 0x2222, }, | ||
72 | { 0x59, 0x1162, }, | ||
73 | { 0x5a, 0x3211, }, | ||
74 | { 0x5d, 0x0370, }, | ||
75 | { 0x5e, 0x0296, }, | ||
76 | { 0x61, 0x0010, }, | ||
77 | { 0x63, 0x4a00, }, | ||
78 | { 0x65, 0x0800, }, | ||
79 | { 0x71, 0x0003, }, | ||
80 | { 0x72, 0x0470, }, | ||
81 | { 0x81, 0x0002, }, | ||
82 | { 0x82, 0x0600, }, | ||
83 | { 0x86, 0x0002, }, | ||
84 | { 0x8a, 0x2c38, }, | ||
85 | { 0x8b, 0x2a37, }, | ||
86 | { 0x92, 0x302f, }, | ||
87 | { 0x93, 0x3332, }, | ||
88 | { 0x96, 0x000c, }, | ||
89 | { 0x99, 0x0101, }, | ||
90 | { 0x9c, 0x2e37, }, | ||
91 | { 0x9d, 0x2c37, }, | ||
92 | { 0x9e, 0x2c37, }, | ||
93 | { 0xab, 0x0100, }, | ||
94 | { 0xac, 0x1003, }, | ||
95 | { 0xad, 0x103f, }, | ||
96 | { 0xe2, 0x0100, }, | ||
97 | { 0x28, 0x1010, }, | ||
98 | { 0xb1, 0x000e, }, | ||
99 | }; | ||
100 | |||
101 | /* VSB SNR lookup table */ | ||
102 | static struct vsb_snr_tab { | ||
103 | u16 val; | ||
104 | u16 data; | ||
105 | } vsb_snr_tab[] = { | ||
106 | { 1023, 770, }, | ||
107 | { 923, 300, }, | ||
108 | { 918, 295, }, | ||
109 | { 915, 290, }, | ||
110 | { 911, 285, }, | ||
111 | { 906, 280, }, | ||
112 | { 901, 275, }, | ||
113 | { 896, 270, }, | ||
114 | { 891, 265, }, | ||
115 | { 885, 260, }, | ||
116 | { 879, 255, }, | ||
117 | { 873, 250, }, | ||
118 | { 864, 245, }, | ||
119 | { 858, 240, }, | ||
120 | { 850, 235, }, | ||
121 | { 841, 230, }, | ||
122 | { 832, 225, }, | ||
123 | { 823, 220, }, | ||
124 | { 812, 215, }, | ||
125 | { 802, 210, }, | ||
126 | { 788, 205, }, | ||
127 | { 778, 200, }, | ||
128 | { 767, 195, }, | ||
129 | { 753, 190, }, | ||
130 | { 740, 185, }, | ||
131 | { 725, 180, }, | ||
132 | { 707, 175, }, | ||
133 | { 689, 170, }, | ||
134 | { 671, 165, }, | ||
135 | { 656, 160, }, | ||
136 | { 637, 155, }, | ||
137 | { 616, 150, }, | ||
138 | { 542, 145, }, | ||
139 | { 519, 140, }, | ||
140 | { 507, 135, }, | ||
141 | { 497, 130, }, | ||
142 | { 492, 125, }, | ||
143 | { 474, 120, }, | ||
144 | { 300, 111, }, | ||
145 | { 0, 0, }, | ||
146 | }; | ||
147 | |||
148 | /* QAM64 SNR lookup table */ | ||
149 | static struct qam64_snr_tab { | ||
150 | u16 val; | ||
151 | u16 data; | ||
152 | } qam64_snr_tab[] = { | ||
153 | { 12, 300, }, | ||
154 | { 15, 290, }, | ||
155 | { 18, 280, }, | ||
156 | { 22, 270, }, | ||
157 | { 23, 268, }, | ||
158 | { 24, 266, }, | ||
159 | { 25, 264, }, | ||
160 | { 27, 262, }, | ||
161 | { 28, 260, }, | ||
162 | { 29, 258, }, | ||
163 | { 30, 256, }, | ||
164 | { 32, 254, }, | ||
165 | { 33, 252, }, | ||
166 | { 34, 250, }, | ||
167 | { 35, 249, }, | ||
168 | { 36, 248, }, | ||
169 | { 37, 247, }, | ||
170 | { 38, 246, }, | ||
171 | { 39, 245, }, | ||
172 | { 40, 244, }, | ||
173 | { 41, 243, }, | ||
174 | { 42, 241, }, | ||
175 | { 43, 240, }, | ||
176 | { 44, 239, }, | ||
177 | { 45, 238, }, | ||
178 | { 46, 237, }, | ||
179 | { 47, 236, }, | ||
180 | { 48, 235, }, | ||
181 | { 49, 234, }, | ||
182 | { 50, 233, }, | ||
183 | { 51, 232, }, | ||
184 | { 52, 231, }, | ||
185 | { 53, 230, }, | ||
186 | { 55, 229, }, | ||
187 | { 56, 228, }, | ||
188 | { 57, 227, }, | ||
189 | { 58, 226, }, | ||
190 | { 59, 225, }, | ||
191 | { 60, 224, }, | ||
192 | { 62, 223, }, | ||
193 | { 63, 222, }, | ||
194 | { 65, 221, }, | ||
195 | { 66, 220, }, | ||
196 | { 68, 219, }, | ||
197 | { 69, 218, }, | ||
198 | { 70, 217, }, | ||
199 | { 72, 216, }, | ||
200 | { 73, 215, }, | ||
201 | { 75, 214, }, | ||
202 | { 76, 213, }, | ||
203 | { 78, 212, }, | ||
204 | { 80, 211, }, | ||
205 | { 81, 210, }, | ||
206 | { 83, 209, }, | ||
207 | { 84, 208, }, | ||
208 | { 85, 207, }, | ||
209 | { 87, 206, }, | ||
210 | { 89, 205, }, | ||
211 | { 91, 204, }, | ||
212 | { 93, 203, }, | ||
213 | { 95, 202, }, | ||
214 | { 96, 201, }, | ||
215 | { 104, 200, }, | ||
216 | }; | ||
217 | |||
218 | /* QAM256 SNR lookup table */ | ||
219 | static struct qam256_snr_tab { | ||
220 | u16 val; | ||
221 | u16 data; | ||
222 | } qam256_snr_tab[] = { | ||
223 | { 12, 400, }, | ||
224 | { 13, 390, }, | ||
225 | { 15, 380, }, | ||
226 | { 17, 360, }, | ||
227 | { 19, 350, }, | ||
228 | { 22, 348, }, | ||
229 | { 23, 346, }, | ||
230 | { 24, 344, }, | ||
231 | { 25, 342, }, | ||
232 | { 26, 340, }, | ||
233 | { 27, 336, }, | ||
234 | { 28, 334, }, | ||
235 | { 29, 332, }, | ||
236 | { 30, 330, }, | ||
237 | { 31, 328, }, | ||
238 | { 32, 326, }, | ||
239 | { 33, 325, }, | ||
240 | { 34, 322, }, | ||
241 | { 35, 320, }, | ||
242 | { 37, 318, }, | ||
243 | { 39, 316, }, | ||
244 | { 40, 314, }, | ||
245 | { 41, 312, }, | ||
246 | { 42, 310, }, | ||
247 | { 43, 308, }, | ||
248 | { 46, 306, }, | ||
249 | { 47, 304, }, | ||
250 | { 49, 302, }, | ||
251 | { 51, 300, }, | ||
252 | { 53, 298, }, | ||
253 | { 54, 297, }, | ||
254 | { 55, 296, }, | ||
255 | { 56, 295, }, | ||
256 | { 57, 294, }, | ||
257 | { 59, 293, }, | ||
258 | { 60, 292, }, | ||
259 | { 61, 291, }, | ||
260 | { 63, 290, }, | ||
261 | { 64, 289, }, | ||
262 | { 65, 288, }, | ||
263 | { 66, 287, }, | ||
264 | { 68, 286, }, | ||
265 | { 69, 285, }, | ||
266 | { 71, 284, }, | ||
267 | { 72, 283, }, | ||
268 | { 74, 282, }, | ||
269 | { 75, 281, }, | ||
270 | { 76, 280, }, | ||
271 | { 77, 279, }, | ||
272 | { 78, 278, }, | ||
273 | { 81, 277, }, | ||
274 | { 83, 276, }, | ||
275 | { 84, 275, }, | ||
276 | { 86, 274, }, | ||
277 | { 87, 273, }, | ||
278 | { 89, 272, }, | ||
279 | { 90, 271, }, | ||
280 | { 92, 270, }, | ||
281 | { 93, 269, }, | ||
282 | { 95, 268, }, | ||
283 | { 96, 267, }, | ||
284 | { 98, 266, }, | ||
285 | { 100, 265, }, | ||
286 | { 102, 264, }, | ||
287 | { 104, 263, }, | ||
288 | { 105, 262, }, | ||
289 | { 106, 261, }, | ||
290 | { 110, 260, }, | ||
291 | }; | ||
292 | |||
293 | /* 8 bit registers, 16 bit values */ | ||
294 | static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data) | ||
295 | { | ||
296 | int ret; | ||
297 | u8 buf [] = { reg, data >> 8, data & 0xff }; | ||
298 | |||
299 | struct i2c_msg msg = { .addr = state->config->demod_address, | ||
300 | .flags = 0, .buf = buf, .len = 3 }; | ||
301 | |||
302 | ret = i2c_transfer(state->i2c, &msg, 1); | ||
303 | |||
304 | if (ret != 1) | ||
305 | printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, " | ||
306 | "ret == %i)\n", __FUNCTION__, reg, data, ret); | ||
307 | |||
308 | return (ret != 1) ? -1 : 0; | ||
309 | } | ||
310 | |||
311 | static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg) | ||
312 | { | ||
313 | int ret; | ||
314 | u8 b0 [] = { reg }; | ||
315 | u8 b1 [] = { 0, 0 }; | ||
316 | |||
317 | struct i2c_msg msg [] = { | ||
318 | { .addr = state->config->demod_address, .flags = 0, | ||
319 | .buf = b0, .len = 1 }, | ||
320 | { .addr = state->config->demod_address, .flags = I2C_M_RD, | ||
321 | .buf = b1, .len = 2 } }; | ||
322 | |||
323 | ret = i2c_transfer(state->i2c, msg, 2); | ||
324 | |||
325 | if (ret != 2) | ||
326 | printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); | ||
327 | return (b1[0] << 8) | b1[1]; | ||
328 | } | ||
329 | |||
330 | static int s5h1409_softreset(struct dvb_frontend* fe) | ||
331 | { | ||
332 | struct s5h1409_state* state = fe->demodulator_priv; | ||
333 | |||
334 | dprintk("%s()\n", __FUNCTION__); | ||
335 | |||
336 | s5h1409_writereg(state, 0xf5, 0); | ||
337 | s5h1409_writereg(state, 0xf5, 1); | ||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz) | ||
342 | { | ||
343 | struct s5h1409_state* state = fe->demodulator_priv; | ||
344 | int ret = 0; | ||
345 | |||
346 | dprintk("%s(%d KHz)\n", __FUNCTION__, KHz); | ||
347 | |||
348 | if( (KHz == 44000) || (KHz == 5380) ) { | ||
349 | s5h1409_writereg(state, 0x87, 0x01be); | ||
350 | s5h1409_writereg(state, 0x88, 0x0436); | ||
351 | s5h1409_writereg(state, 0x89, 0x054d); | ||
352 | } else { | ||
353 | printk("%s() Invalid arg = %d KHz\n", __FUNCTION__, KHz); | ||
354 | ret = -1; | ||
355 | } | ||
356 | |||
357 | return ret; | ||
358 | } | ||
359 | |||
360 | static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted) | ||
361 | { | ||
362 | struct s5h1409_state* state = fe->demodulator_priv; | ||
363 | |||
364 | dprintk("%s()\n", __FUNCTION__); | ||
365 | |||
366 | if(inverted == 1) | ||
367 | return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */ | ||
368 | else | ||
369 | return s5h1409_writereg(state, 0x1b, 0x0110); /* Normal */ | ||
370 | } | ||
371 | |||
372 | static int s5h1409_enable_modulation(struct dvb_frontend* fe, | ||
373 | fe_modulation_t m) | ||
374 | { | ||
375 | struct s5h1409_state* state = fe->demodulator_priv; | ||
376 | |||
377 | dprintk("%s(0x%08x)\n", __FUNCTION__, m); | ||
378 | |||
379 | switch(m) { | ||
380 | case VSB_8: | ||
381 | dprintk("%s() VSB_8\n", __FUNCTION__); | ||
382 | s5h1409_writereg(state, 0xf4, 0); | ||
383 | break; | ||
384 | case QAM_64: | ||
385 | dprintk("%s() QAM_64\n", __FUNCTION__); | ||
386 | s5h1409_writereg(state, 0xf4, 1); | ||
387 | s5h1409_writereg(state, 0x85, 0x100); | ||
388 | break; | ||
389 | case QAM_256: | ||
390 | dprintk("%s() QAM_256\n", __FUNCTION__); | ||
391 | s5h1409_writereg(state, 0xf4, 1); | ||
392 | s5h1409_writereg(state, 0x85, 0x101); | ||
393 | break; | ||
394 | default: | ||
395 | dprintk("%s() Invalid modulation\n", __FUNCTION__); | ||
396 | return -EINVAL; | ||
397 | } | ||
398 | |||
399 | state->current_modulation = m; | ||
400 | s5h1409_softreset(fe); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) | ||
406 | { | ||
407 | struct s5h1409_state* state = fe->demodulator_priv; | ||
408 | |||
409 | dprintk("%s(%d)\n", __FUNCTION__, enable); | ||
410 | |||
411 | if (enable) | ||
412 | return s5h1409_writereg(state, 0xf3, 1); | ||
413 | else | ||
414 | return s5h1409_writereg(state, 0xf3, 0); | ||
415 | } | ||
416 | |||
417 | static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable) | ||
418 | { | ||
419 | struct s5h1409_state* state = fe->demodulator_priv; | ||
420 | |||
421 | dprintk("%s(%d)\n", __FUNCTION__, enable); | ||
422 | |||
423 | if (enable) | ||
424 | return s5h1409_writereg(state, 0xe3, 0x1100); | ||
425 | else | ||
426 | return s5h1409_writereg(state, 0xe3, 0); | ||
427 | } | ||
428 | |||
429 | static int s5h1409_sleep(struct dvb_frontend* fe, int enable) | ||
430 | { | ||
431 | struct s5h1409_state* state = fe->demodulator_priv; | ||
432 | |||
433 | dprintk("%s(%d)\n", __FUNCTION__, enable); | ||
434 | |||
435 | return s5h1409_writereg(state, 0xf2, enable); | ||
436 | } | ||
437 | |||
438 | static int s5h1409_register_reset(struct dvb_frontend* fe) | ||
439 | { | ||
440 | struct s5h1409_state* state = fe->demodulator_priv; | ||
441 | |||
442 | dprintk("%s()\n", __FUNCTION__); | ||
443 | |||
444 | return s5h1409_writereg(state, 0xfa, 0); | ||
445 | } | ||
446 | |||
447 | /* Talk to the demod, set the FEC, GUARD, QAM settings etc */ | ||
448 | static int s5h1409_set_frontend (struct dvb_frontend* fe, | ||
449 | struct dvb_frontend_parameters *p) | ||
450 | { | ||
451 | struct s5h1409_state* state = fe->demodulator_priv; | ||
452 | |||
453 | dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency); | ||
454 | |||
455 | s5h1409_softreset(fe); | ||
456 | |||
457 | state->current_frequency = p->frequency; | ||
458 | |||
459 | s5h1409_enable_modulation(fe, p->u.vsb.modulation); | ||
460 | |||
461 | if (fe->ops.tuner_ops.set_params) { | ||
462 | if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); | ||
463 | fe->ops.tuner_ops.set_params(fe, p); | ||
464 | if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); | ||
465 | } | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | /* Reset the demod hardware and reset all of the configuration registers | ||
471 | to a default state. */ | ||
472 | static int s5h1409_init (struct dvb_frontend* fe) | ||
473 | { | ||
474 | int i; | ||
475 | |||
476 | struct s5h1409_state* state = fe->demodulator_priv; | ||
477 | dprintk("%s()\n", __FUNCTION__); | ||
478 | |||
479 | s5h1409_sleep(fe, 0); | ||
480 | s5h1409_register_reset(fe); | ||
481 | |||
482 | for (i=0; i < ARRAY_SIZE(init_tab); i++) | ||
483 | s5h1409_writereg(state, init_tab[i].reg, init_tab[i].data); | ||
484 | |||
485 | /* The datasheet says that after initialisation, VSB is default */ | ||
486 | state->current_modulation = VSB_8; | ||
487 | |||
488 | if (state->config->output_mode == S5H1409_SERIAL_OUTPUT) | ||
489 | s5h1409_writereg(state, 0xab, 0x100); /* Serial */ | ||
490 | else | ||
491 | s5h1409_writereg(state, 0xab, 0x0); /* Parallel */ | ||
492 | |||
493 | s5h1409_set_spectralinversion(fe, state->config->inversion); | ||
494 | s5h1409_set_if_freq(fe, state->config->if_freq); | ||
495 | s5h1409_set_gpio(fe, state->config->gpio); | ||
496 | s5h1409_softreset(fe); | ||
497 | |||
498 | /* Note: Leaving the I2C gate open here. */ | ||
499 | s5h1409_i2c_gate_ctrl(fe, 1); | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status) | ||
505 | { | ||
506 | struct s5h1409_state* state = fe->demodulator_priv; | ||
507 | u16 reg; | ||
508 | u32 tuner_status = 0; | ||
509 | |||
510 | *status = 0; | ||
511 | |||
512 | /* Get the demodulator status */ | ||
513 | reg = s5h1409_readreg(state, 0xf1); | ||
514 | if(reg & 0x1000) | ||
515 | *status |= FE_HAS_VITERBI; | ||
516 | if(reg & 0x8000) | ||
517 | *status |= FE_HAS_LOCK | FE_HAS_SYNC; | ||
518 | |||
519 | switch(state->config->status_mode) { | ||
520 | case S5H1409_DEMODLOCKING: | ||
521 | if (*status & FE_HAS_VITERBI) | ||
522 | *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; | ||
523 | break; | ||
524 | case S5H1409_TUNERLOCKING: | ||
525 | /* Get the tuner status */ | ||
526 | if (fe->ops.tuner_ops.get_status) { | ||
527 | if (fe->ops.i2c_gate_ctrl) | ||
528 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
529 | |||
530 | fe->ops.tuner_ops.get_status(fe, &tuner_status); | ||
531 | |||
532 | if (fe->ops.i2c_gate_ctrl) | ||
533 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
534 | } | ||
535 | if (tuner_status) | ||
536 | *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; | ||
537 | break; | ||
538 | } | ||
539 | |||
540 | dprintk("%s() status 0x%08x\n", __FUNCTION__, *status); | ||
541 | |||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v) | ||
546 | { | ||
547 | int i, ret = -EINVAL; | ||
548 | dprintk("%s()\n", __FUNCTION__); | ||
549 | |||
550 | for (i=0; i < ARRAY_SIZE(qam256_snr_tab); i++) { | ||
551 | if (v < qam256_snr_tab[i].val) { | ||
552 | *snr = qam256_snr_tab[i].data; | ||
553 | ret = 0; | ||
554 | break; | ||
555 | } | ||
556 | } | ||
557 | return ret; | ||
558 | } | ||
559 | |||
560 | static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v) | ||
561 | { | ||
562 | int i, ret = -EINVAL; | ||
563 | dprintk("%s()\n", __FUNCTION__); | ||
564 | |||
565 | for (i=0; i < ARRAY_SIZE(qam64_snr_tab); i++) { | ||
566 | if (v < qam64_snr_tab[i].val) { | ||
567 | *snr = qam64_snr_tab[i].data; | ||
568 | ret = 0; | ||
569 | break; | ||
570 | } | ||
571 | } | ||
572 | return ret; | ||
573 | } | ||
574 | |||
575 | static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v) | ||
576 | { | ||
577 | int i, ret = -EINVAL; | ||
578 | dprintk("%s()\n", __FUNCTION__); | ||
579 | |||
580 | for (i=0; i < ARRAY_SIZE(vsb_snr_tab); i++) { | ||
581 | if (v > vsb_snr_tab[i].val) { | ||
582 | *snr = vsb_snr_tab[i].data; | ||
583 | ret = 0; | ||
584 | break; | ||
585 | } | ||
586 | } | ||
587 | dprintk("%s() snr=%d\n", __FUNCTION__, *snr); | ||
588 | return ret; | ||
589 | } | ||
590 | |||
591 | static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr) | ||
592 | { | ||
593 | struct s5h1409_state* state = fe->demodulator_priv; | ||
594 | u16 reg; | ||
595 | dprintk("%s()\n", __FUNCTION__); | ||
596 | |||
597 | reg = s5h1409_readreg(state, 0xf1) & 0x1ff; | ||
598 | |||
599 | switch(state->current_modulation) { | ||
600 | case QAM_64: | ||
601 | return s5h1409_qam64_lookup_snr(fe, snr, reg); | ||
602 | case QAM_256: | ||
603 | return s5h1409_qam256_lookup_snr(fe, snr, reg); | ||
604 | case VSB_8: | ||
605 | return s5h1409_vsb_lookup_snr(fe, snr, reg); | ||
606 | default: | ||
607 | break; | ||
608 | } | ||
609 | |||
610 | return -EINVAL; | ||
611 | } | ||
612 | |||
613 | static int s5h1409_read_signal_strength(struct dvb_frontend* fe, | ||
614 | u16* signal_strength) | ||
615 | { | ||
616 | return s5h1409_read_snr(fe, signal_strength); | ||
617 | } | ||
618 | |||
619 | static int s5h1409_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | ||
620 | { | ||
621 | struct s5h1409_state* state = fe->demodulator_priv; | ||
622 | |||
623 | *ucblocks = s5h1409_readreg(state, 0xb5); | ||
624 | |||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | static int s5h1409_read_ber(struct dvb_frontend* fe, u32* ber) | ||
629 | { | ||
630 | return s5h1409_read_ucblocks(fe, ber); | ||
631 | } | ||
632 | |||
633 | static int s5h1409_get_frontend(struct dvb_frontend* fe, | ||
634 | struct dvb_frontend_parameters *p) | ||
635 | { | ||
636 | struct s5h1409_state* state = fe->demodulator_priv; | ||
637 | |||
638 | p->frequency = state->current_frequency; | ||
639 | p->u.vsb.modulation = state->current_modulation; | ||
640 | |||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | static int s5h1409_get_tune_settings(struct dvb_frontend* fe, | ||
645 | struct dvb_frontend_tune_settings *tune) | ||
646 | { | ||
647 | tune->min_delay_ms = 1000; | ||
648 | return 0; | ||
649 | } | ||
650 | |||
651 | static void s5h1409_release(struct dvb_frontend* fe) | ||
652 | { | ||
653 | struct s5h1409_state* state = fe->demodulator_priv; | ||
654 | kfree(state); | ||
655 | } | ||
656 | |||
657 | static struct dvb_frontend_ops s5h1409_ops; | ||
658 | |||
659 | struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config, | ||
660 | struct i2c_adapter* i2c) | ||
661 | { | ||
662 | struct s5h1409_state* state = NULL; | ||
663 | |||
664 | /* allocate memory for the internal state */ | ||
665 | state = kmalloc(sizeof(struct s5h1409_state), GFP_KERNEL); | ||
666 | if (state == NULL) | ||
667 | goto error; | ||
668 | |||
669 | /* setup the state */ | ||
670 | state->config = config; | ||
671 | state->i2c = i2c; | ||
672 | state->current_modulation = 0; | ||
673 | |||
674 | /* check if the demod exists */ | ||
675 | if (s5h1409_readreg(state, 0x04) != 0x0066) | ||
676 | goto error; | ||
677 | |||
678 | /* create dvb_frontend */ | ||
679 | memcpy(&state->frontend.ops, &s5h1409_ops, | ||
680 | sizeof(struct dvb_frontend_ops)); | ||
681 | state->frontend.demodulator_priv = state; | ||
682 | |||
683 | /* Note: Leaving the I2C gate open here. */ | ||
684 | s5h1409_writereg(state, 0xf3, 1); | ||
685 | |||
686 | return &state->frontend; | ||
687 | |||
688 | error: | ||
689 | kfree(state); | ||
690 | return NULL; | ||
691 | } | ||
692 | |||
693 | static struct dvb_frontend_ops s5h1409_ops = { | ||
694 | |||
695 | .info = { | ||
696 | .name = "Samsung S5H1409 QAM/8VSB Frontend", | ||
697 | .type = FE_ATSC, | ||
698 | .frequency_min = 54000000, | ||
699 | .frequency_max = 858000000, | ||
700 | .frequency_stepsize = 62500, | ||
701 | .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB | ||
702 | }, | ||
703 | |||
704 | .init = s5h1409_init, | ||
705 | .i2c_gate_ctrl = s5h1409_i2c_gate_ctrl, | ||
706 | .set_frontend = s5h1409_set_frontend, | ||
707 | .get_frontend = s5h1409_get_frontend, | ||
708 | .get_tune_settings = s5h1409_get_tune_settings, | ||
709 | .read_status = s5h1409_read_status, | ||
710 | .read_ber = s5h1409_read_ber, | ||
711 | .read_signal_strength = s5h1409_read_signal_strength, | ||
712 | .read_snr = s5h1409_read_snr, | ||
713 | .read_ucblocks = s5h1409_read_ucblocks, | ||
714 | .release = s5h1409_release, | ||
715 | }; | ||
716 | |||
717 | module_param(debug, int, 0644); | ||
718 | MODULE_PARM_DESC(debug, "Enable verbose debug messages"); | ||
719 | |||
720 | MODULE_DESCRIPTION("Samsung S5H1409 QAM-B/ATSC Demodulator driver"); | ||
721 | MODULE_AUTHOR("Steven Toth"); | ||
722 | MODULE_LICENSE("GPL"); | ||
723 | |||
724 | EXPORT_SYMBOL(s5h1409_attach); | ||
725 | |||
726 | /* | ||
727 | * Local variables: | ||
728 | * c-basic-offset: 8 | ||
729 | */ | ||
diff --git a/drivers/media/dvb/frontends/s5h1409.h b/drivers/media/dvb/frontends/s5h1409.h new file mode 100644 index 000000000000..20f9af1af445 --- /dev/null +++ b/drivers/media/dvb/frontends/s5h1409.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | Samsung S5H1409 VSB/QAM demodulator driver | ||
3 | |||
4 | Copyright (C) 2006 Steven Toth <stoth@hauppauge.com> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | |||
20 | */ | ||
21 | |||
22 | #ifndef __S5H1409_H__ | ||
23 | #define __S5H1409_H__ | ||
24 | |||
25 | #include <linux/dvb/frontend.h> | ||
26 | |||
27 | struct s5h1409_config | ||
28 | { | ||
29 | /* the demodulator's i2c address */ | ||
30 | u8 demod_address; | ||
31 | |||
32 | /* serial/parallel output */ | ||
33 | #define S5H1409_PARALLEL_OUTPUT 0 | ||
34 | #define S5H1409_SERIAL_OUTPUT 1 | ||
35 | u8 output_mode; | ||
36 | |||
37 | /* GPIO Setting */ | ||
38 | #define S5H1409_GPIO_OFF 0 | ||
39 | #define S5H1409_GPIO_ON 1 | ||
40 | u8 gpio; | ||
41 | |||
42 | /* IF Freq in KHz */ | ||
43 | u16 if_freq; | ||
44 | |||
45 | /* Spectral Inversion */ | ||
46 | #define S5H1409_INVERSION_OFF 0 | ||
47 | #define S5H1409_INVERSION_ON 1 | ||
48 | u8 inversion; | ||
49 | |||
50 | /* Return lock status based on tuner lock, or demod lock */ | ||
51 | #define S5H1409_TUNERLOCKING 0 | ||
52 | #define S5H1409_DEMODLOCKING 1 | ||
53 | u8 status_mode; | ||
54 | }; | ||
55 | |||
56 | #if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) && defined(MODULE)) | ||
57 | extern struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config, | ||
58 | struct i2c_adapter* i2c); | ||
59 | #else | ||
60 | static inline struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config, | ||
61 | struct i2c_adapter* i2c) | ||
62 | { | ||
63 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | ||
64 | return NULL; | ||
65 | } | ||
66 | #endif /* CONFIG_DVB_S5H1409 */ | ||
67 | |||
68 | #endif /* __S5H1409_H__ */ | ||
69 | |||
70 | /* | ||
71 | * Local variables: | ||
72 | * c-basic-offset: 8 | ||
73 | */ | ||
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c index d98fd5c2e13e..da876f7bfe32 100644 --- a/drivers/media/dvb/frontends/sp8870.c +++ b/drivers/media/dvb/frontends/sp8870.c | |||
@@ -29,7 +29,6 @@ | |||
29 | 29 | ||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/moduleparam.h> | ||
33 | #include <linux/device.h> | 32 | #include <linux/device.h> |
34 | #include <linux/firmware.h> | 33 | #include <linux/firmware.h> |
35 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c index 5c2f8f4e0ae5..1aa2539f5099 100644 --- a/drivers/media/dvb/frontends/sp887x.c +++ b/drivers/media/dvb/frontends/sp887x.c | |||
@@ -12,7 +12,6 @@ | |||
12 | 12 | ||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/device.h> | 15 | #include <linux/device.h> |
17 | #include <linux/firmware.h> | 16 | #include <linux/firmware.h> |
18 | #include <linux/string.h> | 17 | #include <linux/string.h> |
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c index 9a343972ff50..17e5cb561cd8 100644 --- a/drivers/media/dvb/frontends/stv0297.c +++ b/drivers/media/dvb/frontends/stv0297.c | |||
@@ -680,8 +680,8 @@ static struct dvb_frontend_ops stv0297_ops = { | |||
680 | .info = { | 680 | .info = { |
681 | .name = "ST STV0297 DVB-C", | 681 | .name = "ST STV0297 DVB-C", |
682 | .type = FE_QAM, | 682 | .type = FE_QAM, |
683 | .frequency_min = 64000000, | 683 | .frequency_min = 47000000, |
684 | .frequency_max = 1300000000, | 684 | .frequency_max = 862000000, |
685 | .frequency_stepsize = 62500, | 685 | .frequency_stepsize = 62500, |
686 | .symbol_rate_min = 870000, | 686 | .symbol_rate_min = 870000, |
687 | .symbol_rate_max = 11700000, | 687 | .symbol_rate_max = 11700000, |
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 6c607302c1b6..035dd7ba6519 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <linux/init.h> | 45 | #include <linux/init.h> |
46 | #include <linux/kernel.h> | 46 | #include <linux/kernel.h> |
47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
48 | #include <linux/moduleparam.h> | ||
49 | #include <linux/string.h> | 48 | #include <linux/string.h> |
50 | #include <linux/slab.h> | 49 | #include <linux/slab.h> |
51 | #include <linux/jiffies.h> | 50 | #include <linux/jiffies.h> |
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index e725f612a6b7..4cd9e82c4669 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c | |||
@@ -439,8 +439,8 @@ static struct dvb_frontend_ops tda10021_ops = { | |||
439 | .name = "Philips TDA10021 DVB-C", | 439 | .name = "Philips TDA10021 DVB-C", |
440 | .type = FE_QAM, | 440 | .type = FE_QAM, |
441 | .frequency_stepsize = 62500, | 441 | .frequency_stepsize = 62500, |
442 | .frequency_min = 51000000, | 442 | .frequency_min = 47000000, |
443 | .frequency_max = 858000000, | 443 | .frequency_max = 862000000, |
444 | .symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */ | 444 | .symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */ |
445 | .symbol_rate_max = (XIN/2)/4, /* SACLK/4 */ | 445 | .symbol_rate_max = (XIN/2)/4, /* SACLK/4 */ |
446 | #if 0 | 446 | #if 0 |
diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb/frontends/tda10023.c index 4bb06f97938b..364bc01971a0 100644 --- a/drivers/media/dvb/frontends/tda10023.c +++ b/drivers/media/dvb/frontends/tda10023.c | |||
@@ -215,12 +215,6 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr) | |||
215 | s16 SFIL=0; | 215 | s16 SFIL=0; |
216 | u16 NDEC = 0; | 216 | u16 NDEC = 0; |
217 | 217 | ||
218 | if (sr > (SYSCLK/(2*4))) | ||
219 | sr=SYSCLK/(2*4); | ||
220 | |||
221 | if (sr<870000) | ||
222 | sr=870000; | ||
223 | |||
224 | if (sr < (u32)(SYSCLK/98.40)) { | 218 | if (sr < (u32)(SYSCLK/98.40)) { |
225 | NDEC=3; | 219 | NDEC=3; |
226 | SFIL=1; | 220 | SFIL=1; |
@@ -506,8 +500,8 @@ static struct dvb_frontend_ops tda10023_ops = { | |||
506 | .name = "Philips TDA10023 DVB-C", | 500 | .name = "Philips TDA10023 DVB-C", |
507 | .type = FE_QAM, | 501 | .type = FE_QAM, |
508 | .frequency_stepsize = 62500, | 502 | .frequency_stepsize = 62500, |
509 | .frequency_min = 51000000, | 503 | .frequency_min = 47000000, |
510 | .frequency_max = 858000000, | 504 | .frequency_max = 862000000, |
511 | .symbol_rate_min = (SYSCLK/2)/64, /* SACLK/64 == (SYSCLK/2)/64 */ | 505 | .symbol_rate_min = (SYSCLK/2)/64, /* SACLK/64 == (SYSCLK/2)/64 */ |
512 | .symbol_rate_max = (SYSCLK/2)/4, /* SACLK/4 */ | 506 | .symbol_rate_max = (SYSCLK/2)/4, /* SACLK/4 */ |
513 | .caps = 0x400 | //FE_CAN_QAM_4 | 507 | .caps = 0x400 | //FE_CAN_QAM_4 |
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index 33a84372c9e6..8415a8a5247a 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c | |||
@@ -31,7 +31,6 @@ | |||
31 | 31 | ||
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/moduleparam.h> | ||
35 | #include <linux/device.h> | 34 | #include <linux/device.h> |
36 | #include <linux/jiffies.h> | 35 | #include <linux/jiffies.h> |
37 | #include <linux/string.h> | 36 | #include <linux/string.h> |
diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c index 0f2d4b415560..9a8ddc537f8f 100644 --- a/drivers/media/dvb/frontends/tda10086.c +++ b/drivers/media/dvb/frontends/tda10086.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/device.h> | 25 | #include <linux/device.h> |
27 | #include <linux/jiffies.h> | 26 | #include <linux/jiffies.h> |
28 | #include <linux/string.h> | 27 | #include <linux/string.h> |
diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c index 67415c9db6f7..011b74f798a0 100644 --- a/drivers/media/dvb/frontends/tda8083.c +++ b/drivers/media/dvb/frontends/tda8083.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/moduleparam.h> | ||
31 | #include <linux/string.h> | 30 | #include <linux/string.h> |
32 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
33 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
@@ -443,12 +442,12 @@ static struct dvb_frontend_ops tda8083_ops = { | |||
443 | .info = { | 442 | .info = { |
444 | .name = "Philips TDA8083 DVB-S", | 443 | .name = "Philips TDA8083 DVB-S", |
445 | .type = FE_QPSK, | 444 | .type = FE_QPSK, |
446 | .frequency_min = 950000, /* FIXME: guessed! */ | 445 | .frequency_min = 920000, /* TDA8060 */ |
447 | .frequency_max = 1400000, /* FIXME: guessed! */ | 446 | .frequency_max = 2200000, /* TDA8060 */ |
448 | .frequency_stepsize = 125, /* kHz for QPSK frontends */ | 447 | .frequency_stepsize = 125, /* kHz for QPSK frontends */ |
449 | /* .frequency_tolerance = ???,*/ | 448 | /* .frequency_tolerance = ???,*/ |
450 | .symbol_rate_min = 1000000, /* FIXME: guessed! */ | 449 | .symbol_rate_min = 12000000, |
451 | .symbol_rate_max = 45000000, /* FIXME: guessed! */ | 450 | .symbol_rate_max = 30000000, |
452 | /* .symbol_rate_tolerance = ???,*/ | 451 | /* .symbol_rate_tolerance = ???,*/ |
453 | .caps = FE_CAN_INVERSION_AUTO | | 452 | .caps = FE_CAN_INVERSION_AUTO | |
454 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | 453 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | |
diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c index 9b57576bfeb4..066b73b75698 100644 --- a/drivers/media/dvb/frontends/ves1820.c +++ b/drivers/media/dvb/frontends/ves1820.c | |||
@@ -410,8 +410,8 @@ static struct dvb_frontend_ops ves1820_ops = { | |||
410 | .name = "VLSI VES1820 DVB-C", | 410 | .name = "VLSI VES1820 DVB-C", |
411 | .type = FE_QAM, | 411 | .type = FE_QAM, |
412 | .frequency_stepsize = 62500, | 412 | .frequency_stepsize = 62500, |
413 | .frequency_min = 51000000, | 413 | .frequency_min = 47000000, |
414 | .frequency_max = 858000000, | 414 | .frequency_max = 862000000, |
415 | .caps = FE_CAN_QAM_16 | | 415 | .caps = FE_CAN_QAM_16 | |
416 | FE_CAN_QAM_32 | | 416 | FE_CAN_QAM_32 | |
417 | FE_CAN_QAM_64 | | 417 | FE_CAN_QAM_64 | |
diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index 245f9b7dddfa..a97a7fd2c891 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c | |||
@@ -21,7 +21,6 @@ | |||
21 | 21 | ||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/init.h> | 24 | #include <linux/init.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/string.h> | 26 | #include <linux/string.h> |
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 8178832d14a8..8b8144f77a73 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/smp_lock.h> | 40 | #include <linux/smp_lock.h> |
41 | 41 | ||
42 | #include <linux/kernel.h> | 42 | #include <linux/kernel.h> |
43 | #include <linux/moduleparam.h> | ||
44 | #include <linux/sched.h> | 43 | #include <linux/sched.h> |
45 | #include <linux/types.h> | 44 | #include <linux/types.h> |
46 | #include <linux/fcntl.h> | 45 | #include <linux/fcntl.h> |
@@ -1543,7 +1542,7 @@ static int get_firmware(struct av7110* av7110) | |||
1543 | } | 1542 | } |
1544 | 1543 | ||
1545 | /* check if the firmware is available */ | 1544 | /* check if the firmware is available */ |
1546 | av7110->bin_fw = (unsigned char *) vmalloc(fw->size); | 1545 | av7110->bin_fw = vmalloc(fw->size); |
1547 | if (NULL == av7110->bin_fw) { | 1546 | if (NULL == av7110->bin_fw) { |
1548 | dprintk(1, "out of memory\n"); | 1547 | dprintk(1, "out of memory\n"); |
1549 | release_firmware(fw); | 1548 | release_firmware(fw); |
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index 515e8232e020..a468aa2e4854 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c | |||
@@ -978,24 +978,24 @@ static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 ble | |||
978 | 978 | ||
979 | static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last) | 979 | static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last) |
980 | { | 980 | { |
981 | int i; | 981 | int i; |
982 | int length = last - first + 1; | 982 | int length = last - first + 1; |
983 | 983 | ||
984 | if (length * 4 > DATA_BUFF3_SIZE) | 984 | if (length * 4 > DATA_BUFF3_SIZE) |
985 | return -EINVAL; | 985 | return -EINVAL; |
986 | 986 | ||
987 | for (i = 0; i < length; i++) { | 987 | for (i = 0; i < length; i++) { |
988 | u32 color, blend, yuv; | 988 | u32 color, blend, yuv; |
989 | 989 | ||
990 | if (get_user(color, colors + i)) | 990 | if (get_user(color, colors + i)) |
991 | return -EFAULT; | 991 | return -EFAULT; |
992 | blend = (color & 0xF0000000) >> 4; | 992 | blend = (color & 0xF0000000) >> 4; |
993 | yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF, | 993 | yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF, |
994 | (color >> 16) & 0xFF) | blend : 0; | 994 | (color >> 16) & 0xFF) | blend : 0; |
995 | yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16); | 995 | yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16); |
996 | wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4); | 996 | wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4); |
997 | } | 997 | } |
998 | return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4, | 998 | return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4, |
999 | av7110->osdwin, | 999 | av7110->osdwin, |
1000 | bpp2pal[av7110->osdbpp[av7110->osdwin]], | 1000 | bpp2pal[av7110->osdbpp[av7110->osdwin]], |
1001 | first, last); | 1001 | first, last); |
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index 6322800ee12b..5d19c402dad1 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | ||
29 | #include <linux/proc_fs.h> | 28 | #include <linux/proc_fs.h> |
30 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
31 | #include <asm/bitops.h> | 30 | #include <asm/bitops.h> |
@@ -280,7 +279,7 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer, | |||
280 | if (count < size) | 279 | if (count < size) |
281 | return -EINVAL; | 280 | return -EINVAL; |
282 | 281 | ||
283 | page = (char *) vmalloc(size); | 282 | page = vmalloc(size); |
284 | if (!page) | 283 | if (!page) |
285 | return -ENOMEM; | 284 | return -ENOMEM; |
286 | 285 | ||
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c index 87afaebc0703..76cca003252f 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/dvb/ttpci/av7110_v4l.c | |||
@@ -129,23 +129,25 @@ static struct v4l2_input inputs[4] = { | |||
129 | 129 | ||
130 | static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data) | 130 | static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data) |
131 | { | 131 | { |
132 | struct av7110 *av7110 = dev->ext_priv; | ||
132 | u8 buf[] = { 0x00, reg, data }; | 133 | u8 buf[] = { 0x00, reg, data }; |
133 | struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 }; | 134 | struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 }; |
134 | 135 | ||
135 | dprintk(4, "dev: %p\n", dev); | 136 | dprintk(4, "dev: %p\n", dev); |
136 | 137 | ||
137 | if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) | 138 | if (1 != i2c_transfer(&av7110->i2c_adap, &msg, 1)) |
138 | return -1; | 139 | return -1; |
139 | return 0; | 140 | return 0; |
140 | } | 141 | } |
141 | 142 | ||
142 | static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4]) | 143 | static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4]) |
143 | { | 144 | { |
145 | struct av7110 *av7110 = dev->ext_priv; | ||
144 | struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 }; | 146 | struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 }; |
145 | 147 | ||
146 | dprintk(4, "dev: %p\n", dev); | 148 | dprintk(4, "dev: %p\n", dev); |
147 | 149 | ||
148 | if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) | 150 | if (1 != i2c_transfer(&av7110->i2c_adap, &msg, 1)) |
149 | return -1; | 151 | return -1; |
150 | return 0; | 152 | return 0; |
151 | } | 153 | } |
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 0aee7a13a070..3439c9864f67 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c | |||
@@ -1232,7 +1232,7 @@ static struct saa7146_ext_vv vv_data = { | |||
1232 | .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113 | 1232 | .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113 |
1233 | .flags = 0, | 1233 | .flags = 0, |
1234 | .stds = &standard[0], | 1234 | .stds = &standard[0], |
1235 | .num_stds = sizeof(standard) / sizeof(struct saa7146_standard), | 1235 | .num_stds = ARRAY_SIZE(standard), |
1236 | .ioctls = &ioctls[0], | 1236 | .ioctls = &ioctls[0], |
1237 | .ioctl = av_ioctl, | 1237 | .ioctl = av_ioctl, |
1238 | }; | 1238 | }; |
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 873c3ba296f2..509349211d4f 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c | |||
@@ -214,7 +214,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
214 | case 0x100f: | 214 | case 0x100f: |
215 | case 0x1011: | 215 | case 0x1011: |
216 | case 0x1012: | 216 | case 0x1012: |
217 | case 0x1017: | ||
218 | /* The hauppauge keymap is a superset of these remotes */ | 217 | /* The hauppauge keymap is a superset of these remotes */ |
219 | ir_input_init(input_dev, &budget_ci->ir.state, | 218 | ir_input_init(input_dev, &budget_ci->ir.state, |
220 | IR_TYPE_RC5, ir_codes_hauppauge_new); | 219 | IR_TYPE_RC5, ir_codes_hauppauge_new); |
@@ -225,6 +224,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
225 | budget_ci->ir.rc5_device = rc5_device; | 224 | budget_ci->ir.rc5_device = rc5_device; |
226 | break; | 225 | break; |
227 | case 0x1010: | 226 | case 0x1010: |
227 | case 0x1017: | ||
228 | /* for the Technotrend 1500 bundled remote */ | 228 | /* for the Technotrend 1500 bundled remote */ |
229 | ir_input_init(input_dev, &budget_ci->ir.state, | 229 | ir_input_init(input_dev, &budget_ci->ir.state, |
230 | IR_TYPE_RC5, ir_codes_tt_1500); | 230 | IR_TYPE_RC5, ir_codes_tt_1500); |
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index b611f2b1f8bc..0252081f013c 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c | |||
@@ -34,7 +34,6 @@ | |||
34 | * the project's page is at http://www.linuxtv.org/dvb/ | 34 | * the project's page is at http://www.linuxtv.org/dvb/ |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include <linux/moduleparam.h> | ||
38 | 37 | ||
39 | #include "budget.h" | 38 | #include "budget.h" |
40 | #include "ttpci-eeprom.h" | 39 | #include "ttpci-eeprom.h" |
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index b60cdc93d6db..288e79f2cb0f 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/wait.h> | 14 | #include <linux/wait.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/usb.h> | 16 | #include <linux/usb.h> |
18 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
19 | #include <linux/time.h> | 18 | #include <linux/time.h> |
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 78c98b089975..5e691fd79904 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include <linux/list.h> | 23 | #include <linux/list.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
27 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
28 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index f8bf9fe37d36..11e962f1a97f 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig | |||
@@ -111,11 +111,16 @@ config RADIO_AZTECH_PORT | |||
111 | jumper sets the card to 0x358. | 111 | jumper sets the card to 0x358. |
112 | 112 | ||
113 | config RADIO_GEMTEK | 113 | config RADIO_GEMTEK |
114 | tristate "GemTek Radio Card support" | 114 | tristate "GemTek Radio card (or compatible) support" |
115 | depends on ISA && VIDEO_V4L2 | 115 | depends on ISA && VIDEO_V4L2 |
116 | ---help--- | 116 | ---help--- |
117 | Choose Y here if you have this FM radio card, and then fill in the | 117 | Choose Y here if you have this FM radio card, and then fill in the |
118 | port address below. | 118 | I/O port address and settings below. The following cards either have |
119 | GemTek Radio tuner or are rebranded GemTek Radio cards: | ||
120 | |||
121 | - Sound Vision 16 Gold with FM Radio | ||
122 | - Typhoon Radio card (some models) | ||
123 | - Hama Radio card | ||
119 | 124 | ||
120 | In order to control your radio card, you will need to use programs | 125 | In order to control your radio card, you will need to use programs |
121 | that are compatible with the Video For Linux API. Information on | 126 | that are compatible with the Video For Linux API. Information on |
@@ -126,14 +131,25 @@ config RADIO_GEMTEK | |||
126 | module will be called radio-gemtek. | 131 | module will be called radio-gemtek. |
127 | 132 | ||
128 | config RADIO_GEMTEK_PORT | 133 | config RADIO_GEMTEK_PORT |
129 | hex "GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)" | 134 | hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0c24c or 0x28c)" |
130 | depends on RADIO_GEMTEK=y | 135 | depends on RADIO_GEMTEK=y |
131 | default "34c" | 136 | default "34c" |
132 | help | 137 | help |
133 | Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is | 138 | Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is |
134 | 0x34c, if you haven't changed the jumper setting on the card. On | 139 | 0x34c, if you haven't changed the jumper setting on the card. On |
135 | Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O | 140 | Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O |
136 | port is 0x28c. | 141 | port is 0x20c, 0x248 or 0x28c. |
142 | If automatic I/O port probing is enabled this port will be used only | ||
143 | in case of automatic probing failure, ie. as a fallback. | ||
144 | |||
145 | config RADIO_GEMTEK_PROBE | ||
146 | bool "Automatic I/O port probing" | ||
147 | depends on RADIO_GEMTEK=y | ||
148 | default y | ||
149 | help | ||
150 | Say Y here to enable automatic probing for GemTek Radio card. The | ||
151 | following ports will be probed: 0x20c, 0x30c, 0x24c, 0x34c, 0x248 and | ||
152 | 0x28c. | ||
137 | 153 | ||
138 | config RADIO_GEMTEK_PCI | 154 | config RADIO_GEMTEK_PCI |
139 | tristate "GemTek PCI Radio Card support" | 155 | tristate "GemTek PCI Radio Card support" |
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index eab8c80a2e47..0c963db03614 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c | |||
@@ -26,143 +26,383 @@ | |||
26 | #include <media/v4l2-common.h> | 26 | #include <media/v4l2-common.h> |
27 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
28 | 28 | ||
29 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ | 29 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ |
30 | #define RADIO_VERSION KERNEL_VERSION(0,0,2) | 30 | #define RADIO_VERSION KERNEL_VERSION(0,0,3) |
31 | #define RADIO_BANNER "GemTek Radio card driver: v0.0.3" | ||
31 | 32 | ||
32 | static struct v4l2_queryctrl radio_qctrl[] = { | 33 | /* |
33 | { | 34 | * Module info. |
34 | .id = V4L2_CID_AUDIO_MUTE, | 35 | */ |
35 | .name = "Mute", | 36 | |
36 | .minimum = 0, | 37 | MODULE_AUTHOR("Jonas Munsin, Pekka Seppänen <pexu@kapsi.fi>"); |
37 | .maximum = 1, | 38 | MODULE_DESCRIPTION("A driver for the GemTek Radio card."); |
38 | .default_value = 1, | 39 | MODULE_LICENSE("GPL"); |
39 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 40 | |
40 | },{ | 41 | /* |
41 | .id = V4L2_CID_AUDIO_VOLUME, | 42 | * Module params. |
42 | .name = "Volume", | 43 | */ |
43 | .minimum = 0, | ||
44 | .maximum = 65535, | ||
45 | .step = 65535, | ||
46 | .default_value = 0xff, | ||
47 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
48 | } | ||
49 | }; | ||
50 | 44 | ||
51 | #ifndef CONFIG_RADIO_GEMTEK_PORT | 45 | #ifndef CONFIG_RADIO_GEMTEK_PORT |
52 | #define CONFIG_RADIO_GEMTEK_PORT -1 | 46 | #define CONFIG_RADIO_GEMTEK_PORT -1 |
53 | #endif | 47 | #endif |
48 | #ifndef CONFIG_RADIO_GEMTEK_PROBE | ||
49 | #define CONFIG_RADIO_GEMTEK_PROBE 1 | ||
50 | #endif | ||
54 | 51 | ||
55 | static int io = CONFIG_RADIO_GEMTEK_PORT; | 52 | static int io = CONFIG_RADIO_GEMTEK_PORT; |
56 | static int radio_nr = -1; | 53 | static int probe = CONFIG_RADIO_GEMTEK_PROBE; |
57 | static spinlock_t lock; | 54 | static int hardmute; |
55 | static int shutdown = 1; | ||
56 | static int keepmuted = 1; | ||
57 | static int initmute = 1; | ||
58 | static int radio_nr = -1; | ||
58 | 59 | ||
59 | struct gemtek_device | 60 | module_param(io, int, 0444); |
60 | { | 61 | MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic" |
61 | int port; | 62 | "probing is disabled or fails. The most common I/O ports are: 0x20c " |
62 | unsigned long curfreq; | 63 | "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to " |
64 | " work for the combined sound/radiocard)."); | ||
65 | |||
66 | module_param(probe, bool, 0444); | ||
67 | MODULE_PARM_DESC(probe, "Enable automatic device probing. Note: only the most " | ||
68 | "common I/O ports used by the card are probed."); | ||
69 | |||
70 | module_param(hardmute, bool, 0644); | ||
71 | MODULE_PARM_DESC(hardmute, "Enable `hard muting' by shutting down PLL, may " | ||
72 | "reduce static noise."); | ||
73 | |||
74 | module_param(shutdown, bool, 0644); | ||
75 | MODULE_PARM_DESC(shutdown, "Enable shutting down PLL and muting line when " | ||
76 | "module is unloaded."); | ||
77 | |||
78 | module_param(keepmuted, bool, 0644); | ||
79 | MODULE_PARM_DESC(keepmuted, "Keep card muted even when frequency is changed."); | ||
80 | |||
81 | module_param(initmute, bool, 0444); | ||
82 | MODULE_PARM_DESC(initmute, "Mute card when module is loaded."); | ||
83 | |||
84 | module_param(radio_nr, int, 0444); | ||
85 | |||
86 | /* | ||
87 | * Functions for controlling the card. | ||
88 | */ | ||
89 | #define GEMTEK_LOWFREQ (87*16000) | ||
90 | #define GEMTEK_HIGHFREQ (108*16000) | ||
91 | |||
92 | /* | ||
93 | * Frequency calculation constants. Intermediate frequency 10.52 MHz (nominal | ||
94 | * value 10.7 MHz), reference divisor 6.39 kHz (nominal 6.25 kHz). | ||
95 | */ | ||
96 | #define FSCALE 8 | ||
97 | #define IF_OFFSET ((unsigned int)(10.52 * 16000 * (1<<FSCALE))) | ||
98 | #define REF_FREQ ((unsigned int)(6.39 * 16 * (1<<FSCALE))) | ||
99 | |||
100 | #define GEMTEK_CK 0x01 /* Clock signal */ | ||
101 | #define GEMTEK_DA 0x02 /* Serial data */ | ||
102 | #define GEMTEK_CE 0x04 /* Chip enable */ | ||
103 | #define GEMTEK_NS 0x08 /* No signal */ | ||
104 | #define GEMTEK_MT 0x10 /* Line mute */ | ||
105 | #define GEMTEK_STDF_3_125_KHZ 0x01 /* Standard frequency 3.125 kHz */ | ||
106 | #define GEMTEK_PLL_OFF 0x07 /* PLL off */ | ||
107 | |||
108 | #define BU2614_BUS_SIZE 32 /* BU2614 / BU2614FS bus size */ | ||
109 | |||
110 | #define SHORT_DELAY 5 /* usec */ | ||
111 | #define LONG_DELAY 75 /* usec */ | ||
112 | |||
113 | struct gemtek_device { | ||
114 | unsigned long lastfreq; | ||
63 | int muted; | 115 | int muted; |
116 | u32 bu2614data; | ||
64 | }; | 117 | }; |
65 | 118 | ||
119 | #define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */ | ||
120 | #define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */ | ||
121 | #define BU2614_VOID_BITS 4 /* unused */ | ||
122 | #define BU2614_FMES_BITS 1 /* CT, Frequency measurement beginning data */ | ||
123 | #define BU2614_STDF_BITS 3 /* R0..R2, Standard frequency data */ | ||
124 | #define BU2614_SWIN_BITS 1 /* S, Switch between FMIN / AMIN */ | ||
125 | #define BU2614_SWAL_BITS 1 /* PS, Swallow counter division (AMIN only)*/ | ||
126 | #define BU2614_VOID2_BITS 1 /* unused */ | ||
127 | #define BU2614_FMUN_BITS 1 /* GT, Frequency measurement time & unlock */ | ||
128 | #define BU2614_TEST_BITS 1 /* TS, Test data is input */ | ||
129 | |||
130 | #define BU2614_FREQ_SHIFT 0 | ||
131 | #define BU2614_PORT_SHIFT (BU2614_FREQ_BITS + BU2614_FREQ_SHIFT) | ||
132 | #define BU2614_VOID_SHIFT (BU2614_PORT_BITS + BU2614_PORT_SHIFT) | ||
133 | #define BU2614_FMES_SHIFT (BU2614_VOID_BITS + BU2614_VOID_SHIFT) | ||
134 | #define BU2614_STDF_SHIFT (BU2614_FMES_BITS + BU2614_FMES_SHIFT) | ||
135 | #define BU2614_SWIN_SHIFT (BU2614_STDF_BITS + BU2614_STDF_SHIFT) | ||
136 | #define BU2614_SWAL_SHIFT (BU2614_SWIN_BITS + BU2614_SWIN_SHIFT) | ||
137 | #define BU2614_VOID2_SHIFT (BU2614_SWAL_BITS + BU2614_SWAL_SHIFT) | ||
138 | #define BU2614_FMUN_SHIFT (BU2614_VOID2_BITS + BU2614_VOID2_SHIFT) | ||
139 | #define BU2614_TEST_SHIFT (BU2614_FMUN_BITS + BU2614_FMUN_SHIFT) | ||
140 | |||
141 | #define MKMASK(field) (((1<<BU2614_##field##_BITS) - 1) << \ | ||
142 | BU2614_##field##_SHIFT) | ||
143 | #define BU2614_PORT_MASK MKMASK(PORT) | ||
144 | #define BU2614_FREQ_MASK MKMASK(FREQ) | ||
145 | #define BU2614_VOID_MASK MKMASK(VOID) | ||
146 | #define BU2614_FMES_MASK MKMASK(FMES) | ||
147 | #define BU2614_STDF_MASK MKMASK(STDF) | ||
148 | #define BU2614_SWIN_MASK MKMASK(SWIN) | ||
149 | #define BU2614_SWAL_MASK MKMASK(SWAL) | ||
150 | #define BU2614_VOID2_MASK MKMASK(VOID2) | ||
151 | #define BU2614_FMUN_MASK MKMASK(FMUN) | ||
152 | #define BU2614_TEST_MASK MKMASK(TEST) | ||
66 | 153 | ||
67 | /* local things */ | 154 | static struct gemtek_device gemtek_unit; |
68 | 155 | ||
69 | /* the correct way to mute the gemtek may be to write the last written | 156 | static spinlock_t lock; |
70 | * frequency || 0x10, but just writing 0x10 once seems to do it as well | 157 | |
158 | /* | ||
159 | * Set data which will be sent to BU2614FS. | ||
71 | */ | 160 | */ |
72 | static void gemtek_mute(struct gemtek_device *dev) | 161 | #define gemtek_bu2614_set(dev, field, data) ((dev)->bu2614data = \ |
162 | ((dev)->bu2614data & ~field##_MASK) | ((data) << field##_SHIFT)) | ||
163 | |||
164 | /* | ||
165 | * Transmit settings to BU2614FS over GemTek IC. | ||
166 | */ | ||
167 | static void gemtek_bu2614_transmit(struct gemtek_device *dev) | ||
73 | { | 168 | { |
74 | if(dev->muted) | 169 | int i, bit, q, mute; |
75 | return; | 170 | |
76 | spin_lock(&lock); | 171 | spin_lock(&lock); |
77 | outb(0x10, io); | 172 | |
173 | mute = dev->muted ? GEMTEK_MT : 0x00; | ||
174 | |||
175 | outb_p(mute | GEMTEK_DA | GEMTEK_CK, io); | ||
176 | udelay(SHORT_DELAY); | ||
177 | outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io); | ||
178 | udelay(LONG_DELAY); | ||
179 | |||
180 | for (i = 0, q = dev->bu2614data; i < 32; i++, q >>= 1) { | ||
181 | bit = (q & 1) ? GEMTEK_DA : 0; | ||
182 | outb_p(mute | GEMTEK_CE | bit, io); | ||
183 | udelay(SHORT_DELAY); | ||
184 | outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, io); | ||
185 | udelay(SHORT_DELAY); | ||
186 | } | ||
187 | |||
188 | outb_p(mute | GEMTEK_DA | GEMTEK_CK, io); | ||
189 | udelay(SHORT_DELAY); | ||
190 | outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io); | ||
191 | udelay(LONG_DELAY); | ||
192 | |||
78 | spin_unlock(&lock); | 193 | spin_unlock(&lock); |
79 | dev->muted = 1; | ||
80 | } | 194 | } |
81 | 195 | ||
82 | static void gemtek_unmute(struct gemtek_device *dev) | 196 | /* |
197 | * Calculate divisor from FM-frequency for BU2614FS (3.125 KHz STDF expected). | ||
198 | */ | ||
199 | static unsigned long gemtek_convfreq(unsigned long freq) | ||
83 | { | 200 | { |
84 | if(dev->muted == 0) | 201 | return ((freq<<FSCALE) + IF_OFFSET + REF_FREQ/2) / REF_FREQ; |
202 | } | ||
203 | |||
204 | /* | ||
205 | * Set FM-frequency. | ||
206 | */ | ||
207 | static void gemtek_setfreq(struct gemtek_device *dev, unsigned long freq) | ||
208 | { | ||
209 | |||
210 | if (keepmuted && hardmute && dev->muted) | ||
85 | return; | 211 | return; |
86 | spin_lock(&lock); | 212 | |
87 | outb(0x20, io); | 213 | if (freq < GEMTEK_LOWFREQ) |
88 | spin_unlock(&lock); | 214 | freq = GEMTEK_LOWFREQ; |
215 | else if (freq > GEMTEK_HIGHFREQ) | ||
216 | freq = GEMTEK_HIGHFREQ; | ||
217 | |||
218 | dev->lastfreq = freq; | ||
89 | dev->muted = 0; | 219 | dev->muted = 0; |
220 | |||
221 | gemtek_bu2614_set(dev, BU2614_PORT, 0); | ||
222 | gemtek_bu2614_set(dev, BU2614_FMES, 0); | ||
223 | gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */ | ||
224 | gemtek_bu2614_set(dev, BU2614_SWAL, 0); | ||
225 | gemtek_bu2614_set(dev, BU2614_FMUN, 1); /* GT bit set */ | ||
226 | gemtek_bu2614_set(dev, BU2614_TEST, 0); | ||
227 | |||
228 | gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_STDF_3_125_KHZ); | ||
229 | gemtek_bu2614_set(dev, BU2614_FREQ, gemtek_convfreq(freq)); | ||
230 | |||
231 | gemtek_bu2614_transmit(dev); | ||
90 | } | 232 | } |
91 | 233 | ||
92 | static void zero(void) | 234 | /* |
235 | * Set mute flag. | ||
236 | */ | ||
237 | static void gemtek_mute(struct gemtek_device *dev) | ||
93 | { | 238 | { |
94 | outb_p(0x04, io); | 239 | int i; |
95 | udelay(5); | 240 | dev->muted = 1; |
96 | outb_p(0x05, io); | 241 | |
97 | udelay(5); | 242 | if (hardmute) { |
243 | /* Turn off PLL, disable data output */ | ||
244 | gemtek_bu2614_set(dev, BU2614_PORT, 0); | ||
245 | gemtek_bu2614_set(dev, BU2614_FMES, 0); /* CT bit off */ | ||
246 | gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */ | ||
247 | gemtek_bu2614_set(dev, BU2614_SWAL, 0); | ||
248 | gemtek_bu2614_set(dev, BU2614_FMUN, 0); /* GT bit off */ | ||
249 | gemtek_bu2614_set(dev, BU2614_TEST, 0); | ||
250 | gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_PLL_OFF); | ||
251 | gemtek_bu2614_set(dev, BU2614_FREQ, 0); | ||
252 | gemtek_bu2614_transmit(dev); | ||
253 | } else { | ||
254 | spin_lock(&lock); | ||
255 | |||
256 | /* Read bus contents (CE, CK and DA). */ | ||
257 | i = inb_p(io); | ||
258 | /* Write it back with mute flag set. */ | ||
259 | outb_p((i >> 5) | GEMTEK_MT, io); | ||
260 | udelay(SHORT_DELAY); | ||
261 | |||
262 | spin_unlock(&lock); | ||
263 | } | ||
98 | } | 264 | } |
99 | 265 | ||
100 | static void one(void) | 266 | /* |
267 | * Unset mute flag. | ||
268 | */ | ||
269 | static void gemtek_unmute(struct gemtek_device *dev) | ||
101 | { | 270 | { |
102 | outb_p(0x06, io); | 271 | int i; |
103 | udelay(5); | 272 | dev->muted = 0; |
104 | outb_p(0x07, io); | 273 | |
105 | udelay(5); | 274 | if (hardmute) { |
275 | /* Turn PLL back on. */ | ||
276 | gemtek_setfreq(dev, dev->lastfreq); | ||
277 | } else { | ||
278 | spin_lock(&lock); | ||
279 | |||
280 | i = inb_p(io); | ||
281 | outb_p(i >> 5, io); | ||
282 | udelay(SHORT_DELAY); | ||
283 | |||
284 | spin_unlock(&lock); | ||
285 | } | ||
106 | } | 286 | } |
107 | 287 | ||
108 | static int gemtek_setfreq(struct gemtek_device *dev, unsigned long freq) | 288 | /* |
289 | * Get signal strength (= stereo status). | ||
290 | */ | ||
291 | static inline int gemtek_getsigstr(void) | ||
109 | { | 292 | { |
110 | int i; | 293 | return inb_p(io) & GEMTEK_NS ? 0 : 1; |
294 | } | ||
111 | 295 | ||
112 | /* freq = 78.25*((float)freq/16000.0 + 10.52); */ | 296 | /* |
297 | * Check if requested card acts like GemTek Radio card. | ||
298 | */ | ||
299 | static int gemtek_verify(int port) | ||
300 | { | ||
301 | static int verified = -1; | ||
302 | int i, q; | ||
113 | 303 | ||
114 | freq /= 16; | 304 | if (verified == port) |
115 | freq += 10520; | 305 | return 1; |
116 | freq *= 7825; | ||
117 | freq /= 100000; | ||
118 | 306 | ||
119 | spin_lock(&lock); | 307 | spin_lock(&lock); |
120 | 308 | ||
121 | /* 2 start bits */ | 309 | q = inb_p(port); /* Read bus contents before probing. */ |
122 | outb_p(0x03, io); | 310 | /* Try to turn on CE, CK and DA respectively and check if card responds |
123 | udelay(5); | 311 | properly. */ |
124 | outb_p(0x07, io); | 312 | for (i = 0; i < 3; ++i) { |
125 | udelay(5); | 313 | outb_p(1 << i, port); |
314 | udelay(SHORT_DELAY); | ||
126 | 315 | ||
127 | /* 28 frequency bits (lsb first) */ | 316 | if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) { |
128 | for (i = 0; i < 14; i++) | 317 | spin_unlock(&lock); |
129 | if (freq & (1 << i)) | 318 | return 0; |
130 | one(); | 319 | } |
131 | else | 320 | } |
132 | zero(); | 321 | outb_p(q >> 5, port); /* Write bus contents back. */ |
133 | /* 36 unknown bits */ | 322 | udelay(SHORT_DELAY); |
134 | for (i = 0; i < 11; i++) | ||
135 | zero(); | ||
136 | one(); | ||
137 | for (i = 0; i < 4; i++) | ||
138 | zero(); | ||
139 | one(); | ||
140 | zero(); | ||
141 | |||
142 | /* 2 end bits */ | ||
143 | outb_p(0x03, io); | ||
144 | udelay(5); | ||
145 | outb_p(0x07, io); | ||
146 | udelay(5); | ||
147 | 323 | ||
148 | spin_unlock(&lock); | 324 | spin_unlock(&lock); |
325 | verified = port; | ||
149 | 326 | ||
150 | return 0; | 327 | return 1; |
151 | } | 328 | } |
152 | 329 | ||
153 | static int gemtek_getsigstr(struct gemtek_device *dev) | 330 | /* |
331 | * Automatic probing for card. | ||
332 | */ | ||
333 | static int gemtek_probe(void) | ||
154 | { | 334 | { |
155 | spin_lock(&lock); | 335 | int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c }; |
156 | inb(io); | 336 | int i; |
157 | udelay(5); | 337 | |
158 | spin_unlock(&lock); | 338 | if (!probe) { |
159 | if (inb(io) & 8) /* bit set = no signal present */ | 339 | printk(KERN_INFO "Automatic device probing disabled.\n"); |
160 | return 0; | 340 | return -1; |
161 | return 1; /* signal present */ | 341 | } |
342 | |||
343 | printk(KERN_INFO "Automatic device probing enabled.\n"); | ||
344 | |||
345 | for (i = 0; i < ARRAY_SIZE(ioports); ++i) { | ||
346 | printk(KERN_INFO "Trying I/O port 0x%x...\n", ioports[i]); | ||
347 | |||
348 | if (!request_region(ioports[i], 1, "gemtek-probe")) { | ||
349 | printk(KERN_WARNING "I/O port 0x%x busy!\n", | ||
350 | ioports[i]); | ||
351 | continue; | ||
352 | } | ||
353 | |||
354 | if (gemtek_verify(ioports[i])) { | ||
355 | printk(KERN_INFO "Card found from I/O port " | ||
356 | "0x%x!\n", ioports[i]); | ||
357 | |||
358 | release_region(ioports[i], 1); | ||
359 | |||
360 | io = ioports[i]; | ||
361 | return io; | ||
362 | } | ||
363 | |||
364 | release_region(ioports[i], 1); | ||
365 | } | ||
366 | |||
367 | printk(KERN_ERR "Automatic probing failed!\n"); | ||
368 | |||
369 | return -1; | ||
162 | } | 370 | } |
163 | 371 | ||
164 | static int vidioc_querycap(struct file *file, void *priv, | 372 | /* |
165 | struct v4l2_capability *v) | 373 | * Video 4 Linux stuff. |
374 | */ | ||
375 | |||
376 | static struct v4l2_queryctrl radio_qctrl[] = { | ||
377 | { | ||
378 | .id = V4L2_CID_AUDIO_MUTE, | ||
379 | .name = "Mute", | ||
380 | .minimum = 0, | ||
381 | .maximum = 1, | ||
382 | .default_value = 1, | ||
383 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
384 | }, { | ||
385 | .id = V4L2_CID_AUDIO_VOLUME, | ||
386 | .name = "Volume", | ||
387 | .minimum = 0, | ||
388 | .maximum = 65535, | ||
389 | .step = 65535, | ||
390 | .default_value = 0xff, | ||
391 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
392 | } | ||
393 | }; | ||
394 | |||
395 | static struct file_operations gemtek_fops = { | ||
396 | .owner = THIS_MODULE, | ||
397 | .open = video_exclusive_open, | ||
398 | .release = video_exclusive_release, | ||
399 | .ioctl = video_ioctl2, | ||
400 | .compat_ioctl = v4l_compat_ioctl32, | ||
401 | .llseek = no_llseek | ||
402 | }; | ||
403 | |||
404 | static int vidioc_querycap(struct file *file, void *priv, | ||
405 | struct v4l2_capability *v) | ||
166 | { | 406 | { |
167 | strlcpy(v->driver, "radio-gemtek", sizeof(v->driver)); | 407 | strlcpy(v->driver, "radio-gemtek", sizeof(v->driver)); |
168 | strlcpy(v->card, "GemTek", sizeof(v->card)); | 408 | strlcpy(v->card, "GemTek", sizeof(v->card)); |
@@ -172,28 +412,29 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
172 | return 0; | 412 | return 0; |
173 | } | 413 | } |
174 | 414 | ||
175 | static int vidioc_g_tuner(struct file *file, void *priv, | 415 | static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) |
176 | struct v4l2_tuner *v) | ||
177 | { | 416 | { |
178 | struct video_device *dev = video_devdata(file); | ||
179 | struct gemtek_device *rt = dev->priv; | ||
180 | |||
181 | if (v->index > 0) | 417 | if (v->index > 0) |
182 | return -EINVAL; | 418 | return -EINVAL; |
183 | 419 | ||
184 | strcpy(v->name, "FM"); | 420 | strcpy(v->name, "FM"); |
185 | v->type = V4L2_TUNER_RADIO; | 421 | v->type = V4L2_TUNER_RADIO; |
186 | v->rangelow = (87*16000); | 422 | v->rangelow = GEMTEK_LOWFREQ; |
187 | v->rangehigh = (108*16000); | 423 | v->rangehigh = GEMTEK_HIGHFREQ; |
188 | v->rxsubchans = V4L2_TUNER_SUB_MONO; | 424 | v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; |
189 | v->capability = V4L2_TUNER_CAP_LOW; | 425 | v->signal = 0xffff * gemtek_getsigstr(); |
190 | v->audmode = V4L2_TUNER_MODE_MONO; | 426 | if (v->signal) { |
191 | v->signal = 0xffff*gemtek_getsigstr(rt); | 427 | v->audmode = V4L2_TUNER_MODE_STEREO; |
428 | v->rxsubchans = V4L2_TUNER_SUB_STEREO; | ||
429 | } else { | ||
430 | v->audmode = V4L2_TUNER_MODE_MONO; | ||
431 | v->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
432 | } | ||
433 | |||
192 | return 0; | 434 | return 0; |
193 | } | 435 | } |
194 | 436 | ||
195 | static int vidioc_s_tuner(struct file *file, void *priv, | 437 | static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) |
196 | struct v4l2_tuner *v) | ||
197 | { | 438 | { |
198 | if (v->index > 0) | 439 | if (v->index > 0) |
199 | return -EINVAL; | 440 | return -EINVAL; |
@@ -201,38 +442,35 @@ static int vidioc_s_tuner(struct file *file, void *priv, | |||
201 | } | 442 | } |
202 | 443 | ||
203 | static int vidioc_s_frequency(struct file *file, void *priv, | 444 | static int vidioc_s_frequency(struct file *file, void *priv, |
204 | struct v4l2_frequency *f) | 445 | struct v4l2_frequency *f) |
205 | { | 446 | { |
206 | struct video_device *dev = video_devdata(file); | 447 | struct video_device *dev = video_devdata(file); |
207 | struct gemtek_device *rt = dev->priv; | 448 | struct gemtek_device *rt = dev->priv; |
208 | 449 | ||
209 | rt->curfreq = f->frequency; | 450 | gemtek_setfreq(rt, f->frequency); |
210 | /* needs to be called twice in order for getsigstr to work */ | 451 | |
211 | gemtek_setfreq(rt, rt->curfreq); | ||
212 | gemtek_setfreq(rt, rt->curfreq); | ||
213 | return 0; | 452 | return 0; |
214 | } | 453 | } |
215 | 454 | ||
216 | static int vidioc_g_frequency(struct file *file, void *priv, | 455 | static int vidioc_g_frequency(struct file *file, void *priv, |
217 | struct v4l2_frequency *f) | 456 | struct v4l2_frequency *f) |
218 | { | 457 | { |
219 | struct video_device *dev = video_devdata(file); | 458 | struct video_device *dev = video_devdata(file); |
220 | struct gemtek_device *rt = dev->priv; | 459 | struct gemtek_device *rt = dev->priv; |
221 | 460 | ||
222 | f->type = V4L2_TUNER_RADIO; | 461 | f->type = V4L2_TUNER_RADIO; |
223 | f->frequency = rt->curfreq; | 462 | f->frequency = rt->lastfreq; |
224 | return 0; | 463 | return 0; |
225 | } | 464 | } |
226 | 465 | ||
227 | static int vidioc_queryctrl(struct file *file, void *priv, | 466 | static int vidioc_queryctrl(struct file *file, void *priv, |
228 | struct v4l2_queryctrl *qc) | 467 | struct v4l2_queryctrl *qc) |
229 | { | 468 | { |
230 | int i; | 469 | int i; |
231 | 470 | ||
232 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | 471 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); ++i) { |
233 | if (qc->id && qc->id == radio_qctrl[i].id) { | 472 | if (qc->id && qc->id == radio_qctrl[i].id) { |
234 | memcpy(qc, &(radio_qctrl[i]), | 473 | memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); |
235 | sizeof(*qc)); | ||
236 | return 0; | 474 | return 0; |
237 | } | 475 | } |
238 | } | 476 | } |
@@ -240,7 +478,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
240 | } | 478 | } |
241 | 479 | ||
242 | static int vidioc_g_ctrl(struct file *file, void *priv, | 480 | static int vidioc_g_ctrl(struct file *file, void *priv, |
243 | struct v4l2_control *ctrl) | 481 | struct v4l2_control *ctrl) |
244 | { | 482 | { |
245 | struct video_device *dev = video_devdata(file); | 483 | struct video_device *dev = video_devdata(file); |
246 | struct gemtek_device *rt = dev->priv; | 484 | struct gemtek_device *rt = dev->priv; |
@@ -260,7 +498,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
260 | } | 498 | } |
261 | 499 | ||
262 | static int vidioc_s_ctrl(struct file *file, void *priv, | 500 | static int vidioc_s_ctrl(struct file *file, void *priv, |
263 | struct v4l2_control *ctrl) | 501 | struct v4l2_control *ctrl) |
264 | { | 502 | { |
265 | struct video_device *dev = video_devdata(file); | 503 | struct video_device *dev = video_devdata(file); |
266 | struct gemtek_device *rt = dev->priv; | 504 | struct gemtek_device *rt = dev->priv; |
@@ -282,8 +520,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
282 | return -EINVAL; | 520 | return -EINVAL; |
283 | } | 521 | } |
284 | 522 | ||
285 | static int vidioc_g_audio (struct file *file, void *priv, | 523 | static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) |
286 | struct v4l2_audio *a) | ||
287 | { | 524 | { |
288 | if (a->index > 1) | 525 | if (a->index > 1) |
289 | return -EINVAL; | 526 | return -EINVAL; |
@@ -306,99 +543,102 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) | |||
306 | return 0; | 543 | return 0; |
307 | } | 544 | } |
308 | 545 | ||
309 | static int vidioc_s_audio(struct file *file, void *priv, | 546 | static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) |
310 | struct v4l2_audio *a) | ||
311 | { | 547 | { |
312 | if (a->index != 0) | 548 | if (a->index != 0) |
313 | return -EINVAL; | 549 | return -EINVAL; |
314 | return 0; | 550 | return 0; |
315 | } | 551 | } |
316 | 552 | ||
317 | static struct gemtek_device gemtek_unit; | 553 | static struct video_device gemtek_radio = { |
318 | 554 | .owner = THIS_MODULE, | |
319 | static const struct file_operations gemtek_fops = { | 555 | .name = "GemTek Radio card", |
320 | .owner = THIS_MODULE, | 556 | .type = VID_TYPE_TUNER, |
321 | .open = video_exclusive_open, | 557 | .hardware = VID_HARDWARE_GEMTEK, |
322 | .release = video_exclusive_release, | 558 | .fops = &gemtek_fops, |
323 | .ioctl = video_ioctl2, | 559 | .vidioc_querycap = vidioc_querycap, |
324 | .compat_ioctl = v4l_compat_ioctl32, | 560 | .vidioc_g_tuner = vidioc_g_tuner, |
325 | .llseek = no_llseek, | 561 | .vidioc_s_tuner = vidioc_s_tuner, |
562 | .vidioc_g_audio = vidioc_g_audio, | ||
563 | .vidioc_s_audio = vidioc_s_audio, | ||
564 | .vidioc_g_input = vidioc_g_input, | ||
565 | .vidioc_s_input = vidioc_s_input, | ||
566 | .vidioc_g_frequency = vidioc_g_frequency, | ||
567 | .vidioc_s_frequency = vidioc_s_frequency, | ||
568 | .vidioc_queryctrl = vidioc_queryctrl, | ||
569 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
570 | .vidioc_s_ctrl = vidioc_s_ctrl | ||
326 | }; | 571 | }; |
327 | 572 | ||
328 | static struct video_device gemtek_radio= | 573 | /* |
329 | { | 574 | * Initialization / cleanup related stuff. |
330 | .owner = THIS_MODULE, | 575 | */ |
331 | .name = "GemTek radio", | ||
332 | .type = VID_TYPE_TUNER, | ||
333 | .fops = &gemtek_fops, | ||
334 | .vidioc_querycap = vidioc_querycap, | ||
335 | .vidioc_g_tuner = vidioc_g_tuner, | ||
336 | .vidioc_s_tuner = vidioc_s_tuner, | ||
337 | .vidioc_g_audio = vidioc_g_audio, | ||
338 | .vidioc_s_audio = vidioc_s_audio, | ||
339 | .vidioc_g_input = vidioc_g_input, | ||
340 | .vidioc_s_input = vidioc_s_input, | ||
341 | .vidioc_g_frequency = vidioc_g_frequency, | ||
342 | .vidioc_s_frequency = vidioc_s_frequency, | ||
343 | .vidioc_queryctrl = vidioc_queryctrl, | ||
344 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
345 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
346 | }; | ||
347 | 576 | ||
577 | /* | ||
578 | * Initilize card. | ||
579 | */ | ||
348 | static int __init gemtek_init(void) | 580 | static int __init gemtek_init(void) |
349 | { | 581 | { |
350 | if(io==-1) | 582 | printk(KERN_INFO RADIO_BANNER "\n"); |
351 | { | ||
352 | printk(KERN_ERR "You must set an I/O address with io=0x20c, io=0x30c, io=0x24c or io=0x34c (io=0x020c or io=0x248 for the combined sound/radiocard)\n"); | ||
353 | return -EINVAL; | ||
354 | } | ||
355 | 583 | ||
356 | if (!request_region(io, 4, "gemtek")) | 584 | spin_lock_init(&lock); |
357 | { | ||
358 | printk(KERN_ERR "gemtek: port 0x%x already in use\n", io); | ||
359 | return -EBUSY; | ||
360 | } | ||
361 | 585 | ||
362 | gemtek_radio.priv=&gemtek_unit; | 586 | gemtek_probe(); |
587 | if (io) { | ||
588 | if (!request_region(io, 1, "gemtek")) { | ||
589 | printk(KERN_ERR "I/O port 0x%x already in use.\n", io); | ||
590 | return -EBUSY; | ||
591 | } | ||
363 | 592 | ||
364 | if(video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr)==-1) | 593 | if (!gemtek_verify(io)) |
365 | { | 594 | printk(KERN_WARNING "Card at I/O port 0x%x does not " |
366 | release_region(io, 4); | 595 | "respond properly, check your " |
596 | "configuration.\n", io); | ||
597 | else | ||
598 | printk(KERN_INFO "Using I/O port 0x%x.\n", io); | ||
599 | } else if (probe) { | ||
600 | printk(KERN_ERR "Automatic probing failed and no " | ||
601 | "fixed I/O port defined.\n"); | ||
602 | return -ENODEV; | ||
603 | } else { | ||
604 | printk(KERN_ERR "Automatic probing disabled but no fixed " | ||
605 | "I/O port defined."); | ||
367 | return -EINVAL; | 606 | return -EINVAL; |
368 | } | 607 | } |
369 | printk(KERN_INFO "GemTek Radio Card driver.\n"); | ||
370 | 608 | ||
371 | spin_lock_init(&lock); | 609 | gemtek_radio.priv = &gemtek_unit; |
372 | 610 | ||
373 | /* this is _maybe_ unnecessary */ | 611 | if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, |
374 | outb(0x01, io); | 612 | radio_nr) == -1) { |
613 | release_region(io, 1); | ||
614 | return -EBUSY; | ||
615 | } | ||
375 | 616 | ||
376 | /* mute card - prevents noisy bootups */ | 617 | /* Set defaults */ |
377 | gemtek_unit.muted = 0; | 618 | gemtek_unit.lastfreq = GEMTEK_LOWFREQ; |
378 | gemtek_mute(&gemtek_unit); | 619 | gemtek_unit.bu2614data = 0; |
620 | |||
621 | if (initmute) | ||
622 | gemtek_mute(&gemtek_unit); | ||
379 | 623 | ||
380 | return 0; | 624 | return 0; |
381 | } | 625 | } |
382 | 626 | ||
383 | MODULE_AUTHOR("Jonas Munsin"); | 627 | /* |
384 | MODULE_DESCRIPTION("A driver for the GemTek Radio Card"); | 628 | * Module cleanup |
385 | MODULE_LICENSE("GPL"); | 629 | */ |
386 | 630 | static void __exit gemtek_exit(void) | |
387 | module_param(io, int, 0); | ||
388 | MODULE_PARM_DESC(io, "I/O address of the GemTek card (0x20c, 0x30c, 0x24c or 0x34c (0x20c or 0x248 have been reported to work for the combined sound/radiocard))."); | ||
389 | module_param(radio_nr, int, 0); | ||
390 | |||
391 | static void __exit gemtek_cleanup(void) | ||
392 | { | 631 | { |
632 | if (shutdown) { | ||
633 | hardmute = 1; /* Turn off PLL */ | ||
634 | gemtek_mute(&gemtek_unit); | ||
635 | } else { | ||
636 | printk(KERN_INFO "Module unloaded but card not muted!\n"); | ||
637 | } | ||
638 | |||
393 | video_unregister_device(&gemtek_radio); | 639 | video_unregister_device(&gemtek_radio); |
394 | release_region(io,4); | 640 | release_region(io, 1); |
395 | } | 641 | } |
396 | 642 | ||
397 | module_init(gemtek_init); | 643 | module_init(gemtek_init); |
398 | module_exit(gemtek_cleanup); | 644 | module_exit(gemtek_exit); |
399 | |||
400 | /* | ||
401 | Local variables: | ||
402 | compile-command: "gcc -c -DMODVERSIONS -D__KERNEL__ -DMODULE -O6 -Wall -Wstrict-prototypes -I /home/blp/tmp/linux-2.1.111-rtrack/include radio-rtrack2.c" | ||
403 | End: | ||
404 | */ | ||
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index 7e1911c3d54e..535ffe8c8102 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c | |||
@@ -173,7 +173,7 @@ static int tt_setfreq(struct tt_device *dev, unsigned long freq1) | |||
173 | i--; | 173 | i--; |
174 | p--; | 174 | p--; |
175 | temp = temp/2; | 175 | temp = temp/2; |
176 | } | 176 | } |
177 | 177 | ||
178 | spin_lock(&lock); | 178 | spin_lock(&lock); |
179 | 179 | ||
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index e204e7b4028a..2e571eb9313a 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -148,6 +148,15 @@ config VIDEO_WM8739 | |||
148 | To compile this driver as a module, choose M here: the | 148 | To compile this driver as a module, choose M here: the |
149 | module will be called wm8739. | 149 | module will be called wm8739. |
150 | 150 | ||
151 | config VIDEO_VP27SMPX | ||
152 | tristate "Panasonic VP27s internal MPX" | ||
153 | depends on VIDEO_V4L2 && I2C && EXPERIMENTAL | ||
154 | ---help--- | ||
155 | Support for the internal MPX of the Panasonic VP27s tuner. | ||
156 | |||
157 | To compile this driver as a module, choose M here: the | ||
158 | module will be called vp27smpx. | ||
159 | |||
151 | comment "Video decoders" | 160 | comment "Video decoders" |
152 | 161 | ||
153 | config VIDEO_BT819 | 162 | config VIDEO_BT819 |
@@ -197,6 +206,13 @@ config VIDEO_OV7670 | |||
197 | OV7670 VGA camera. It currently only works with the M88ALP01 | 206 | OV7670 VGA camera. It currently only works with the M88ALP01 |
198 | controller. | 207 | controller. |
199 | 208 | ||
209 | config VIDEO_TCM825X | ||
210 | tristate "TCM825x camera sensor support" | ||
211 | depends on I2C && VIDEO_V4L2 | ||
212 | ---help--- | ||
213 | This is a driver for the Toshiba TCM825x VGA camera sensor. | ||
214 | It is used for example in Nokia N800. | ||
215 | |||
200 | config VIDEO_SAA7110 | 216 | config VIDEO_SAA7110 |
201 | tristate "Philips SAA7110 video decoder" | 217 | tristate "Philips SAA7110 video decoder" |
202 | depends on VIDEO_V4L1 && I2C | 218 | depends on VIDEO_V4L1 && I2C |
@@ -348,7 +364,7 @@ endmenu # encoder / decoder chips | |||
348 | config VIDEO_VIVI | 364 | config VIDEO_VIVI |
349 | tristate "Virtual Video Driver" | 365 | tristate "Virtual Video Driver" |
350 | depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI | 366 | depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI |
351 | select VIDEO_BUF | 367 | select VIDEOBUF_VMALLOC |
352 | default n | 368 | default n |
353 | ---help--- | 369 | ---help--- |
354 | Enables a virtual video driver. This device shows a color bar | 370 | Enables a virtual video driver. This device shows a color bar |
@@ -489,15 +505,6 @@ config TUNER_3036 | |||
489 | Say Y here to include support for Philips SAB3036 compatible tuners. | 505 | Say Y here to include support for Philips SAB3036 compatible tuners. |
490 | If in doubt, say N. | 506 | If in doubt, say N. |
491 | 507 | ||
492 | config TUNER_TEA5761 | ||
493 | bool "TEA 5761 radio tuner (EXPERIMENTAL)" | ||
494 | depends on EXPERIMENTAL | ||
495 | depends on I2C | ||
496 | select VIDEO_TUNER | ||
497 | help | ||
498 | Say Y here to include support for Philips TEA5761 radio tuner. | ||
499 | If in doubt, say N. | ||
500 | |||
501 | config VIDEO_VINO | 508 | config VIDEO_VINO |
502 | tristate "SGI Vino Video For Linux (EXPERIMENTAL)" | 509 | tristate "SGI Vino Video For Linux (EXPERIMENTAL)" |
503 | depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 | 510 | depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 |
@@ -661,6 +668,8 @@ config VIDEO_HEXIUM_GEMINI | |||
661 | 668 | ||
662 | source "drivers/media/video/cx88/Kconfig" | 669 | source "drivers/media/video/cx88/Kconfig" |
663 | 670 | ||
671 | source "drivers/media/video/cx23885/Kconfig" | ||
672 | |||
664 | source "drivers/media/video/ivtv/Kconfig" | 673 | source "drivers/media/video/ivtv/Kconfig" |
665 | 674 | ||
666 | config VIDEO_M32R_AR | 675 | config VIDEO_M32R_AR |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 10b4d4469016..b5a064163e03 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -4,14 +4,12 @@ | |||
4 | 4 | ||
5 | zr36067-objs := zoran_procfs.o zoran_device.o \ | 5 | zr36067-objs := zoran_procfs.o zoran_device.o \ |
6 | zoran_driver.o zoran_card.o | 6 | zoran_driver.o zoran_card.o |
7 | tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ | 7 | tuner-objs := tuner-core.o tuner-types.o tda9887.o |
8 | mt20xx.o tda8290.o tea5767.o tda9887.o | ||
9 | |||
10 | tuner-$(CONFIG_TUNER_TEA5761) += tea5761.o | ||
11 | 8 | ||
12 | msp3400-objs := msp3400-driver.o msp3400-kthreads.o | 9 | msp3400-objs := msp3400-driver.o msp3400-kthreads.o |
13 | 10 | ||
14 | obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o | 11 | obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o \ |
12 | v4l2-int-device.o | ||
15 | 13 | ||
16 | ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y) | 14 | ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y) |
17 | obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o | 15 | obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o |
@@ -63,7 +61,6 @@ obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o | |||
63 | obj-$(CONFIG_VIDEO_MEYE) += meye.o | 61 | obj-$(CONFIG_VIDEO_MEYE) += meye.o |
64 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ | 62 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ |
65 | obj-$(CONFIG_VIDEO_CX88) += cx88/ | 63 | obj-$(CONFIG_VIDEO_CX88) += cx88/ |
66 | obj-$(CONFIG_VIDEO_IVTV) += ivtv/ | ||
67 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ | 64 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ |
68 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ | 65 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ |
69 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o | 66 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o |
@@ -73,6 +70,7 @@ obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o | |||
73 | obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o | 70 | obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o |
74 | obj-$(CONFIG_VIDEO_WM8775) += wm8775.o | 71 | obj-$(CONFIG_VIDEO_WM8775) += wm8775.o |
75 | obj-$(CONFIG_VIDEO_WM8739) += wm8739.o | 72 | obj-$(CONFIG_VIDEO_WM8739) += wm8739.o |
73 | obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o | ||
76 | obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ | 74 | obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ |
77 | obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ | 75 | obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ |
78 | obj-$(CONFIG_VIDEO_MXB) += mxb.o | 76 | obj-$(CONFIG_VIDEO_MXB) += mxb.o |
@@ -82,8 +80,17 @@ obj-$(CONFIG_VIDEO_DPC) += dpc7146.o | |||
82 | obj-$(CONFIG_TUNER_3036) += tuner-3036.o | 80 | obj-$(CONFIG_TUNER_3036) += tuner-3036.o |
83 | 81 | ||
84 | obj-$(CONFIG_VIDEO_TUNER) += tuner.o | 82 | obj-$(CONFIG_VIDEO_TUNER) += tuner.o |
85 | obj-$(CONFIG_VIDEO_BUF) += video-buf.o | 83 | |
86 | obj-$(CONFIG_VIDEO_BUF_DVB) += video-buf-dvb.o | 84 | obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o |
85 | obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o | ||
86 | obj-$(CONFIG_TUNER_TDA8290) += tda8290.o | ||
87 | obj-$(CONFIG_TUNER_TEA5767) += tea5767.o | ||
88 | obj-$(CONFIG_TUNER_TEA5761) += tea5761.o | ||
89 | |||
90 | obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o | ||
91 | obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o | ||
92 | obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o | ||
93 | obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o | ||
87 | obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o | 94 | obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o |
88 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o | 95 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o |
89 | 96 | ||
@@ -97,6 +104,8 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o | |||
97 | obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o | 104 | obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o |
98 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o | 105 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o |
99 | 106 | ||
107 | obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o | ||
108 | |||
100 | obj-$(CONFIG_USB_DABUSB) += dabusb.o | 109 | obj-$(CONFIG_USB_DABUSB) += dabusb.o |
101 | obj-$(CONFIG_USB_OV511) += ov511.o | 110 | obj-$(CONFIG_USB_OV511) += ov511.o |
102 | obj-$(CONFIG_USB_SE401) += se401.o | 111 | obj-$(CONFIG_USB_SE401) += se401.o |
@@ -114,6 +123,9 @@ obj-$(CONFIG_USB_KONICAWC) += usbvideo/ | |||
114 | obj-$(CONFIG_USB_VICAM) += usbvideo/ | 123 | obj-$(CONFIG_USB_VICAM) += usbvideo/ |
115 | obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/ | 124 | obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/ |
116 | 125 | ||
126 | obj-$(CONFIG_VIDEO_IVTV) += ivtv/ | ||
127 | |||
117 | obj-$(CONFIG_VIDEO_VIVI) += vivi.o | 128 | obj-$(CONFIG_VIDEO_VIVI) += vivi.o |
129 | obj-$(CONFIG_VIDEO_CX23885) += cx23885/ | ||
118 | 130 | ||
119 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | 131 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core |
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 649f52f9ad27..19e9929ffa0f 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/init.h> | ||
27 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
28 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
29 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
@@ -442,7 +441,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file, | |||
442 | { | 441 | { |
443 | struct video_window *w = arg; | 442 | struct video_window *w = arg; |
444 | DEBUG(1, "VIDIOCGWIN:\n"); | 443 | DEBUG(1, "VIDIOCGWIN:\n"); |
445 | memset(w, 0, sizeof(w)); | 444 | memset(w, 0, sizeof(*w)); |
446 | w->width = ar->width; | 445 | w->width = ar->width; |
447 | w->height = ar->height; | 446 | w->height = ar->height; |
448 | return 0; | 447 | return 0; |
diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index 58eae887a629..2ca162b390a2 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig | |||
@@ -4,7 +4,7 @@ config VIDEO_BT848 | |||
4 | select I2C_ALGOBIT | 4 | select I2C_ALGOBIT |
5 | select FW_LOADER | 5 | select FW_LOADER |
6 | select VIDEO_BTCX | 6 | select VIDEO_BTCX |
7 | select VIDEO_BUF | 7 | select VIDEOBUF_DMA_SG |
8 | select VIDEO_IR | 8 | select VIDEO_IR |
9 | select VIDEO_TUNER | 9 | select VIDEO_TUNER |
10 | select VIDEO_TVEEPROM | 10 | select VIDEO_TVEEPROM |
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index f6715007d409..dd6a7d68b07f 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c | |||
@@ -27,7 +27,6 @@ | |||
27 | 27 | ||
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/moduleparam.h> | ||
31 | #include <linux/kmod.h> | 30 | #include <linux/kmod.h> |
32 | #include <linux/init.h> | 31 | #include <linux/init.h> |
33 | #include <linux/pci.h> | 32 | #include <linux/pci.h> |
@@ -2989,6 +2988,23 @@ struct tvcard bttv_tvcards[] = { | |||
2989 | .no_tda9875 = 1, | 2988 | .no_tda9875 = 1, |
2990 | .no_tda7432 = 1, | 2989 | .no_tda7432 = 1, |
2991 | }, | 2990 | }, |
2991 | /* ---- card 0x95---------------------------------- */ | ||
2992 | [BTTV_BOARD_TYPHOON_TVTUNERPCI] = { | ||
2993 | .name = "Typhoon TV-Tuner PCI (50684)", | ||
2994 | .video_inputs = 3, | ||
2995 | .audio_inputs = 1, | ||
2996 | .tuner = 0, | ||
2997 | .svhs = 2, | ||
2998 | .gpiomask = 0x3014f, | ||
2999 | .muxsel = { 2, 3, 1, 1 }, | ||
3000 | .gpiomux = { 0x20001,0x10001, 0, 0 }, | ||
3001 | .gpiomute = 10, | ||
3002 | .needs_tvaudio = 1, | ||
3003 | .pll = PLL_28, | ||
3004 | .tuner_type = TUNER_PHILIPS_PAL_I, | ||
3005 | .tuner_addr = ADDR_UNSET, | ||
3006 | .radio_addr = ADDR_UNSET, | ||
3007 | }, | ||
2992 | }; | 3008 | }; |
2993 | 3009 | ||
2994 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); | 3010 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); |
@@ -3276,15 +3292,15 @@ static void eagle_muxsel(struct bttv *btv, unsigned int input) | |||
3276 | btaor((2)<<5, ~(3<<5), BT848_IFORM); | 3292 | btaor((2)<<5, ~(3<<5), BT848_IFORM); |
3277 | gpio_bits(3,bttv_tvcards[btv->c.type].muxsel[input&7]); | 3293 | gpio_bits(3,bttv_tvcards[btv->c.type].muxsel[input&7]); |
3278 | 3294 | ||
3279 | /* composite */ | 3295 | /* composite */ |
3280 | /* set chroma ADC to sleep */ | 3296 | /* set chroma ADC to sleep */ |
3281 | btor(BT848_ADC_C_SLEEP, BT848_ADC); | 3297 | btor(BT848_ADC_C_SLEEP, BT848_ADC); |
3282 | /* set to composite video */ | 3298 | /* set to composite video */ |
3283 | btand(~BT848_CONTROL_COMP, BT848_E_CONTROL); | 3299 | btand(~BT848_CONTROL_COMP, BT848_E_CONTROL); |
3284 | btand(~BT848_CONTROL_COMP, BT848_O_CONTROL); | 3300 | btand(~BT848_CONTROL_COMP, BT848_O_CONTROL); |
3285 | 3301 | ||
3286 | /* switch sync drive off */ | 3302 | /* switch sync drive off */ |
3287 | gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE); | 3303 | gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE); |
3288 | } | 3304 | } |
3289 | 3305 | ||
3290 | static void gvc1100_muxsel(struct bttv *btv, unsigned int input) | 3306 | static void gvc1100_muxsel(struct bttv *btv, unsigned int input) |
@@ -3453,7 +3469,7 @@ void __devinit bttv_init_card2(struct bttv *btv) | |||
3453 | printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->c.nr); | 3469 | printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->c.nr); |
3454 | } | 3470 | } |
3455 | break; | 3471 | break; |
3456 | case BTTV_BOARD_STB2: | 3472 | case BTTV_BOARD_STB2: |
3457 | if (btv->cardid == 0x3060121a) { | 3473 | if (btv->cardid == 0x3060121a) { |
3458 | /* Fix up entry for 3DFX VoodooTV 100, | 3474 | /* Fix up entry for 3DFX VoodooTV 100, |
3459 | which is an OEM STB card variant. */ | 3475 | which is an OEM STB card variant. */ |
@@ -3784,7 +3800,7 @@ static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256]) | |||
3784 | for (i = 12; i < 21; i++) | 3800 | for (i = 12; i < 21; i++) |
3785 | serial *= 10, serial += ee[i] - '0'; | 3801 | serial *= 10, serial += ee[i] - '0'; |
3786 | } | 3802 | } |
3787 | } else { | 3803 | } else { |
3788 | unsigned short type; | 3804 | unsigned short type; |
3789 | 3805 | ||
3790 | for (i = 4*16; i < 8*16; i += 16) { | 3806 | for (i = 4*16; i < 8*16; i += 16) { |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index cb555f2c40f9..7a332b3efe51 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -30,7 +30,6 @@ | |||
30 | 30 | ||
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/moduleparam.h> | ||
34 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
35 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
36 | #include <linux/fs.h> | 35 | #include <linux/fs.h> |
@@ -155,13 +154,14 @@ MODULE_LICENSE("GPL"); | |||
155 | /* ----------------------------------------------------------------------- */ | 154 | /* ----------------------------------------------------------------------- */ |
156 | /* sysfs */ | 155 | /* sysfs */ |
157 | 156 | ||
158 | static ssize_t show_card(struct class_device *cd, char *buf) | 157 | static ssize_t show_card(struct device *cd, |
158 | struct device_attribute *attr, char *buf) | ||
159 | { | 159 | { |
160 | struct video_device *vfd = to_video_device(cd); | 160 | struct video_device *vfd = to_video_device(cd); |
161 | struct bttv *btv = dev_get_drvdata(vfd->dev); | 161 | struct bttv *btv = dev_get_drvdata(vfd->dev); |
162 | return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); | 162 | return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); |
163 | } | 163 | } |
164 | static CLASS_DEVICE_ATTR(card, S_IRUGO, show_card, NULL); | 164 | static DEVICE_ATTR(card, S_IRUGO, show_card, NULL); |
165 | 165 | ||
166 | /* ----------------------------------------------------------------------- */ | 166 | /* ----------------------------------------------------------------------- */ |
167 | /* dvb auto-load setup */ | 167 | /* dvb auto-load setup */ |
@@ -2583,7 +2583,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, | |||
2583 | if (check_btres(fh, RESOURCE_OVERLAY)) { | 2583 | if (check_btres(fh, RESOURCE_OVERLAY)) { |
2584 | struct bttv_buffer *new; | 2584 | struct bttv_buffer *new; |
2585 | 2585 | ||
2586 | new = videobuf_alloc(sizeof(*new)); | 2586 | new = videobuf_pci_alloc(sizeof(*new)); |
2587 | new->crop = btv->crop[!!fh->do_crop].rect; | 2587 | new->crop = btv->crop[!!fh->do_crop].rect; |
2588 | bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); | 2588 | bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); |
2589 | retval = bttv_switch_overlay(btv,fh,new); | 2589 | retval = bttv_switch_overlay(btv,fh,new); |
@@ -3049,7 +3049,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
3049 | mutex_lock(&fh->cap.lock); | 3049 | mutex_lock(&fh->cap.lock); |
3050 | if (*on) { | 3050 | if (*on) { |
3051 | fh->ov.tvnorm = btv->tvnorm; | 3051 | fh->ov.tvnorm = btv->tvnorm; |
3052 | new = videobuf_alloc(sizeof(*new)); | 3052 | new = videobuf_pci_alloc(sizeof(*new)); |
3053 | new->crop = btv->crop[!!fh->do_crop].rect; | 3053 | new->crop = btv->crop[!!fh->do_crop].rect; |
3054 | bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); | 3054 | bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); |
3055 | } else { | 3055 | } else { |
@@ -3072,6 +3072,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
3072 | V4L2_MEMORY_MMAP); | 3072 | V4L2_MEMORY_MMAP); |
3073 | if (retval < 0) | 3073 | if (retval < 0) |
3074 | goto fh_unlock_and_return; | 3074 | goto fh_unlock_and_return; |
3075 | |||
3076 | gbuffers = retval; | ||
3075 | memset(mbuf,0,sizeof(*mbuf)); | 3077 | memset(mbuf,0,sizeof(*mbuf)); |
3076 | mbuf->frames = gbuffers; | 3078 | mbuf->frames = gbuffers; |
3077 | mbuf->size = gbuffers * gbufsize; | 3079 | mbuf->size = gbuffers * gbufsize; |
@@ -3142,9 +3144,12 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
3142 | retval = -EIO; | 3144 | retval = -EIO; |
3143 | /* fall through */ | 3145 | /* fall through */ |
3144 | case STATE_DONE: | 3146 | case STATE_DONE: |
3145 | videobuf_dma_sync(&fh->cap,&buf->vb.dma); | 3147 | { |
3148 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
3149 | videobuf_dma_sync(&fh->cap,dma); | ||
3146 | bttv_dma_free(&fh->cap,btv,buf); | 3150 | bttv_dma_free(&fh->cap,btv,buf); |
3147 | break; | 3151 | break; |
3152 | } | ||
3148 | default: | 3153 | default: |
3149 | retval = -EINVAL; | 3154 | retval = -EINVAL; |
3150 | break; | 3155 | break; |
@@ -3338,7 +3343,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
3338 | if (check_btres(fh, RESOURCE_OVERLAY)) { | 3343 | if (check_btres(fh, RESOURCE_OVERLAY)) { |
3339 | struct bttv_buffer *new; | 3344 | struct bttv_buffer *new; |
3340 | 3345 | ||
3341 | new = videobuf_alloc(sizeof(*new)); | 3346 | new = videobuf_pci_alloc(sizeof(*new)); |
3342 | new->crop = btv->crop[!!fh->do_crop].rect; | 3347 | new->crop = btv->crop[!!fh->do_crop].rect; |
3343 | bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new); | 3348 | bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new); |
3344 | retval = bttv_switch_overlay(btv,fh,new); | 3349 | retval = bttv_switch_overlay(btv,fh,new); |
@@ -3697,7 +3702,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) | |||
3697 | mutex_unlock(&fh->cap.lock); | 3702 | mutex_unlock(&fh->cap.lock); |
3698 | return POLLERR; | 3703 | return POLLERR; |
3699 | } | 3704 | } |
3700 | fh->cap.read_buf = videobuf_alloc(fh->cap.msize); | 3705 | fh->cap.read_buf = videobuf_pci_alloc(fh->cap.msize); |
3701 | if (NULL == fh->cap.read_buf) { | 3706 | if (NULL == fh->cap.read_buf) { |
3702 | mutex_unlock(&fh->cap.lock); | 3707 | mutex_unlock(&fh->cap.lock); |
3703 | return POLLERR; | 3708 | return POLLERR; |
@@ -3764,13 +3769,13 @@ static int bttv_open(struct inode *inode, struct file *file) | |||
3764 | fh->ov.setup_ok = 0; | 3769 | fh->ov.setup_ok = 0; |
3765 | v4l2_prio_open(&btv->prio,&fh->prio); | 3770 | v4l2_prio_open(&btv->prio,&fh->prio); |
3766 | 3771 | ||
3767 | videobuf_queue_init(&fh->cap, &bttv_video_qops, | 3772 | videobuf_queue_pci_init(&fh->cap, &bttv_video_qops, |
3768 | btv->c.pci, &btv->s_lock, | 3773 | btv->c.pci, &btv->s_lock, |
3769 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 3774 | V4L2_BUF_TYPE_VIDEO_CAPTURE, |
3770 | V4L2_FIELD_INTERLACED, | 3775 | V4L2_FIELD_INTERLACED, |
3771 | sizeof(struct bttv_buffer), | 3776 | sizeof(struct bttv_buffer), |
3772 | fh); | 3777 | fh); |
3773 | videobuf_queue_init(&fh->vbi, &bttv_vbi_qops, | 3778 | videobuf_queue_pci_init(&fh->vbi, &bttv_vbi_qops, |
3774 | btv->c.pci, &btv->s_lock, | 3779 | btv->c.pci, &btv->s_lock, |
3775 | V4L2_BUF_TYPE_VBI_CAPTURE, | 3780 | V4L2_BUF_TYPE_VBI_CAPTURE, |
3776 | V4L2_FIELD_SEQ_TB, | 3781 | V4L2_FIELD_SEQ_TB, |
@@ -4613,9 +4618,9 @@ static int __devinit bttv_register_video(struct bttv *btv) | |||
4613 | goto err; | 4618 | goto err; |
4614 | printk(KERN_INFO "bttv%d: registered device video%d\n", | 4619 | printk(KERN_INFO "bttv%d: registered device video%d\n", |
4615 | btv->c.nr,btv->video_dev->minor & 0x1f); | 4620 | btv->c.nr,btv->video_dev->minor & 0x1f); |
4616 | if (class_device_create_file(&btv->video_dev->class_dev, | 4621 | if (device_create_file(&btv->video_dev->class_dev, |
4617 | &class_device_attr_card)<0) { | 4622 | &dev_attr_card)<0) { |
4618 | printk(KERN_ERR "bttv%d: class_device_create_file 'card' " | 4623 | printk(KERN_ERR "bttv%d: device_create_file 'card' " |
4619 | "failed\n", btv->c.nr); | 4624 | "failed\n", btv->c.nr); |
4620 | goto err; | 4625 | goto err; |
4621 | } | 4626 | } |
diff --git a/drivers/media/video/bt8xx/bttv-gpio.c b/drivers/media/video/bt8xx/bttv-gpio.c index 84154c26f9c5..dce6dae5740e 100644 --- a/drivers/media/video/bt8xx/bttv-gpio.c +++ b/drivers/media/video/bt8xx/bttv-gpio.c | |||
@@ -106,11 +106,9 @@ int bttv_sub_add_device(struct bttv_core *core, char *name) | |||
106 | 106 | ||
107 | int bttv_sub_del_devices(struct bttv_core *core) | 107 | int bttv_sub_del_devices(struct bttv_core *core) |
108 | { | 108 | { |
109 | struct bttv_sub_device *sub; | 109 | struct bttv_sub_device *sub, *save; |
110 | struct list_head *item,*save; | ||
111 | 110 | ||
112 | list_for_each_safe(item,save,&core->subs) { | 111 | list_for_each_entry_safe(sub, save, &core->subs, list) { |
113 | sub = list_entry(item,struct bttv_sub_device,list); | ||
114 | list_del(&sub->list); | 112 | list_del(&sub->list); |
115 | device_unregister(&sub->dev); | 113 | device_unregister(&sub->dev); |
116 | } | 114 | } |
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c index 0dfa49b66418..844f1762c45a 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/video/bt8xx/bttv-i2c.c | |||
@@ -28,7 +28,6 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/init.h> | 31 | #include <linux/init.h> |
33 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
34 | 33 | ||
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 4201552bc3c0..e7c521b8444a 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c | |||
@@ -19,7 +19,6 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/init.h> | 22 | #include <linux/init.h> |
24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
25 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c index e7104d9cb4bd..58986f1a5f1a 100644 --- a/drivers/media/video/bt8xx/bttv-risc.c +++ b/drivers/media/video/bt8xx/bttv-risc.c | |||
@@ -574,10 +574,12 @@ bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, | |||
574 | void | 574 | void |
575 | bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf) | 575 | bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf) |
576 | { | 576 | { |
577 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
578 | |||
577 | BUG_ON(in_interrupt()); | 579 | BUG_ON(in_interrupt()); |
578 | videobuf_waiton(&buf->vb,0,0); | 580 | videobuf_waiton(&buf->vb,0,0); |
579 | videobuf_dma_unmap(q, &buf->vb.dma); | 581 | videobuf_dma_unmap(q, dma); |
580 | videobuf_dma_free(&buf->vb.dma); | 582 | videobuf_dma_free(dma); |
581 | btcx_riscmem_free(btv->c.pci,&buf->bottom); | 583 | btcx_riscmem_free(btv->c.pci,&buf->bottom); |
582 | btcx_riscmem_free(btv->c.pci,&buf->top); | 584 | btcx_riscmem_free(btv->c.pci,&buf->top); |
583 | buf->vb.state = STATE_NEEDS_INIT; | 585 | buf->vb.state = STATE_NEEDS_INIT; |
@@ -699,6 +701,7 @@ int | |||
699 | bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | 701 | bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) |
700 | { | 702 | { |
701 | const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm; | 703 | const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm; |
704 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
702 | 705 | ||
703 | dprintk(KERN_DEBUG | 706 | dprintk(KERN_DEBUG |
704 | "bttv%d: buffer field: %s format: %s size: %dx%d\n", | 707 | "bttv%d: buffer field: %s format: %s size: %dx%d\n", |
@@ -716,25 +719,25 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
716 | 719 | ||
717 | switch (buf->vb.field) { | 720 | switch (buf->vb.field) { |
718 | case V4L2_FIELD_TOP: | 721 | case V4L2_FIELD_TOP: |
719 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, | 722 | bttv_risc_packed(btv,&buf->top,dma->sglist, |
720 | /* offset */ 0,bpl, | 723 | /* offset */ 0,bpl, |
721 | /* padding */ 0,/* skip_lines */ 0, | 724 | /* padding */ 0,/* skip_lines */ 0, |
722 | buf->vb.height); | 725 | buf->vb.height); |
723 | break; | 726 | break; |
724 | case V4L2_FIELD_BOTTOM: | 727 | case V4L2_FIELD_BOTTOM: |
725 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, | 728 | bttv_risc_packed(btv,&buf->bottom,dma->sglist, |
726 | 0,bpl,0,0,buf->vb.height); | 729 | 0,bpl,0,0,buf->vb.height); |
727 | break; | 730 | break; |
728 | case V4L2_FIELD_INTERLACED: | 731 | case V4L2_FIELD_INTERLACED: |
729 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, | 732 | bttv_risc_packed(btv,&buf->top,dma->sglist, |
730 | 0,bpl,bpl,0,buf->vb.height >> 1); | 733 | 0,bpl,bpl,0,buf->vb.height >> 1); |
731 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, | 734 | bttv_risc_packed(btv,&buf->bottom,dma->sglist, |
732 | bpl,bpl,bpl,0,buf->vb.height >> 1); | 735 | bpl,bpl,bpl,0,buf->vb.height >> 1); |
733 | break; | 736 | break; |
734 | case V4L2_FIELD_SEQ_TB: | 737 | case V4L2_FIELD_SEQ_TB: |
735 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, | 738 | bttv_risc_packed(btv,&buf->top,dma->sglist, |
736 | 0,bpl,0,0,buf->vb.height >> 1); | 739 | 0,bpl,0,0,buf->vb.height >> 1); |
737 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, | 740 | bttv_risc_packed(btv,&buf->bottom,dma->sglist, |
738 | bpf,bpl,0,0,buf->vb.height >> 1); | 741 | bpf,bpl,0,0,buf->vb.height >> 1); |
739 | break; | 742 | break; |
740 | default: | 743 | default: |
@@ -767,7 +770,7 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
767 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, | 770 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
768 | buf->vb.height,/* both_fields */ 0, | 771 | buf->vb.height,/* both_fields */ 0, |
769 | tvnorm,&buf->crop); | 772 | tvnorm,&buf->crop); |
770 | bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist, | 773 | bttv_risc_planar(btv, &buf->top, dma->sglist, |
771 | 0,buf->vb.width,0,buf->vb.height, | 774 | 0,buf->vb.width,0,buf->vb.height, |
772 | uoffset,voffset,buf->fmt->hshift, | 775 | uoffset,voffset,buf->fmt->hshift, |
773 | buf->fmt->vshift,0); | 776 | buf->fmt->vshift,0); |
@@ -776,7 +779,7 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
776 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, | 779 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
777 | buf->vb.height,0, | 780 | buf->vb.height,0, |
778 | tvnorm,&buf->crop); | 781 | tvnorm,&buf->crop); |
779 | bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist, | 782 | bttv_risc_planar(btv, &buf->bottom, dma->sglist, |
780 | 0,buf->vb.width,0,buf->vb.height, | 783 | 0,buf->vb.width,0,buf->vb.height, |
781 | uoffset,voffset,buf->fmt->hshift, | 784 | uoffset,voffset,buf->fmt->hshift, |
782 | buf->fmt->vshift,0); | 785 | buf->fmt->vshift,0); |
@@ -789,14 +792,14 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
789 | ypadding = buf->vb.width; | 792 | ypadding = buf->vb.width; |
790 | cpadding = buf->vb.width >> buf->fmt->hshift; | 793 | cpadding = buf->vb.width >> buf->fmt->hshift; |
791 | bttv_risc_planar(btv,&buf->top, | 794 | bttv_risc_planar(btv,&buf->top, |
792 | buf->vb.dma.sglist, | 795 | dma->sglist, |
793 | 0,buf->vb.width,ypadding,lines, | 796 | 0,buf->vb.width,ypadding,lines, |
794 | uoffset,voffset, | 797 | uoffset,voffset, |
795 | buf->fmt->hshift, | 798 | buf->fmt->hshift, |
796 | buf->fmt->vshift, | 799 | buf->fmt->vshift, |
797 | cpadding); | 800 | cpadding); |
798 | bttv_risc_planar(btv,&buf->bottom, | 801 | bttv_risc_planar(btv,&buf->bottom, |
799 | buf->vb.dma.sglist, | 802 | dma->sglist, |
800 | ypadding,buf->vb.width,ypadding,lines, | 803 | ypadding,buf->vb.width,ypadding,lines, |
801 | uoffset+cpadding, | 804 | uoffset+cpadding, |
802 | voffset+cpadding, | 805 | voffset+cpadding, |
@@ -812,7 +815,7 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
812 | ypadding = buf->vb.width; | 815 | ypadding = buf->vb.width; |
813 | cpadding = buf->vb.width >> buf->fmt->hshift; | 816 | cpadding = buf->vb.width >> buf->fmt->hshift; |
814 | bttv_risc_planar(btv,&buf->top, | 817 | bttv_risc_planar(btv,&buf->top, |
815 | buf->vb.dma.sglist, | 818 | dma->sglist, |
816 | 0,buf->vb.width,0,lines, | 819 | 0,buf->vb.width,0,lines, |
817 | uoffset >> 1, | 820 | uoffset >> 1, |
818 | voffset >> 1, | 821 | voffset >> 1, |
@@ -820,7 +823,7 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
820 | buf->fmt->vshift, | 823 | buf->fmt->vshift, |
821 | 0); | 824 | 0); |
822 | bttv_risc_planar(btv,&buf->bottom, | 825 | bttv_risc_planar(btv,&buf->bottom, |
823 | buf->vb.dma.sglist, | 826 | dma->sglist, |
824 | lines * ypadding,buf->vb.width,0,lines, | 827 | lines * ypadding,buf->vb.width,0,lines, |
825 | lines * ypadding + (uoffset >> 1), | 828 | lines * ypadding + (uoffset >> 1), |
826 | lines * ypadding + (voffset >> 1), | 829 | lines * ypadding + (voffset >> 1), |
@@ -839,10 +842,10 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
839 | buf->vb.field = V4L2_FIELD_SEQ_TB; | 842 | buf->vb.field = V4L2_FIELD_SEQ_TB; |
840 | bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight, | 843 | bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight, |
841 | 1,tvnorm,&buf->crop); | 844 | 1,tvnorm,&buf->crop); |
842 | bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist, | 845 | bttv_risc_packed(btv, &buf->top, dma->sglist, |
843 | /* offset */ 0, RAW_BPL, /* padding */ 0, | 846 | /* offset */ 0, RAW_BPL, /* padding */ 0, |
844 | /* skip_lines */ 0, RAW_LINES); | 847 | /* skip_lines */ 0, RAW_LINES); |
845 | bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist, | 848 | bttv_risc_packed(btv, &buf->bottom, dma->sglist, |
846 | buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES); | 849 | buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES); |
847 | } | 850 | } |
848 | 851 | ||
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c index 93e35de5a181..346ce019bdcb 100644 --- a/drivers/media/video/bt8xx/bttv-vbi.c +++ b/drivers/media/video/bt8xx/bttv-vbi.c | |||
@@ -24,7 +24,6 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/moduleparam.h> | ||
28 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
29 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
30 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
@@ -151,13 +150,14 @@ static int vbi_buffer_prepare(struct videobuf_queue *q, | |||
151 | 150 | ||
152 | if (redo_dma_risc) { | 151 | if (redo_dma_risc) { |
153 | unsigned int bpl, padding, offset; | 152 | unsigned int bpl, padding, offset; |
153 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
154 | 154 | ||
155 | bpl = 2044; /* max. vbipack */ | 155 | bpl = 2044; /* max. vbipack */ |
156 | padding = VBI_BPL - bpl; | 156 | padding = VBI_BPL - bpl; |
157 | 157 | ||
158 | if (fh->vbi_fmt.fmt.count[0] > 0) { | 158 | if (fh->vbi_fmt.fmt.count[0] > 0) { |
159 | rc = bttv_risc_packed(btv, &buf->top, | 159 | rc = bttv_risc_packed(btv, &buf->top, |
160 | buf->vb.dma.sglist, | 160 | dma->sglist, |
161 | /* offset */ 0, bpl, | 161 | /* offset */ 0, bpl, |
162 | padding, skip_lines0, | 162 | padding, skip_lines0, |
163 | fh->vbi_fmt.fmt.count[0]); | 163 | fh->vbi_fmt.fmt.count[0]); |
@@ -169,7 +169,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q, | |||
169 | offset = fh->vbi_fmt.fmt.count[0] * VBI_BPL; | 169 | offset = fh->vbi_fmt.fmt.count[0] * VBI_BPL; |
170 | 170 | ||
171 | rc = bttv_risc_packed(btv, &buf->bottom, | 171 | rc = bttv_risc_packed(btv, &buf->bottom, |
172 | buf->vb.dma.sglist, | 172 | dma->sglist, |
173 | offset, bpl, | 173 | offset, bpl, |
174 | padding, skip_lines1, | 174 | padding, skip_lines1, |
175 | fh->vbi_fmt.fmt.count[1]); | 175 | fh->vbi_fmt.fmt.count[1]); |
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index dcc847dc2486..19e75d50a107 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h | |||
@@ -172,6 +172,8 @@ | |||
172 | #define BTTV_BOARD_SSAI_ULTRASOUND 0x92 | 172 | #define BTTV_BOARD_SSAI_ULTRASOUND 0x92 |
173 | #define BTTV_BOARD_VOODOOTV_200 0x93 | 173 | #define BTTV_BOARD_VOODOOTV_200 0x93 |
174 | #define BTTV_BOARD_DVICO_FUSIONHDTV_2 0x94 | 174 | #define BTTV_BOARD_DVICO_FUSIONHDTV_2 0x94 |
175 | #define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95 | ||
176 | |||
175 | 177 | ||
176 | /* more card-specific defines */ | 178 | /* more card-specific defines */ |
177 | #define PT2254_L_CHANNEL 0x10 | 179 | #define PT2254_L_CHANNEL 0x10 |
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 5b25faca1504..0b92c35a8435 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h | |||
@@ -41,7 +41,7 @@ | |||
41 | #include <media/v4l2-common.h> | 41 | #include <media/v4l2-common.h> |
42 | 42 | ||
43 | #include <linux/device.h> | 43 | #include <linux/device.h> |
44 | #include <media/video-buf.h> | 44 | #include <media/videobuf-dma-sg.h> |
45 | #include <media/tuner.h> | 45 | #include <media/tuner.h> |
46 | #include <media/tveeprom.h> | 46 | #include <media/tveeprom.h> |
47 | #include <media/ir-common.h> | 47 | #include <media/ir-common.h> |
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c index b4aca7249276..ce0840ccd594 100644 --- a/drivers/media/video/btcx-risc.c +++ b/drivers/media/video/btcx-risc.c | |||
@@ -23,7 +23,6 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/init.h> | 26 | #include <linux/init.h> |
28 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
29 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 7d47cbe6ad25..7f7e3d3398d0 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c | |||
@@ -104,6 +104,17 @@ static inline void write_lpdata(struct qcam_device *q, int d) | |||
104 | 104 | ||
105 | static inline void write_lpcontrol(struct qcam_device *q, int d) | 105 | static inline void write_lpcontrol(struct qcam_device *q, int d) |
106 | { | 106 | { |
107 | if (d & 0x20) { | ||
108 | /* Set bidirectional mode to reverse (data in) */ | ||
109 | parport_data_reverse(q->pport); | ||
110 | } else { | ||
111 | /* Set bidirectional mode to forward (data out) */ | ||
112 | parport_data_forward(q->pport); | ||
113 | } | ||
114 | |||
115 | /* Now issue the regular port command, but strip out the | ||
116 | * direction flag */ | ||
117 | d &= ~0x20; | ||
107 | parport_write_control(q->pport, d); | 118 | parport_write_control(q->pport, d); |
108 | } | 119 | } |
109 | 120 | ||
@@ -344,10 +355,13 @@ static int qc_detect(struct qcam_device *q) | |||
344 | /* Be (even more) liberal in what you accept... */ | 355 | /* Be (even more) liberal in what you accept... */ |
345 | 356 | ||
346 | /* if (count > 30 && count < 200) */ | 357 | /* if (count > 30 && count < 200) */ |
347 | if (count > 20 && count < 300) | 358 | if (count > 20 && count < 400) { |
348 | return 1; /* found */ | 359 | return 1; /* found */ |
349 | else | 360 | } else { |
361 | printk(KERN_ERR "No Quickcam found on port %s\n", | ||
362 | q->pport->name); | ||
350 | return 0; /* not found */ | 363 | return 0; /* not found */ |
364 | } | ||
351 | } | 365 | } |
352 | 366 | ||
353 | 367 | ||
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index ef5361824f87..b63cab336920 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c | |||
@@ -14,7 +14,6 @@ | |||
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/moduleparam.h> | ||
18 | #include <linux/init.h> | 17 | #include <linux/init.h> |
19 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
20 | #include <linux/pci.h> | 19 | #include <linux/pci.h> |
@@ -63,13 +62,13 @@ MODULE_SUPPORTED_DEVICE("Video"); | |||
63 | */ | 62 | */ |
64 | 63 | ||
65 | #define MAX_DMA_BUFS 3 | 64 | #define MAX_DMA_BUFS 3 |
66 | static int alloc_bufs_at_load = 0; | 65 | static int alloc_bufs_at_read = 0; |
67 | module_param(alloc_bufs_at_load, bool, 0444); | 66 | module_param(alloc_bufs_at_read, bool, 0444); |
68 | MODULE_PARM_DESC(alloc_bufs_at_load, | 67 | MODULE_PARM_DESC(alloc_bufs_at_read, |
69 | "Non-zero value causes DMA buffers to be allocated at module " | 68 | "Non-zero value causes DMA buffers to be allocated when the " |
70 | "load time. This increases the chances of successfully getting " | 69 | "video capture device is read, rather than at module load " |
71 | "those buffers, but at the cost of nailing down the memory from " | 70 | "time. This saves memory, but decreases the chances of " |
72 | "the outset."); | 71 | "successfully getting those buffers."); |
73 | 72 | ||
74 | static int n_dma_bufs = 3; | 73 | static int n_dma_bufs = 3; |
75 | module_param(n_dma_bufs, uint, 0644); | 74 | module_param(n_dma_bufs, uint, 0644); |
@@ -1198,7 +1197,7 @@ static int cafe_setup_siobuf(struct cafe_camera *cam, int index) | |||
1198 | buf->v4lbuf.field = V4L2_FIELD_NONE; | 1197 | buf->v4lbuf.field = V4L2_FIELD_NONE; |
1199 | buf->v4lbuf.memory = V4L2_MEMORY_MMAP; | 1198 | buf->v4lbuf.memory = V4L2_MEMORY_MMAP; |
1200 | /* | 1199 | /* |
1201 | * Offset: must be 32-bit even on a 64-bit system. video-buf | 1200 | * Offset: must be 32-bit even on a 64-bit system. videobuf-dma-sg |
1202 | * just uses the length times the index, but the spec warns | 1201 | * just uses the length times the index, but the spec warns |
1203 | * against doing just that - vma merging problems. So we | 1202 | * against doing just that - vma merging problems. So we |
1204 | * leave a gap between each pair of buffers. | 1203 | * leave a gap between each pair of buffers. |
@@ -1503,7 +1502,7 @@ static int cafe_v4l_release(struct inode *inode, struct file *filp) | |||
1503 | } | 1502 | } |
1504 | if (cam->users == 0) { | 1503 | if (cam->users == 0) { |
1505 | cafe_ctlr_power_down(cam); | 1504 | cafe_ctlr_power_down(cam); |
1506 | if (! alloc_bufs_at_load) | 1505 | if (alloc_bufs_at_read) |
1507 | cafe_free_dma_bufs(cam); | 1506 | cafe_free_dma_bufs(cam); |
1508 | } | 1507 | } |
1509 | mutex_unlock(&cam->s_mutex); | 1508 | mutex_unlock(&cam->s_mutex); |
@@ -2162,7 +2161,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
2162 | /* | 2161 | /* |
2163 | * If so requested, try to get our DMA buffers now. | 2162 | * If so requested, try to get our DMA buffers now. |
2164 | */ | 2163 | */ |
2165 | if (alloc_bufs_at_load) { | 2164 | if (!alloc_bufs_at_read) { |
2166 | if (cafe_alloc_dma_bufs(cam, 1)) | 2165 | if (cafe_alloc_dma_bufs(cam, 1)) |
2167 | cam_warn(cam, "Unable to alloc DMA buffers at load" | 2166 | cam_warn(cam, "Unable to alloc DMA buffers at load" |
2168 | " will try again later."); | 2167 | " will try again later."); |
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c index f065ad12cc61..cefd1381e8de 100644 --- a/drivers/media/video/compat_ioctl32.c +++ b/drivers/media/video/compat_ioctl32.c | |||
@@ -848,6 +848,8 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) | |||
848 | case VIDIOCSFREQ32: | 848 | case VIDIOCSFREQ32: |
849 | case VIDIOCGAUDIO: | 849 | case VIDIOCGAUDIO: |
850 | case VIDIOCSAUDIO: | 850 | case VIDIOCSAUDIO: |
851 | case VIDIOCGVBIFMT: | ||
852 | case VIDIOCSVBIFMT: | ||
851 | #endif | 853 | #endif |
852 | case VIDIOC_QUERYCAP: | 854 | case VIDIOC_QUERYCAP: |
853 | case VIDIOC_ENUM_FMT: | 855 | case VIDIOC_ENUM_FMT: |
@@ -874,7 +876,10 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) | |||
874 | case VIDIOC_ENUMINPUT: | 876 | case VIDIOC_ENUMINPUT: |
875 | case VIDIOC_ENUMINPUT32: | 877 | case VIDIOC_ENUMINPUT32: |
876 | case VIDIOC_G_CTRL: | 878 | case VIDIOC_G_CTRL: |
879 | case VIDIOC_S_CTRL: | ||
877 | case VIDIOC_S_CTRL32: | 880 | case VIDIOC_S_CTRL32: |
881 | case VIDIOC_S_FREQUENCY: | ||
882 | case VIDIOC_G_FREQUENCY: | ||
878 | case VIDIOC_QUERYCTRL: | 883 | case VIDIOC_QUERYCTRL: |
879 | case VIDIOC_G_INPUT32: | 884 | case VIDIOC_G_INPUT32: |
880 | case VIDIOC_S_INPUT32: | 885 | case VIDIOC_S_INPUT32: |
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 78c9699eafbb..a1d02e5ce0fd 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c | |||
@@ -28,7 +28,6 @@ | |||
28 | 28 | ||
29 | 29 | ||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/init.h> | 31 | #include <linux/init.h> |
33 | #include <linux/fs.h> | 32 | #include <linux/fs.h> |
34 | #include <linux/vmalloc.h> | 33 | #include <linux/vmalloc.h> |
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 92778cd1d735..e3aaba1e0e0a 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/sched.h> | 37 | #include <linux/sched.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
40 | #include <linux/moduleparam.h> | ||
41 | 40 | ||
42 | #include "cpia2.h" | 41 | #include "cpia2.h" |
43 | #include "cpia2dev.h" | 42 | #include "cpia2dev.h" |
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index d73c86aeeaac..62304255dcae 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c | |||
@@ -20,7 +20,6 @@ | |||
20 | 20 | ||
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/moduleparam.h> | ||
24 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
25 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
26 | #include <linux/init.h> | 25 | #include <linux/init.h> |
@@ -191,17 +190,21 @@ static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params, | |||
191 | 190 | ||
192 | /* Map the control ID to the correct field in the cx2341x_mpeg_params | 191 | /* Map the control ID to the correct field in the cx2341x_mpeg_params |
193 | struct. Return -EINVAL if the ID is unknown, else return 0. */ | 192 | struct. Return -EINVAL if the ID is unknown, else return 0. */ |
194 | static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, | 193 | static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy, |
195 | struct v4l2_ext_control *ctrl) | 194 | struct v4l2_ext_control *ctrl) |
196 | { | 195 | { |
197 | switch (ctrl->id) { | 196 | switch (ctrl->id) { |
198 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | 197 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: |
198 | if (busy) | ||
199 | return -EBUSY; | ||
199 | params->audio_sampling_freq = ctrl->value; | 200 | params->audio_sampling_freq = ctrl->value; |
200 | break; | 201 | break; |
201 | case V4L2_CID_MPEG_AUDIO_ENCODING: | 202 | case V4L2_CID_MPEG_AUDIO_ENCODING: |
202 | params->audio_encoding = ctrl->value; | 203 | params->audio_encoding = ctrl->value; |
203 | break; | 204 | break; |
204 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | 205 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: |
206 | if (busy) | ||
207 | return -EBUSY; | ||
205 | params->audio_l2_bitrate = ctrl->value; | 208 | params->audio_l2_bitrate = ctrl->value; |
206 | break; | 209 | break; |
207 | case V4L2_CID_MPEG_AUDIO_MODE: | 210 | case V4L2_CID_MPEG_AUDIO_MODE: |
@@ -246,6 +249,8 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, | |||
246 | params->video_gop_closure = ctrl->value; | 249 | params->video_gop_closure = ctrl->value; |
247 | break; | 250 | break; |
248 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | 251 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: |
252 | if (busy) | ||
253 | return -EBUSY; | ||
249 | /* MPEG-1 only allows CBR */ | 254 | /* MPEG-1 only allows CBR */ |
250 | if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 && | 255 | if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 && |
251 | ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) | 256 | ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) |
@@ -253,9 +258,13 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, | |||
253 | params->video_bitrate_mode = ctrl->value; | 258 | params->video_bitrate_mode = ctrl->value; |
254 | break; | 259 | break; |
255 | case V4L2_CID_MPEG_VIDEO_BITRATE: | 260 | case V4L2_CID_MPEG_VIDEO_BITRATE: |
261 | if (busy) | ||
262 | return -EBUSY; | ||
256 | params->video_bitrate = ctrl->value; | 263 | params->video_bitrate = ctrl->value; |
257 | break; | 264 | break; |
258 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | 265 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: |
266 | if (busy) | ||
267 | return -EBUSY; | ||
259 | params->video_bitrate_peak = ctrl->value; | 268 | params->video_bitrate_peak = ctrl->value; |
260 | break; | 269 | break; |
261 | case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: | 270 | case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: |
@@ -268,6 +277,8 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, | |||
268 | params->video_mute_yuv = ctrl->value; | 277 | params->video_mute_yuv = ctrl->value; |
269 | break; | 278 | break; |
270 | case V4L2_CID_MPEG_STREAM_TYPE: | 279 | case V4L2_CID_MPEG_STREAM_TYPE: |
280 | if (busy) | ||
281 | return -EBUSY; | ||
271 | params->stream_type = ctrl->value; | 282 | params->stream_type = ctrl->value; |
272 | params->video_encoding = | 283 | params->video_encoding = |
273 | (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS || | 284 | (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS || |
@@ -632,7 +643,7 @@ static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params) | |||
632 | (params->audio_crc << 14); | 643 | (params->audio_crc << 14); |
633 | } | 644 | } |
634 | 645 | ||
635 | int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, | 646 | int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy, |
636 | struct v4l2_ext_controls *ctrls, unsigned int cmd) | 647 | struct v4l2_ext_controls *ctrls, unsigned int cmd) |
637 | { | 648 | { |
638 | int err = 0; | 649 | int err = 0; |
@@ -664,7 +675,7 @@ int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, | |||
664 | err = v4l2_ctrl_check(ctrl, &qctrl, menu_items); | 675 | err = v4l2_ctrl_check(ctrl, &qctrl, menu_items); |
665 | if (err) | 676 | if (err) |
666 | break; | 677 | break; |
667 | err = cx2341x_set_ctrl(params, ctrl); | 678 | err = cx2341x_set_ctrl(params, busy, ctrl); |
668 | if (err) | 679 | if (err) |
669 | break; | 680 | break; |
670 | } | 681 | } |
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig new file mode 100644 index 000000000000..72004a07b2d5 --- /dev/null +++ b/drivers/media/video/cx23885/Kconfig | |||
@@ -0,0 +1,20 @@ | |||
1 | config VIDEO_CX23885 | ||
2 | tristate "Conexant cx23885 (2388x successor) support" | ||
3 | depends on DVB_CORE && VIDEO_DEV && PCI && I2C | ||
4 | select I2C_ALGOBIT | ||
5 | select FW_LOADER | ||
6 | select VIDEO_BTCX | ||
7 | select VIDEO_TUNER | ||
8 | select VIDEO_TVEEPROM | ||
9 | select VIDEO_IR | ||
10 | select VIDEOBUF_DVB | ||
11 | select DVB_TUNER_MT2131 if !DVB_FE_CUSTOMISE | ||
12 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE | ||
13 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
14 | ---help--- | ||
15 | This is a video4linux driver for Conexant 23885 based | ||
16 | TV cards. | ||
17 | |||
18 | To compile this driver as a module, choose M here: the | ||
19 | module will be called cx23885 | ||
20 | |||
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile new file mode 100644 index 000000000000..665067022d2a --- /dev/null +++ b/drivers/media/video/cx23885/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | cx23885-objs := cx23885-cards.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o | ||
2 | |||
3 | obj-$(CONFIG_VIDEO_CX23885) += cx23885.o | ||
4 | |||
5 | EXTRA_CFLAGS += -Idrivers/media/video | ||
6 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | ||
7 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | ||
8 | |||
9 | EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) | ||
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c new file mode 100644 index 000000000000..b9012acabb2f --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-cards.c | |||
@@ -0,0 +1,280 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885 PCIe bridge | ||
3 | * | ||
4 | * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/delay.h> | ||
26 | |||
27 | #include "cx23885.h" | ||
28 | |||
29 | /* ------------------------------------------------------------------ */ | ||
30 | /* board config info */ | ||
31 | |||
32 | struct cx23885_board cx23885_boards[] = { | ||
33 | [CX23885_BOARD_UNKNOWN] = { | ||
34 | .name = "UNKNOWN/GENERIC", | ||
35 | .input = {{ | ||
36 | .type = CX23885_VMUX_COMPOSITE1, | ||
37 | .vmux = 0, | ||
38 | },{ | ||
39 | .type = CX23885_VMUX_COMPOSITE2, | ||
40 | .vmux = 1, | ||
41 | },{ | ||
42 | .type = CX23885_VMUX_COMPOSITE3, | ||
43 | .vmux = 2, | ||
44 | },{ | ||
45 | .type = CX23885_VMUX_COMPOSITE4, | ||
46 | .vmux = 3, | ||
47 | }}, | ||
48 | }, | ||
49 | [CX23885_BOARD_HAUPPAUGE_HVR1800lp] = { | ||
50 | .name = "Hauppauge WinTV-HVR1800lp", | ||
51 | .portc = CX23885_MPEG_DVB, | ||
52 | .input = {{ | ||
53 | .type = CX23885_VMUX_TELEVISION, | ||
54 | .vmux = 0, | ||
55 | .gpio0 = 0xff00, | ||
56 | },{ | ||
57 | .type = CX23885_VMUX_DEBUG, | ||
58 | .vmux = 0, | ||
59 | .gpio0 = 0xff01, | ||
60 | },{ | ||
61 | .type = CX23885_VMUX_COMPOSITE1, | ||
62 | .vmux = 1, | ||
63 | .gpio0 = 0xff02, | ||
64 | },{ | ||
65 | .type = CX23885_VMUX_SVIDEO, | ||
66 | .vmux = 2, | ||
67 | .gpio0 = 0xff02, | ||
68 | }}, | ||
69 | }, | ||
70 | [CX23885_BOARD_HAUPPAUGE_HVR1800] = { | ||
71 | .name = "Hauppauge WinTV-HVR1800", | ||
72 | .portc = CX23885_MPEG_DVB, | ||
73 | .input = {{ | ||
74 | .type = CX23885_VMUX_TELEVISION, | ||
75 | .vmux = 0, | ||
76 | .gpio0 = 0xff00, | ||
77 | },{ | ||
78 | .type = CX23885_VMUX_DEBUG, | ||
79 | .vmux = 0, | ||
80 | .gpio0 = 0xff01, | ||
81 | },{ | ||
82 | .type = CX23885_VMUX_COMPOSITE1, | ||
83 | .vmux = 1, | ||
84 | .gpio0 = 0xff02, | ||
85 | },{ | ||
86 | .type = CX23885_VMUX_SVIDEO, | ||
87 | .vmux = 2, | ||
88 | .gpio0 = 0xff02, | ||
89 | }}, | ||
90 | }, | ||
91 | [CX23885_BOARD_HAUPPAUGE_HVR1250] = { | ||
92 | .name = "Hauppauge WinTV-HVR1250", | ||
93 | .portc = CX23885_MPEG_DVB, | ||
94 | .input = {{ | ||
95 | .type = CX23885_VMUX_TELEVISION, | ||
96 | .vmux = 0, | ||
97 | .gpio0 = 0xff00, | ||
98 | },{ | ||
99 | .type = CX23885_VMUX_DEBUG, | ||
100 | .vmux = 0, | ||
101 | .gpio0 = 0xff01, | ||
102 | },{ | ||
103 | .type = CX23885_VMUX_COMPOSITE1, | ||
104 | .vmux = 1, | ||
105 | .gpio0 = 0xff02, | ||
106 | },{ | ||
107 | .type = CX23885_VMUX_SVIDEO, | ||
108 | .vmux = 2, | ||
109 | .gpio0 = 0xff02, | ||
110 | }}, | ||
111 | }, | ||
112 | [CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP] = { | ||
113 | .name = "DViCO FusionHDTV5 Express", | ||
114 | .portb = CX23885_MPEG_DVB, | ||
115 | }, | ||
116 | }; | ||
117 | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); | ||
118 | |||
119 | /* ------------------------------------------------------------------ */ | ||
120 | /* PCI subsystem IDs */ | ||
121 | |||
122 | struct cx23885_subid cx23885_subids[] = { | ||
123 | { | ||
124 | .subvendor = 0x0070, | ||
125 | .subdevice = 0x3400, | ||
126 | .card = CX23885_BOARD_UNKNOWN, | ||
127 | },{ | ||
128 | .subvendor = 0x0070, | ||
129 | .subdevice = 0x7600, | ||
130 | .card = CX23885_BOARD_HAUPPAUGE_HVR1800lp, | ||
131 | },{ | ||
132 | .subvendor = 0x0070, | ||
133 | .subdevice = 0x7800, | ||
134 | .card = CX23885_BOARD_HAUPPAUGE_HVR1800, | ||
135 | },{ | ||
136 | .subvendor = 0x0070, | ||
137 | .subdevice = 0x7801, | ||
138 | .card = CX23885_BOARD_HAUPPAUGE_HVR1800, | ||
139 | },{ | ||
140 | .subvendor = 0x0070, | ||
141 | .subdevice = 0x7911, | ||
142 | .card = CX23885_BOARD_HAUPPAUGE_HVR1250, | ||
143 | },{ | ||
144 | .subvendor = 0x18ac, | ||
145 | .subdevice = 0xd500, | ||
146 | .card = CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP, | ||
147 | }, | ||
148 | }; | ||
149 | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); | ||
150 | |||
151 | void cx23885_card_list(struct cx23885_dev *dev) | ||
152 | { | ||
153 | int i; | ||
154 | |||
155 | if (0 == dev->pci->subsystem_vendor && | ||
156 | 0 == dev->pci->subsystem_device) { | ||
157 | printk("%s: Your board has no valid PCIe Subsystem ID and thus can't\n" | ||
158 | "%s: be autodetected. Please pass card=<n> insmod option to\n" | ||
159 | "%s: workaround that. Redirect complaints to the vendor of\n" | ||
160 | "%s: the TV card. Best regards,\n" | ||
161 | "%s: -- tux\n", | ||
162 | dev->name, dev->name, dev->name, dev->name, dev->name); | ||
163 | } else { | ||
164 | printk("%s: Your board isn't known (yet) to the driver. You can\n" | ||
165 | "%s: try to pick one of the existing card configs via\n" | ||
166 | "%s: card=<n> insmod option. Updating to the latest\n" | ||
167 | "%s: version might help as well.\n", | ||
168 | dev->name, dev->name, dev->name, dev->name); | ||
169 | } | ||
170 | printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n", | ||
171 | dev->name); | ||
172 | for (i = 0; i < cx23885_bcount; i++) | ||
173 | printk("%s: card=%d -> %s\n", | ||
174 | dev->name, i, cx23885_boards[i].name); | ||
175 | } | ||
176 | |||
177 | static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) | ||
178 | { | ||
179 | struct tveeprom tv; | ||
180 | |||
181 | tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv, eeprom_data); | ||
182 | |||
183 | /* Make sure we support the board model */ | ||
184 | switch (tv.model) | ||
185 | { | ||
186 | case 76601: /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual channel ATSC and MPEG2 HW Encoder */ | ||
187 | case 77001: /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC and Basic analog */ | ||
188 | case 78501: /* WinTV-HVR1800 (PCIe, Retail, IR, Dual channel ATSC and MPEG2 HW Encoder */ | ||
189 | case 78521: /* WinTV-HVR1800 (PCIe, Retail, IR, Dual channel ATSC and MPEG2 HW Encoder */ | ||
190 | break; | ||
191 | default: | ||
192 | printk("%s: warning: unknown hauppauge model #%d\n", dev->name, tv.model); | ||
193 | break; | ||
194 | } | ||
195 | |||
196 | printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n", | ||
197 | dev->name, tv.model); | ||
198 | } | ||
199 | |||
200 | void cx23885_gpio_setup(struct cx23885_dev *dev) | ||
201 | { | ||
202 | switch(dev->board) { | ||
203 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | ||
204 | /* GPIO-0 cx24227 demodulator reset */ | ||
205 | cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */ | ||
206 | break; | ||
207 | case CX23885_BOARD_HAUPPAUGE_HVR1800: | ||
208 | /* GPIO-0 656_CLK */ | ||
209 | /* GPIO-1 656_D0 */ | ||
210 | /* GPIO-2 8295A Reset */ | ||
211 | /* GPIO-3-10 cx23417 data0-7 */ | ||
212 | /* GPIO-11-14 cx23417 addr0-3 */ | ||
213 | /* GPIO-15-18 cx23417 READY, CS, RD, WR */ | ||
214 | /* GPIO-19 IR_RX */ | ||
215 | // FIXME: Analog requires the tuner is brought out of reset | ||
216 | break; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | int cx23885_ir_init(struct cx23885_dev *dev) | ||
221 | { | ||
222 | switch (dev->board) { | ||
223 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | ||
224 | case CX23885_BOARD_HAUPPAUGE_HVR1800: | ||
225 | /* FIXME: Implement me */ | ||
226 | break; | ||
227 | } | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | void cx23885_card_setup(struct cx23885_dev *dev) | ||
233 | { | ||
234 | struct cx23885_tsport *ts1 = &dev->ts1; | ||
235 | struct cx23885_tsport *ts2 = &dev->ts2; | ||
236 | |||
237 | static u8 eeprom[256]; | ||
238 | |||
239 | if (dev->i2c_bus[0].i2c_rc == 0) { | ||
240 | dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; | ||
241 | tveeprom_read(&dev->i2c_bus[0].i2c_client, | ||
242 | eeprom, sizeof(eeprom)); | ||
243 | } | ||
244 | |||
245 | switch (dev->board) { | ||
246 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | ||
247 | case CX23885_BOARD_HAUPPAUGE_HVR1800: | ||
248 | case CX23885_BOARD_HAUPPAUGE_HVR1800lp: | ||
249 | if (dev->i2c_bus[0].i2c_rc == 0) | ||
250 | hauppauge_eeprom(dev, eeprom+0x80); | ||
251 | break; | ||
252 | } | ||
253 | |||
254 | switch (dev->board) { | ||
255 | case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP: | ||
256 | ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ | ||
257 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | ||
258 | ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | ||
259 | break; | ||
260 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | ||
261 | case CX23885_BOARD_HAUPPAUGE_HVR1800: | ||
262 | case CX23885_BOARD_HAUPPAUGE_HVR1800lp: | ||
263 | default: | ||
264 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ | ||
265 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | ||
266 | ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | ||
267 | } | ||
268 | |||
269 | } | ||
270 | |||
271 | /* ------------------------------------------------------------------ */ | ||
272 | |||
273 | EXPORT_SYMBOL(cx23885_boards); | ||
274 | |||
275 | /* | ||
276 | * Local variables: | ||
277 | * c-basic-offset: 8 | ||
278 | * End: | ||
279 | * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off | ||
280 | */ | ||
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c new file mode 100644 index 000000000000..af16505bd2e0 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-core.c | |||
@@ -0,0 +1,1530 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885 PCIe bridge | ||
3 | * | ||
4 | * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/kmod.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <asm/div64.h> | ||
32 | |||
33 | #include "cx23885.h" | ||
34 | |||
35 | MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); | ||
36 | MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>"); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | |||
39 | static unsigned int debug = 0; | ||
40 | module_param(debug,int,0644); | ||
41 | MODULE_PARM_DESC(debug,"enable debug messages"); | ||
42 | |||
43 | static unsigned int card[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET }; | ||
44 | module_param_array(card, int, NULL, 0444); | ||
45 | MODULE_PARM_DESC(card,"card type"); | ||
46 | |||
47 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | ||
48 | printk(KERN_DEBUG "%s/0: " fmt, dev->name , ## arg) | ||
49 | |||
50 | static unsigned int cx23885_devcount; | ||
51 | |||
52 | static DEFINE_MUTEX(devlist); | ||
53 | static LIST_HEAD(cx23885_devlist); | ||
54 | |||
55 | #define NO_SYNC_LINE (-1U) | ||
56 | |||
57 | /* | ||
58 | * CX23885 Assumptions | ||
59 | * 1 line = 16 bytes of CDT | ||
60 | * cmds size = 80 | ||
61 | * cdt size = 16 * linesize | ||
62 | * iqsize = 64 | ||
63 | * maxlines = 6 | ||
64 | * | ||
65 | * Address Space: | ||
66 | * 0x00000000 0x00008fff FIFO clusters | ||
67 | * 0x00010000 0x000104af Channel Management Data Structures | ||
68 | * 0x000104b0 0x000104ff Free | ||
69 | * 0x00010500 0x000108bf 15 channels * iqsize | ||
70 | * 0x000108c0 0x000108ff Free | ||
71 | * 0x00010900 0x00010e9f IQ's + Cluster Descriptor Tables | ||
72 | * 15 channels * (iqsize + (maxlines * linesize)) | ||
73 | * 0x00010ea0 0x00010xxx Free | ||
74 | */ | ||
75 | |||
76 | struct sram_channel cx23885_sram_channels[] = { | ||
77 | [SRAM_CH01] = { | ||
78 | .name = "test ch1", | ||
79 | .cmds_start = 0x10000, | ||
80 | .ctrl_start = 0x10500, | ||
81 | .cdt = 0x10900, | ||
82 | .fifo_start = 0x3000, | ||
83 | .fifo_size = 0x1000, | ||
84 | .ptr1_reg = DMA1_PTR1, | ||
85 | .ptr2_reg = DMA1_PTR2, | ||
86 | .cnt1_reg = DMA1_CNT1, | ||
87 | .cnt2_reg = DMA1_CNT2, | ||
88 | .jumponly = 1, | ||
89 | }, | ||
90 | [SRAM_CH02] = { | ||
91 | .name = "ch2", | ||
92 | .cmds_start = 0x0, | ||
93 | .ctrl_start = 0x0, | ||
94 | .cdt = 0x0, | ||
95 | .fifo_start = 0x0, | ||
96 | .fifo_size = 0x0, | ||
97 | .ptr1_reg = DMA2_PTR1, | ||
98 | .ptr2_reg = DMA2_PTR2, | ||
99 | .cnt1_reg = DMA2_CNT1, | ||
100 | .cnt2_reg = DMA2_CNT2, | ||
101 | }, | ||
102 | [SRAM_CH03] = { | ||
103 | .name = "TS1 B", | ||
104 | .cmds_start = 0x100A0, | ||
105 | .ctrl_start = 0x10780, | ||
106 | .cdt = 0x10400, | ||
107 | .fifo_start = 0x5000, | ||
108 | .fifo_size = 0x1000, | ||
109 | .ptr1_reg = DMA3_PTR1, | ||
110 | .ptr2_reg = DMA3_PTR2, | ||
111 | .cnt1_reg = DMA3_CNT1, | ||
112 | .cnt2_reg = DMA3_CNT2, | ||
113 | }, | ||
114 | [SRAM_CH04] = { | ||
115 | .name = "ch4", | ||
116 | .cmds_start = 0x0, | ||
117 | .ctrl_start = 0x0, | ||
118 | .cdt = 0x0, | ||
119 | .fifo_start = 0x0, | ||
120 | .fifo_size = 0x0, | ||
121 | .ptr1_reg = DMA4_PTR1, | ||
122 | .ptr2_reg = DMA4_PTR2, | ||
123 | .cnt1_reg = DMA4_CNT1, | ||
124 | .cnt2_reg = DMA4_CNT2, | ||
125 | }, | ||
126 | [SRAM_CH05] = { | ||
127 | .name = "ch5", | ||
128 | .cmds_start = 0x0, | ||
129 | .ctrl_start = 0x0, | ||
130 | .cdt = 0x0, | ||
131 | .fifo_start = 0x0, | ||
132 | .fifo_size = 0x0, | ||
133 | .ptr1_reg = DMA5_PTR1, | ||
134 | .ptr2_reg = DMA5_PTR2, | ||
135 | .cnt1_reg = DMA5_CNT1, | ||
136 | .cnt2_reg = DMA5_CNT2, | ||
137 | }, | ||
138 | [SRAM_CH06] = { | ||
139 | .name = "TS2 C", | ||
140 | .cmds_start = 0x10140, | ||
141 | .ctrl_start = 0x10680, | ||
142 | .cdt = 0x10480, | ||
143 | .fifo_start = 0x6000, | ||
144 | .fifo_size = 0x1000, | ||
145 | .ptr1_reg = DMA5_PTR1, | ||
146 | .ptr2_reg = DMA5_PTR2, | ||
147 | .cnt1_reg = DMA5_CNT1, | ||
148 | .cnt2_reg = DMA5_CNT2, | ||
149 | }, | ||
150 | [SRAM_CH07] = { | ||
151 | .name = "ch7", | ||
152 | .cmds_start = 0x0, | ||
153 | .ctrl_start = 0x0, | ||
154 | .cdt = 0x0, | ||
155 | .fifo_start = 0x0, | ||
156 | .fifo_size = 0x0, | ||
157 | .ptr1_reg = DMA6_PTR1, | ||
158 | .ptr2_reg = DMA6_PTR2, | ||
159 | .cnt1_reg = DMA6_CNT1, | ||
160 | .cnt2_reg = DMA6_CNT2, | ||
161 | }, | ||
162 | [SRAM_CH08] = { | ||
163 | .name = "ch8", | ||
164 | .cmds_start = 0x0, | ||
165 | .ctrl_start = 0x0, | ||
166 | .cdt = 0x0, | ||
167 | .fifo_start = 0x0, | ||
168 | .fifo_size = 0x0, | ||
169 | .ptr1_reg = DMA7_PTR1, | ||
170 | .ptr2_reg = DMA7_PTR2, | ||
171 | .cnt1_reg = DMA7_CNT1, | ||
172 | .cnt2_reg = DMA7_CNT2, | ||
173 | }, | ||
174 | [SRAM_CH09] = { | ||
175 | .name = "ch9", | ||
176 | .cmds_start = 0x0, | ||
177 | .ctrl_start = 0x0, | ||
178 | .cdt = 0x0, | ||
179 | .fifo_start = 0x0, | ||
180 | .fifo_size = 0x0, | ||
181 | .ptr1_reg = DMA8_PTR1, | ||
182 | .ptr2_reg = DMA8_PTR2, | ||
183 | .cnt1_reg = DMA8_CNT1, | ||
184 | .cnt2_reg = DMA8_CNT2, | ||
185 | }, | ||
186 | }; | ||
187 | |||
188 | /* FIXME, these allocations will change when | ||
189 | * analog arrives. The be reviewed. | ||
190 | * CX23887 Assumptions | ||
191 | * 1 line = 16 bytes of CDT | ||
192 | * cmds size = 80 | ||
193 | * cdt size = 16 * linesize | ||
194 | * iqsize = 64 | ||
195 | * maxlines = 6 | ||
196 | * | ||
197 | * Address Space: | ||
198 | * 0x00000000 0x00008fff FIFO clusters | ||
199 | * 0x00010000 0x000104af Channel Management Data Structures | ||
200 | * 0x000104b0 0x000104ff Free | ||
201 | * 0x00010500 0x000108bf 15 channels * iqsize | ||
202 | * 0x000108c0 0x000108ff Free | ||
203 | * 0x00010900 0x00010e9f IQ's + Cluster Descriptor Tables | ||
204 | * 15 channels * (iqsize + (maxlines * linesize)) | ||
205 | * 0x00010ea0 0x00010xxx Free | ||
206 | */ | ||
207 | |||
208 | struct sram_channel cx23887_sram_channels[] = { | ||
209 | [SRAM_CH01] = { | ||
210 | .name = "test ch1", | ||
211 | .cmds_start = 0x0, | ||
212 | .ctrl_start = 0x0, | ||
213 | .cdt = 0x0, | ||
214 | .fifo_start = 0x0, | ||
215 | .fifo_size = 0x0, | ||
216 | .ptr1_reg = DMA1_PTR1, | ||
217 | .ptr2_reg = DMA1_PTR2, | ||
218 | .cnt1_reg = DMA1_CNT1, | ||
219 | .cnt2_reg = DMA1_CNT2, | ||
220 | }, | ||
221 | [SRAM_CH02] = { | ||
222 | .name = "ch2", | ||
223 | .cmds_start = 0x0, | ||
224 | .ctrl_start = 0x0, | ||
225 | .cdt = 0x0, | ||
226 | .fifo_start = 0x0, | ||
227 | .fifo_size = 0x0, | ||
228 | .ptr1_reg = DMA2_PTR1, | ||
229 | .ptr2_reg = DMA2_PTR2, | ||
230 | .cnt1_reg = DMA2_CNT1, | ||
231 | .cnt2_reg = DMA2_CNT2, | ||
232 | }, | ||
233 | [SRAM_CH03] = { | ||
234 | .name = "ch3", | ||
235 | .cmds_start = 0x0, | ||
236 | .ctrl_start = 0x0, | ||
237 | .cdt = 0x0, | ||
238 | .fifo_start = 0x0, | ||
239 | .fifo_size = 0x0, | ||
240 | .ptr1_reg = DMA3_PTR1, | ||
241 | .ptr2_reg = DMA3_PTR2, | ||
242 | .cnt1_reg = DMA3_CNT1, | ||
243 | .cnt2_reg = DMA3_CNT2, | ||
244 | }, | ||
245 | [SRAM_CH04] = { | ||
246 | .name = "ch4", | ||
247 | .cmds_start = 0x0, | ||
248 | .ctrl_start = 0x0, | ||
249 | .cdt = 0x0, | ||
250 | .fifo_start = 0x0, | ||
251 | .fifo_size = 0x0, | ||
252 | .ptr1_reg = DMA4_PTR1, | ||
253 | .ptr2_reg = DMA4_PTR2, | ||
254 | .cnt1_reg = DMA4_CNT1, | ||
255 | .cnt2_reg = DMA4_CNT2, | ||
256 | }, | ||
257 | [SRAM_CH05] = { | ||
258 | .name = "ch5", | ||
259 | .cmds_start = 0x0, | ||
260 | .ctrl_start = 0x0, | ||
261 | .cdt = 0x0, | ||
262 | .fifo_start = 0x0, | ||
263 | .fifo_size = 0x0, | ||
264 | .ptr1_reg = DMA5_PTR1, | ||
265 | .ptr2_reg = DMA5_PTR2, | ||
266 | .cnt1_reg = DMA5_CNT1, | ||
267 | .cnt2_reg = DMA5_CNT2, | ||
268 | }, | ||
269 | [SRAM_CH06] = { | ||
270 | .name = "TS2 C", | ||
271 | .cmds_start = 0x10140, | ||
272 | .ctrl_start = 0x10680, | ||
273 | .cdt = 0x108d0, | ||
274 | .fifo_start = 0x6000, | ||
275 | .fifo_size = 0x1000, | ||
276 | .ptr1_reg = DMA5_PTR1, | ||
277 | .ptr2_reg = DMA5_PTR2, | ||
278 | .cnt1_reg = DMA5_CNT1, | ||
279 | .cnt2_reg = DMA5_CNT2, | ||
280 | }, | ||
281 | [SRAM_CH07] = { | ||
282 | .name = "ch7", | ||
283 | .cmds_start = 0x0, | ||
284 | .ctrl_start = 0x0, | ||
285 | .cdt = 0x0, | ||
286 | .fifo_start = 0x0, | ||
287 | .fifo_size = 0x0, | ||
288 | .ptr1_reg = DMA6_PTR1, | ||
289 | .ptr2_reg = DMA6_PTR2, | ||
290 | .cnt1_reg = DMA6_CNT1, | ||
291 | .cnt2_reg = DMA6_CNT2, | ||
292 | }, | ||
293 | [SRAM_CH08] = { | ||
294 | .name = "ch8", | ||
295 | .cmds_start = 0x0, | ||
296 | .ctrl_start = 0x0, | ||
297 | .cdt = 0x0, | ||
298 | .fifo_start = 0x0, | ||
299 | .fifo_size = 0x0, | ||
300 | .ptr1_reg = DMA7_PTR1, | ||
301 | .ptr2_reg = DMA7_PTR2, | ||
302 | .cnt1_reg = DMA7_CNT1, | ||
303 | .cnt2_reg = DMA7_CNT2, | ||
304 | }, | ||
305 | [SRAM_CH09] = { | ||
306 | .name = "ch9", | ||
307 | .cmds_start = 0x0, | ||
308 | .ctrl_start = 0x0, | ||
309 | .cdt = 0x0, | ||
310 | .fifo_start = 0x0, | ||
311 | .fifo_size = 0x0, | ||
312 | .ptr1_reg = DMA8_PTR1, | ||
313 | .ptr2_reg = DMA8_PTR2, | ||
314 | .cnt1_reg = DMA8_CNT1, | ||
315 | .cnt2_reg = DMA8_CNT2, | ||
316 | }, | ||
317 | }; | ||
318 | |||
319 | static int cx23885_risc_decode(u32 risc) | ||
320 | { | ||
321 | static char *instr[16] = { | ||
322 | [ RISC_SYNC >> 28 ] = "sync", | ||
323 | [ RISC_WRITE >> 28 ] = "write", | ||
324 | [ RISC_WRITEC >> 28 ] = "writec", | ||
325 | [ RISC_READ >> 28 ] = "read", | ||
326 | [ RISC_READC >> 28 ] = "readc", | ||
327 | [ RISC_JUMP >> 28 ] = "jump", | ||
328 | [ RISC_SKIP >> 28 ] = "skip", | ||
329 | [ RISC_WRITERM >> 28 ] = "writerm", | ||
330 | [ RISC_WRITECM >> 28 ] = "writecm", | ||
331 | [ RISC_WRITECR >> 28 ] = "writecr", | ||
332 | }; | ||
333 | static int incr[16] = { | ||
334 | [ RISC_WRITE >> 28 ] = 3, | ||
335 | [ RISC_JUMP >> 28 ] = 3, | ||
336 | [ RISC_SKIP >> 28 ] = 1, | ||
337 | [ RISC_SYNC >> 28 ] = 1, | ||
338 | [ RISC_WRITERM >> 28 ] = 3, | ||
339 | [ RISC_WRITECM >> 28 ] = 3, | ||
340 | [ RISC_WRITECR >> 28 ] = 4, | ||
341 | }; | ||
342 | static char *bits[] = { | ||
343 | "12", "13", "14", "resync", | ||
344 | "cnt0", "cnt1", "18", "19", | ||
345 | "20", "21", "22", "23", | ||
346 | "irq1", "irq2", "eol", "sol", | ||
347 | }; | ||
348 | int i; | ||
349 | |||
350 | printk("0x%08x [ %s", risc, | ||
351 | instr[risc >> 28] ? instr[risc >> 28] : "INVALID"); | ||
352 | for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) | ||
353 | if (risc & (1 << (i + 12))) | ||
354 | printk(" %s", bits[i]); | ||
355 | printk(" count=%d ]\n", risc & 0xfff); | ||
356 | return incr[risc >> 28] ? incr[risc >> 28] : 1; | ||
357 | } | ||
358 | |||
359 | void cx23885_wakeup(struct cx23885_tsport *port, | ||
360 | struct cx23885_dmaqueue *q, u32 count) | ||
361 | { | ||
362 | struct cx23885_dev *dev = port->dev; | ||
363 | struct cx23885_buffer *buf; | ||
364 | int bc; | ||
365 | |||
366 | for (bc = 0;; bc++) { | ||
367 | if (list_empty(&q->active)) | ||
368 | break; | ||
369 | buf = list_entry(q->active.next, | ||
370 | struct cx23885_buffer, vb.queue); | ||
371 | |||
372 | /* count comes from the hw and is is 16bit wide -- | ||
373 | * this trick handles wrap-arounds correctly for | ||
374 | * up to 32767 buffers in flight... */ | ||
375 | if ((s16) (count - buf->count) < 0) | ||
376 | break; | ||
377 | |||
378 | do_gettimeofday(&buf->vb.ts); | ||
379 | dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i, | ||
380 | count, buf->count); | ||
381 | buf->vb.state = STATE_DONE; | ||
382 | list_del(&buf->vb.queue); | ||
383 | wake_up(&buf->vb.done); | ||
384 | } | ||
385 | if (list_empty(&q->active)) { | ||
386 | del_timer(&q->timeout); | ||
387 | } else { | ||
388 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
389 | } | ||
390 | if (bc != 1) | ||
391 | printk("%s: %d buffers handled (should be 1)\n", | ||
392 | __FUNCTION__, bc); | ||
393 | } | ||
394 | void cx23885_sram_channel_dump(struct cx23885_dev *dev, | ||
395 | struct sram_channel *ch); | ||
396 | |||
397 | int cx23885_sram_channel_setup(struct cx23885_dev *dev, | ||
398 | struct sram_channel *ch, | ||
399 | unsigned int bpl, u32 risc) | ||
400 | { | ||
401 | unsigned int i, lines; | ||
402 | u32 cdt; | ||
403 | |||
404 | if (ch->cmds_start == 0) | ||
405 | { | ||
406 | dprintk(1, "%s() Erasing channel [%s]\n", __FUNCTION__, | ||
407 | ch->name); | ||
408 | cx_write(ch->ptr1_reg, 0); | ||
409 | cx_write(ch->ptr2_reg, 0); | ||
410 | cx_write(ch->cnt2_reg, 0); | ||
411 | cx_write(ch->cnt1_reg, 0); | ||
412 | return 0; | ||
413 | } else { | ||
414 | dprintk(1, "%s() Configuring channel [%s]\n", __FUNCTION__, | ||
415 | ch->name); | ||
416 | } | ||
417 | |||
418 | bpl = (bpl + 7) & ~7; /* alignment */ | ||
419 | cdt = ch->cdt; | ||
420 | lines = ch->fifo_size / bpl; | ||
421 | if (lines > 6) | ||
422 | lines = 6; | ||
423 | BUG_ON(lines < 2); | ||
424 | |||
425 | cx_write(8 + 0, cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC) ); | ||
426 | cx_write(8 + 4, cpu_to_le32(8) ); | ||
427 | cx_write(8 + 8, cpu_to_le32(0) ); | ||
428 | |||
429 | /* write CDT */ | ||
430 | for (i = 0; i < lines; i++) { | ||
431 | dprintk(2, "%s() 0x%08x <- 0x%08x\n", __FUNCTION__, cdt + 16*i, | ||
432 | ch->fifo_start + bpl*i); | ||
433 | cx_write(cdt + 16*i, ch->fifo_start + bpl*i); | ||
434 | cx_write(cdt + 16*i + 4, 0); | ||
435 | cx_write(cdt + 16*i + 8, 0); | ||
436 | cx_write(cdt + 16*i + 12, 0); | ||
437 | } | ||
438 | |||
439 | /* write CMDS */ | ||
440 | if (ch->jumponly) | ||
441 | cx_write(ch->cmds_start + 0, 8); | ||
442 | else | ||
443 | cx_write(ch->cmds_start + 0, risc); | ||
444 | cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ | ||
445 | cx_write(ch->cmds_start + 8, cdt); | ||
446 | cx_write(ch->cmds_start + 12, (lines*16) >> 3); | ||
447 | cx_write(ch->cmds_start + 16, ch->ctrl_start); | ||
448 | if (ch->jumponly) | ||
449 | cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2) ); | ||
450 | else | ||
451 | cx_write(ch->cmds_start + 20, 64 >> 2); | ||
452 | for (i = 24; i < 80; i += 4) | ||
453 | cx_write(ch->cmds_start + i, 0); | ||
454 | |||
455 | /* fill registers */ | ||
456 | cx_write(ch->ptr1_reg, ch->fifo_start); | ||
457 | cx_write(ch->ptr2_reg, cdt); | ||
458 | cx_write(ch->cnt2_reg, (lines*16) >> 3); | ||
459 | cx_write(ch->cnt1_reg, (bpl >> 3) -1); | ||
460 | |||
461 | dprintk(2,"[bridge %d] sram setup %s: bpl=%d lines=%d\n", | ||
462 | dev->bridge, | ||
463 | ch->name, | ||
464 | bpl, | ||
465 | lines); | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | void cx23885_sram_channel_dump(struct cx23885_dev *dev, | ||
471 | struct sram_channel *ch) | ||
472 | { | ||
473 | static char *name[] = { | ||
474 | "init risc lo", | ||
475 | "init risc hi", | ||
476 | "cdt base", | ||
477 | "cdt size", | ||
478 | "iq base", | ||
479 | "iq size", | ||
480 | "risc pc lo", | ||
481 | "risc pc hi", | ||
482 | "iq wr ptr", | ||
483 | "iq rd ptr", | ||
484 | "cdt current", | ||
485 | "pci target lo", | ||
486 | "pci target hi", | ||
487 | "line / byte", | ||
488 | }; | ||
489 | u32 risc; | ||
490 | unsigned int i, j, n; | ||
491 | |||
492 | printk("%s: %s - dma channel status dump\n", | ||
493 | dev->name, ch->name); | ||
494 | for (i = 0; i < ARRAY_SIZE(name); i++) | ||
495 | printk("%s: cmds: %-15s: 0x%08x\n", | ||
496 | dev->name, name[i], | ||
497 | cx_read(ch->cmds_start + 4*i)); | ||
498 | |||
499 | for (i = 0; i < 4; i++) { | ||
500 | risc = cx_read(ch->cmds_start + 4 * (i + 14)); | ||
501 | printk("%s: risc%d: ", dev->name, i); | ||
502 | cx23885_risc_decode(risc); | ||
503 | } | ||
504 | for (i = 0; i < (64 >> 2); i += n) { | ||
505 | risc = cx_read(ch->ctrl_start + 4 * i); | ||
506 | /* No consideration for bits 63-32 */ | ||
507 | |||
508 | printk("%s: (0x%08x) iq %x: ", dev->name, | ||
509 | ch->ctrl_start + 4 * i, i); | ||
510 | n = cx23885_risc_decode(risc); | ||
511 | for (j = 1; j < n; j++) { | ||
512 | risc = cx_read(ch->ctrl_start + 4 * (i + j)); | ||
513 | printk("%s: iq %x: 0x%08x [ arg #%d ]\n", | ||
514 | dev->name, i+j, risc, j); | ||
515 | } | ||
516 | } | ||
517 | |||
518 | printk("%s: fifo: 0x%08x -> 0x%x\n", | ||
519 | dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size); | ||
520 | printk("%s: ctrl: 0x%08x -> 0x%x\n", | ||
521 | dev->name, ch->ctrl_start, ch->ctrl_start + 6*16); | ||
522 | printk("%s: ptr1_reg: 0x%08x\n", | ||
523 | dev->name, cx_read(ch->ptr1_reg)); | ||
524 | printk("%s: ptr2_reg: 0x%08x\n", | ||
525 | dev->name, cx_read(ch->ptr2_reg)); | ||
526 | printk("%s: cnt1_reg: 0x%08x\n", | ||
527 | dev->name, cx_read(ch->cnt1_reg)); | ||
528 | printk("%s: cnt2_reg: 0x%08x\n", | ||
529 | dev->name, cx_read(ch->cnt2_reg)); | ||
530 | } | ||
531 | |||
532 | void cx23885_risc_disasm(struct cx23885_tsport *port, | ||
533 | struct btcx_riscmem *risc) | ||
534 | { | ||
535 | struct cx23885_dev *dev = port->dev; | ||
536 | unsigned int i, j, n; | ||
537 | |||
538 | printk("%s: risc disasm: %p [dma=0x%08lx]\n", | ||
539 | dev->name, risc->cpu, (unsigned long)risc->dma); | ||
540 | for (i = 0; i < (risc->size >> 2); i += n) { | ||
541 | printk("%s: %04d: ", dev->name, i); | ||
542 | n = cx23885_risc_decode(risc->cpu[i]); | ||
543 | for (j = 1; j < n; j++) | ||
544 | printk("%s: %04d: 0x%08x [ arg #%d ]\n", | ||
545 | dev->name, i + j, risc->cpu[i + j], j); | ||
546 | if (risc->cpu[i] == RISC_JUMP) | ||
547 | break; | ||
548 | } | ||
549 | } | ||
550 | |||
551 | void cx23885_shutdown(struct cx23885_dev *dev) | ||
552 | { | ||
553 | /* disable RISC controller */ | ||
554 | cx_write(DEV_CNTRL2, 0); | ||
555 | |||
556 | /* Disable all IR activity */ | ||
557 | cx_write(IR_CNTRL_REG, 0); | ||
558 | |||
559 | /* Disable Video A/B activity */ | ||
560 | cx_write(VID_A_DMA_CTL, 0); | ||
561 | cx_write(VID_B_DMA_CTL, 0); | ||
562 | cx_write(VID_C_DMA_CTL, 0); | ||
563 | |||
564 | /* Disable Audio activity */ | ||
565 | cx_write(AUD_INT_DMA_CTL, 0); | ||
566 | cx_write(AUD_EXT_DMA_CTL, 0); | ||
567 | |||
568 | /* Disable Serial port */ | ||
569 | cx_write(UART_CTL, 0); | ||
570 | |||
571 | /* Disable Interrupts */ | ||
572 | cx_write(PCI_INT_MSK, 0); | ||
573 | cx_write(VID_A_INT_MSK, 0); | ||
574 | cx_write(VID_B_INT_MSK, 0); | ||
575 | cx_write(VID_C_INT_MSK, 0); | ||
576 | cx_write(AUDIO_INT_INT_MSK, 0); | ||
577 | cx_write(AUDIO_EXT_INT_MSK, 0); | ||
578 | |||
579 | } | ||
580 | |||
581 | void cx23885_reset(struct cx23885_dev *dev) | ||
582 | { | ||
583 | dprintk(1, "%s()\n", __FUNCTION__); | ||
584 | |||
585 | cx23885_shutdown(dev); | ||
586 | |||
587 | cx_write(PCI_INT_STAT, 0xffffffff); | ||
588 | cx_write(VID_A_INT_STAT, 0xffffffff); | ||
589 | cx_write(VID_B_INT_STAT, 0xffffffff); | ||
590 | cx_write(VID_C_INT_STAT, 0xffffffff); | ||
591 | cx_write(AUDIO_INT_INT_STAT, 0xffffffff); | ||
592 | cx_write(AUDIO_EXT_INT_STAT, 0xffffffff); | ||
593 | cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000); | ||
594 | |||
595 | mdelay(100); | ||
596 | |||
597 | cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH01 ], 188*4, 0); | ||
598 | cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH02 ], 128, 0); | ||
599 | cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH03 ], 188*4, 0); | ||
600 | cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH04 ], 128, 0); | ||
601 | cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH05 ], 128, 0); | ||
602 | cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH06 ], 188*4, 0); | ||
603 | cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH07 ], 128, 0); | ||
604 | cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH08 ], 128, 0); | ||
605 | cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH09 ], 128, 0); | ||
606 | |||
607 | cx23885_gpio_setup(dev); | ||
608 | } | ||
609 | |||
610 | |||
611 | static int cx23885_pci_quirks(struct cx23885_dev *dev) | ||
612 | { | ||
613 | dprintk(1, "%s()\n", __FUNCTION__); | ||
614 | |||
615 | /* The cx23885 bridge has a weird bug which causes NMI to be asserted | ||
616 | * when DMA begins if RDR_TLCTL0 bit4 is not cleared. It does not | ||
617 | * occur on the cx23887 bridge. | ||
618 | */ | ||
619 | if(dev->bridge == CX23885_BRIDGE_885) | ||
620 | cx_clear(RDR_TLCTL0, 1 << 4); | ||
621 | |||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static int get_resources(struct cx23885_dev *dev) | ||
626 | { | ||
627 | if (request_mem_region(pci_resource_start(dev->pci,0), | ||
628 | pci_resource_len(dev->pci,0), | ||
629 | dev->name)) | ||
630 | return 0; | ||
631 | |||
632 | printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n", | ||
633 | dev->name, (unsigned long long)pci_resource_start(dev->pci,0)); | ||
634 | |||
635 | return -EBUSY; | ||
636 | } | ||
637 | |||
638 | static void cx23885_timeout(unsigned long data); | ||
639 | int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | ||
640 | u32 reg, u32 mask, u32 value); | ||
641 | |||
642 | static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno) | ||
643 | { | ||
644 | dprintk(1, "%s(portno=%d)\n", __FUNCTION__, portno); | ||
645 | |||
646 | /* Transport bus init dma queue - Common settings */ | ||
647 | port->dma_ctl_val = 0x11; /* Enable RISC controller and Fifo */ | ||
648 | port->ts_int_msk_val = 0x1111; /* TS port bits for RISC */ | ||
649 | |||
650 | spin_lock_init(&port->slock); | ||
651 | port->dev = dev; | ||
652 | port->nr = portno; | ||
653 | |||
654 | INIT_LIST_HEAD(&port->mpegq.active); | ||
655 | INIT_LIST_HEAD(&port->mpegq.queued); | ||
656 | port->mpegq.timeout.function = cx23885_timeout; | ||
657 | port->mpegq.timeout.data = (unsigned long)port; | ||
658 | init_timer(&port->mpegq.timeout); | ||
659 | |||
660 | switch(portno) { | ||
661 | case 1: | ||
662 | port->reg_gpcnt = VID_B_GPCNT; | ||
663 | port->reg_gpcnt_ctl = VID_B_GPCNT_CTL; | ||
664 | port->reg_dma_ctl = VID_B_DMA_CTL; | ||
665 | port->reg_lngth = VID_B_LNGTH; | ||
666 | port->reg_hw_sop_ctrl = VID_B_HW_SOP_CTL; | ||
667 | port->reg_gen_ctrl = VID_B_GEN_CTL; | ||
668 | port->reg_bd_pkt_status = VID_B_BD_PKT_STATUS; | ||
669 | port->reg_sop_status = VID_B_SOP_STATUS; | ||
670 | port->reg_fifo_ovfl_stat = VID_B_FIFO_OVFL_STAT; | ||
671 | port->reg_vld_misc = VID_B_VLD_MISC; | ||
672 | port->reg_ts_clk_en = VID_B_TS_CLK_EN; | ||
673 | port->reg_src_sel = VID_B_SRC_SEL; | ||
674 | port->reg_ts_int_msk = VID_B_INT_MSK; | ||
675 | port->reg_ts_int_stat = VID_B_INT_STAT; | ||
676 | port->sram_chno = SRAM_CH03; /* VID_B */ | ||
677 | port->pci_irqmask = 0x02; /* VID_B bit1 */ | ||
678 | break; | ||
679 | case 2: | ||
680 | port->reg_gpcnt = VID_C_GPCNT; | ||
681 | port->reg_gpcnt_ctl = VID_C_GPCNT_CTL; | ||
682 | port->reg_dma_ctl = VID_C_DMA_CTL; | ||
683 | port->reg_lngth = VID_C_LNGTH; | ||
684 | port->reg_hw_sop_ctrl = VID_C_HW_SOP_CTL; | ||
685 | port->reg_gen_ctrl = VID_C_GEN_CTL; | ||
686 | port->reg_bd_pkt_status = VID_C_BD_PKT_STATUS; | ||
687 | port->reg_sop_status = VID_C_SOP_STATUS; | ||
688 | port->reg_fifo_ovfl_stat = VID_C_FIFO_OVFL_STAT; | ||
689 | port->reg_vld_misc = VID_C_VLD_MISC; | ||
690 | port->reg_ts_clk_en = VID_C_TS_CLK_EN; | ||
691 | port->reg_src_sel = 0; | ||
692 | port->reg_ts_int_msk = VID_C_INT_MSK; | ||
693 | port->reg_ts_int_stat = VID_C_INT_STAT; | ||
694 | port->sram_chno = SRAM_CH06; /* VID_C */ | ||
695 | port->pci_irqmask = 0x04; /* VID_C bit2 */ | ||
696 | break; | ||
697 | default: | ||
698 | BUG(); | ||
699 | } | ||
700 | |||
701 | cx23885_risc_stopper(dev->pci, &port->mpegq.stopper, | ||
702 | port->reg_dma_ctl, port->dma_ctl_val, 0x00); | ||
703 | |||
704 | return 0; | ||
705 | } | ||
706 | |||
707 | static int cx23885_dev_setup(struct cx23885_dev *dev) | ||
708 | { | ||
709 | int i; | ||
710 | |||
711 | mutex_init(&dev->lock); | ||
712 | |||
713 | atomic_inc(&dev->refcount); | ||
714 | |||
715 | dev->nr = cx23885_devcount++; | ||
716 | sprintf(dev->name, "cx23885[%d]", dev->nr); | ||
717 | |||
718 | mutex_lock(&devlist); | ||
719 | list_add_tail(&dev->devlist, &cx23885_devlist); | ||
720 | mutex_unlock(&devlist); | ||
721 | |||
722 | /* Configure the internal memory */ | ||
723 | if(dev->pci->device == 0x8880) { | ||
724 | dev->bridge = CX23885_BRIDGE_887; | ||
725 | dev->sram_channels = cx23887_sram_channels; | ||
726 | } else | ||
727 | if(dev->pci->device == 0x8852) { | ||
728 | dev->bridge = CX23885_BRIDGE_885; | ||
729 | dev->sram_channels = cx23885_sram_channels; | ||
730 | } else | ||
731 | BUG(); | ||
732 | |||
733 | dprintk(1, "%s() Memory configured for PCIe bridge type %d\n", | ||
734 | __FUNCTION__, dev->bridge); | ||
735 | |||
736 | /* board config */ | ||
737 | dev->board = UNSET; | ||
738 | if (card[dev->nr] < cx23885_bcount) | ||
739 | dev->board = card[dev->nr]; | ||
740 | for (i = 0; UNSET == dev->board && i < cx23885_idcount; i++) | ||
741 | if (dev->pci->subsystem_vendor == cx23885_subids[i].subvendor && | ||
742 | dev->pci->subsystem_device == cx23885_subids[i].subdevice) | ||
743 | dev->board = cx23885_subids[i].card; | ||
744 | if (UNSET == dev->board) { | ||
745 | dev->board = CX23885_BOARD_UNKNOWN; | ||
746 | cx23885_card_list(dev); | ||
747 | } | ||
748 | |||
749 | dev->pci_bus = dev->pci->bus->number; | ||
750 | dev->pci_slot = PCI_SLOT(dev->pci->devfn); | ||
751 | dev->pci_irqmask = 0x001f00; | ||
752 | |||
753 | /* External Master 1 Bus */ | ||
754 | dev->i2c_bus[0].nr = 0; | ||
755 | dev->i2c_bus[0].dev = dev; | ||
756 | dev->i2c_bus[0].reg_stat = I2C1_STAT; | ||
757 | dev->i2c_bus[0].reg_ctrl = I2C1_CTRL; | ||
758 | dev->i2c_bus[0].reg_addr = I2C1_ADDR; | ||
759 | dev->i2c_bus[0].reg_rdata = I2C1_RDATA; | ||
760 | dev->i2c_bus[0].reg_wdata = I2C1_WDATA; | ||
761 | dev->i2c_bus[0].i2c_period = (0x9d << 24); /* 100kHz */ | ||
762 | |||
763 | /* External Master 2 Bus */ | ||
764 | dev->i2c_bus[1].nr = 1; | ||
765 | dev->i2c_bus[1].dev = dev; | ||
766 | dev->i2c_bus[1].reg_stat = I2C2_STAT; | ||
767 | dev->i2c_bus[1].reg_ctrl = I2C2_CTRL; | ||
768 | dev->i2c_bus[1].reg_addr = I2C2_ADDR; | ||
769 | dev->i2c_bus[1].reg_rdata = I2C2_RDATA; | ||
770 | dev->i2c_bus[1].reg_wdata = I2C2_WDATA; | ||
771 | dev->i2c_bus[1].i2c_period = (0x9d << 24); /* 100kHz */ | ||
772 | |||
773 | /* Internal Master 3 Bus */ | ||
774 | dev->i2c_bus[2].nr = 2; | ||
775 | dev->i2c_bus[2].dev = dev; | ||
776 | dev->i2c_bus[2].reg_stat = I2C3_STAT; | ||
777 | dev->i2c_bus[2].reg_ctrl = I2C3_CTRL; | ||
778 | dev->i2c_bus[2].reg_addr = I2C3_ADDR; | ||
779 | dev->i2c_bus[2].reg_rdata = I2C3_RDATA; | ||
780 | dev->i2c_bus[2].reg_wdata = I2C3_WDATA; | ||
781 | dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */ | ||
782 | |||
783 | if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) | ||
784 | cx23885_init_tsport(dev, &dev->ts1, 1); | ||
785 | |||
786 | if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) | ||
787 | cx23885_init_tsport(dev, &dev->ts2, 2); | ||
788 | |||
789 | if (get_resources(dev) < 0) { | ||
790 | printk(KERN_ERR "CORE %s No more PCIe resources for " | ||
791 | "subsystem: %04x:%04x\n", | ||
792 | dev->name, dev->pci->subsystem_vendor, | ||
793 | dev->pci->subsystem_device); | ||
794 | |||
795 | cx23885_devcount--; | ||
796 | goto fail_free; | ||
797 | } | ||
798 | |||
799 | /* PCIe stuff */ | ||
800 | dev->lmmio = ioremap(pci_resource_start(dev->pci,0), | ||
801 | pci_resource_len(dev->pci,0)); | ||
802 | |||
803 | dev->bmmio = (u8 __iomem *)dev->lmmio; | ||
804 | |||
805 | printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", | ||
806 | dev->name, dev->pci->subsystem_vendor, | ||
807 | dev->pci->subsystem_device, cx23885_boards[dev->board].name, | ||
808 | dev->board, card[dev->nr] == dev->board ? | ||
809 | "insmod option" : "autodetected"); | ||
810 | |||
811 | cx23885_pci_quirks(dev); | ||
812 | |||
813 | /* init hardware */ | ||
814 | cx23885_reset(dev); | ||
815 | |||
816 | cx23885_i2c_register(&dev->i2c_bus[0]); | ||
817 | cx23885_i2c_register(&dev->i2c_bus[1]); | ||
818 | cx23885_i2c_register(&dev->i2c_bus[2]); | ||
819 | cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL); | ||
820 | cx23885_card_setup(dev); | ||
821 | cx23885_ir_init(dev); | ||
822 | |||
823 | if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) { | ||
824 | if (cx23885_dvb_register(&dev->ts1) < 0) { | ||
825 | printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n", | ||
826 | __FUNCTION__); | ||
827 | } | ||
828 | } | ||
829 | |||
830 | if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) { | ||
831 | if (cx23885_dvb_register(&dev->ts2) < 0) { | ||
832 | printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n", | ||
833 | __FUNCTION__); | ||
834 | } | ||
835 | } | ||
836 | |||
837 | return 0; | ||
838 | |||
839 | fail_free: | ||
840 | kfree(dev); | ||
841 | return -ENODEV; | ||
842 | } | ||
843 | |||
844 | void cx23885_dev_unregister(struct cx23885_dev *dev) | ||
845 | { | ||
846 | release_mem_region(pci_resource_start(dev->pci,0), | ||
847 | pci_resource_len(dev->pci,0)); | ||
848 | |||
849 | if (!atomic_dec_and_test(&dev->refcount)) | ||
850 | return; | ||
851 | |||
852 | if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) | ||
853 | cx23885_dvb_unregister(&dev->ts1); | ||
854 | |||
855 | if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) | ||
856 | cx23885_dvb_unregister(&dev->ts2); | ||
857 | |||
858 | cx23885_i2c_unregister(&dev->i2c_bus[2]); | ||
859 | cx23885_i2c_unregister(&dev->i2c_bus[1]); | ||
860 | cx23885_i2c_unregister(&dev->i2c_bus[0]); | ||
861 | |||
862 | iounmap(dev->lmmio); | ||
863 | } | ||
864 | |||
865 | static u32* cx23885_risc_field(u32 *rp, struct scatterlist *sglist, | ||
866 | unsigned int offset, u32 sync_line, | ||
867 | unsigned int bpl, unsigned int padding, | ||
868 | unsigned int lines) | ||
869 | { | ||
870 | struct scatterlist *sg; | ||
871 | unsigned int line, todo; | ||
872 | |||
873 | /* sync instruction */ | ||
874 | if (sync_line != NO_SYNC_LINE) | ||
875 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
876 | |||
877 | /* scan lines */ | ||
878 | sg = sglist; | ||
879 | for (line = 0; line < lines; line++) { | ||
880 | while (offset && offset >= sg_dma_len(sg)) { | ||
881 | offset -= sg_dma_len(sg); | ||
882 | sg++; | ||
883 | } | ||
884 | if (bpl <= sg_dma_len(sg)-offset) { | ||
885 | /* fits into current chunk */ | ||
886 | *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); | ||
887 | *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); | ||
888 | *(rp++)=cpu_to_le32(0); /* bits 63-32 */ | ||
889 | offset+=bpl; | ||
890 | } else { | ||
891 | /* scanline needs to be split */ | ||
892 | todo = bpl; | ||
893 | *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL| | ||
894 | (sg_dma_len(sg)-offset)); | ||
895 | *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); | ||
896 | *(rp++)=cpu_to_le32(0); /* bits 63-32 */ | ||
897 | todo -= (sg_dma_len(sg)-offset); | ||
898 | offset = 0; | ||
899 | sg++; | ||
900 | while (todo > sg_dma_len(sg)) { | ||
901 | *(rp++)=cpu_to_le32(RISC_WRITE| | ||
902 | sg_dma_len(sg)); | ||
903 | *(rp++)=cpu_to_le32(sg_dma_address(sg)); | ||
904 | *(rp++)=cpu_to_le32(0); /* bits 63-32 */ | ||
905 | todo -= sg_dma_len(sg); | ||
906 | sg++; | ||
907 | } | ||
908 | *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); | ||
909 | *(rp++)=cpu_to_le32(sg_dma_address(sg)); | ||
910 | *(rp++)=cpu_to_le32(0); /* bits 63-32 */ | ||
911 | offset += todo; | ||
912 | } | ||
913 | offset += padding; | ||
914 | } | ||
915 | |||
916 | return rp; | ||
917 | } | ||
918 | |||
919 | int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | ||
920 | struct scatterlist *sglist, unsigned int top_offset, | ||
921 | unsigned int bottom_offset, unsigned int bpl, | ||
922 | unsigned int padding, unsigned int lines) | ||
923 | { | ||
924 | u32 instructions, fields; | ||
925 | u32 *rp; | ||
926 | int rc; | ||
927 | |||
928 | fields = 0; | ||
929 | if (UNSET != top_offset) | ||
930 | fields++; | ||
931 | if (UNSET != bottom_offset) | ||
932 | fields++; | ||
933 | |||
934 | /* estimate risc mem: worst case is one write per page border + | ||
935 | one write per scan line + syncs + jump (all 2 dwords). Padding | ||
936 | can cause next bpl to start close to a page border. First DMA | ||
937 | region may be smaller than PAGE_SIZE */ | ||
938 | /* write and jump need and extra dword */ | ||
939 | instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); | ||
940 | instructions += 2; | ||
941 | if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0) | ||
942 | return rc; | ||
943 | |||
944 | /* write risc instructions */ | ||
945 | rp = risc->cpu; | ||
946 | if (UNSET != top_offset) | ||
947 | rp = cx23885_risc_field(rp, sglist, top_offset, 0, | ||
948 | bpl, padding, lines); | ||
949 | if (UNSET != bottom_offset) | ||
950 | rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200, | ||
951 | bpl, padding, lines); | ||
952 | |||
953 | /* save pointer to jmp instruction address */ | ||
954 | risc->jmp = rp; | ||
955 | BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size); | ||
956 | return 0; | ||
957 | } | ||
958 | |||
959 | int cx23885_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, | ||
960 | struct scatterlist *sglist, unsigned int bpl, | ||
961 | unsigned int lines) | ||
962 | { | ||
963 | u32 instructions; | ||
964 | u32 *rp; | ||
965 | int rc; | ||
966 | |||
967 | /* estimate risc mem: worst case is one write per page border + | ||
968 | one write per scan line + syncs + jump (all 2 dwords). Here | ||
969 | there is no padding and no sync. First DMA region may be smaller | ||
970 | than PAGE_SIZE */ | ||
971 | /* Jump and write need an extra dword */ | ||
972 | instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; | ||
973 | instructions += 1; | ||
974 | |||
975 | if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0) | ||
976 | return rc; | ||
977 | |||
978 | /* write risc instructions */ | ||
979 | rp = risc->cpu; | ||
980 | rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines); | ||
981 | |||
982 | /* save pointer to jmp instruction address */ | ||
983 | risc->jmp = rp; | ||
984 | BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size); | ||
985 | return 0; | ||
986 | } | ||
987 | |||
988 | int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | ||
989 | u32 reg, u32 mask, u32 value) | ||
990 | { | ||
991 | u32 *rp; | ||
992 | int rc; | ||
993 | |||
994 | if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0) | ||
995 | return rc; | ||
996 | |||
997 | /* write risc instructions */ | ||
998 | rp = risc->cpu; | ||
999 | *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2); | ||
1000 | *(rp++) = cpu_to_le32(reg); | ||
1001 | *(rp++) = cpu_to_le32(value); | ||
1002 | *(rp++) = cpu_to_le32(mask); | ||
1003 | *(rp++) = cpu_to_le32(RISC_JUMP); | ||
1004 | *(rp++) = cpu_to_le32(risc->dma); | ||
1005 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf) | ||
1010 | { | ||
1011 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); | ||
1012 | |||
1013 | BUG_ON(in_interrupt()); | ||
1014 | videobuf_waiton(&buf->vb, 0, 0); | ||
1015 | videobuf_dma_unmap(q, dma); | ||
1016 | videobuf_dma_free(dma); | ||
1017 | btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc); | ||
1018 | buf->vb.state = STATE_NEEDS_INIT; | ||
1019 | } | ||
1020 | |||
1021 | static int cx23885_start_dma(struct cx23885_tsport *port, | ||
1022 | struct cx23885_dmaqueue *q, | ||
1023 | struct cx23885_buffer *buf) | ||
1024 | { | ||
1025 | struct cx23885_dev *dev = port->dev; | ||
1026 | |||
1027 | dprintk(1, "%s() w: %d, h: %d, f: %d\n", __FUNCTION__, | ||
1028 | buf->vb.width, buf->vb.height, buf->vb.field); | ||
1029 | |||
1030 | /* setup fifo + format */ | ||
1031 | cx23885_sram_channel_setup(dev, | ||
1032 | &dev->sram_channels[ port->sram_chno ], | ||
1033 | port->ts_packet_size, buf->risc.dma); | ||
1034 | if(debug > 5) { | ||
1035 | cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ] ); | ||
1036 | cx23885_risc_disasm(port, &buf->risc); | ||
1037 | } | ||
1038 | |||
1039 | /* write TS length to chip */ | ||
1040 | cx_write(port->reg_lngth, buf->vb.width); | ||
1041 | |||
1042 | if ( (!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) && | ||
1043 | (!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB)) ) { | ||
1044 | printk( "%s() Failed. Unsupported value in .portb/c (0x%08x)/(0x%08x)\n", | ||
1045 | __FUNCTION__, | ||
1046 | cx23885_boards[dev->board].portb, | ||
1047 | cx23885_boards[dev->board].portc ); | ||
1048 | return -EINVAL; | ||
1049 | } | ||
1050 | |||
1051 | udelay(100); | ||
1052 | |||
1053 | /* If the port supports SRC SELECT, configure it */ | ||
1054 | if(port->reg_src_sel) | ||
1055 | cx_write(port->reg_src_sel, port->src_sel_val); | ||
1056 | |||
1057 | cx_write(port->reg_hw_sop_ctrl, 0x47 << 16 | 188 << 4); | ||
1058 | cx_write(port->reg_ts_clk_en, port->ts_clk_en_val); | ||
1059 | cx_write(port->reg_vld_misc, 0x00); | ||
1060 | cx_write(port->reg_gen_ctrl, port->gen_ctrl_val); | ||
1061 | udelay(100); | ||
1062 | |||
1063 | // NOTE: this is 2 (reserved) for portb, does it matter? | ||
1064 | /* reset counter to zero */ | ||
1065 | cx_write(port->reg_gpcnt_ctl, 3); | ||
1066 | q->count = 1; | ||
1067 | |||
1068 | switch(dev->bridge) { | ||
1069 | case CX23885_BRIDGE_885: | ||
1070 | case CX23885_BRIDGE_887: | ||
1071 | /* enable irqs */ | ||
1072 | dprintk(1, "%s() enabling TS int's and DMA\n", __FUNCTION__ ); | ||
1073 | cx_set(port->reg_ts_int_msk, port->ts_int_msk_val); | ||
1074 | cx_set(port->reg_dma_ctl, port->dma_ctl_val); | ||
1075 | cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask); | ||
1076 | break; | ||
1077 | default: | ||
1078 | BUG(); | ||
1079 | } | ||
1080 | |||
1081 | cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */ | ||
1082 | |||
1083 | return 0; | ||
1084 | } | ||
1085 | |||
1086 | static int cx23885_stop_dma(struct cx23885_tsport *port) | ||
1087 | { | ||
1088 | struct cx23885_dev *dev = port->dev; | ||
1089 | dprintk(1, "%s()\n", __FUNCTION__); | ||
1090 | |||
1091 | /* Stop interrupts and DMA */ | ||
1092 | cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val); | ||
1093 | cx_clear(port->reg_dma_ctl, port->dma_ctl_val); | ||
1094 | |||
1095 | return 0; | ||
1096 | } | ||
1097 | |||
1098 | static int cx23885_restart_queue(struct cx23885_tsport *port, | ||
1099 | struct cx23885_dmaqueue *q) | ||
1100 | { | ||
1101 | struct cx23885_dev *dev = port->dev; | ||
1102 | struct cx23885_buffer *buf; | ||
1103 | |||
1104 | dprintk(5, "%s()\n", __FUNCTION__); | ||
1105 | if (list_empty(&q->active)) | ||
1106 | { | ||
1107 | struct cx23885_buffer *prev; | ||
1108 | prev = NULL; | ||
1109 | |||
1110 | dprintk(5, "%s() queue is empty\n", __FUNCTION__); | ||
1111 | |||
1112 | for (;;) { | ||
1113 | if (list_empty(&q->queued)) | ||
1114 | return 0; | ||
1115 | buf = list_entry(q->queued.next, struct cx23885_buffer, | ||
1116 | vb.queue); | ||
1117 | if (NULL == prev) { | ||
1118 | list_del(&buf->vb.queue); | ||
1119 | list_add_tail(&buf->vb.queue, &q->active); | ||
1120 | cx23885_start_dma(port, q, buf); | ||
1121 | buf->vb.state = STATE_ACTIVE; | ||
1122 | buf->count = q->count++; | ||
1123 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
1124 | dprintk(5, "[%p/%d] restart_queue - first active\n", | ||
1125 | buf, buf->vb.i); | ||
1126 | |||
1127 | } else if (prev->vb.width == buf->vb.width && | ||
1128 | prev->vb.height == buf->vb.height && | ||
1129 | prev->fmt == buf->fmt) { | ||
1130 | list_del(&buf->vb.queue); | ||
1131 | list_add_tail(&buf->vb.queue, &q->active); | ||
1132 | buf->vb.state = STATE_ACTIVE; | ||
1133 | buf->count = q->count++; | ||
1134 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
1135 | prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */ | ||
1136 | dprintk(5,"[%p/%d] restart_queue - move to active\n", | ||
1137 | buf, buf->vb.i); | ||
1138 | } else { | ||
1139 | return 0; | ||
1140 | } | ||
1141 | prev = buf; | ||
1142 | } | ||
1143 | return 0; | ||
1144 | } | ||
1145 | |||
1146 | buf = list_entry(q->active.next, struct cx23885_buffer, vb.queue); | ||
1147 | dprintk(2, "restart_queue [%p/%d]: restart dma\n", | ||
1148 | buf, buf->vb.i); | ||
1149 | cx23885_start_dma(port, q, buf); | ||
1150 | list_for_each_entry(buf, &q->active, vb.queue) | ||
1151 | buf->count = q->count++; | ||
1152 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | ||
1153 | return 0; | ||
1154 | } | ||
1155 | |||
1156 | /* ------------------------------------------------------------------ */ | ||
1157 | |||
1158 | int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port, | ||
1159 | struct cx23885_buffer *buf, enum v4l2_field field) | ||
1160 | { | ||
1161 | struct cx23885_dev *dev = port->dev; | ||
1162 | int size = port->ts_packet_size * port->ts_packet_count; | ||
1163 | int rc; | ||
1164 | |||
1165 | dprintk(1, "%s: %p\n", __FUNCTION__, buf); | ||
1166 | if (0 != buf->vb.baddr && buf->vb.bsize < size) | ||
1167 | return -EINVAL; | ||
1168 | |||
1169 | if (STATE_NEEDS_INIT == buf->vb.state) { | ||
1170 | buf->vb.width = port->ts_packet_size; | ||
1171 | buf->vb.height = port->ts_packet_count; | ||
1172 | buf->vb.size = size; | ||
1173 | buf->vb.field = field /*V4L2_FIELD_TOP*/; | ||
1174 | |||
1175 | if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL))) | ||
1176 | goto fail; | ||
1177 | cx23885_risc_databuffer(dev->pci, &buf->risc, | ||
1178 | videobuf_to_dma(&buf->vb)->sglist, | ||
1179 | buf->vb.width, buf->vb.height); | ||
1180 | } | ||
1181 | buf->vb.state = STATE_PREPARED; | ||
1182 | return 0; | ||
1183 | |||
1184 | fail: | ||
1185 | cx23885_free_buffer(q, buf); | ||
1186 | return rc; | ||
1187 | } | ||
1188 | |||
1189 | void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf) | ||
1190 | { | ||
1191 | struct cx23885_buffer *prev; | ||
1192 | struct cx23885_dev *dev = port->dev; | ||
1193 | struct cx23885_dmaqueue *cx88q = &port->mpegq; | ||
1194 | |||
1195 | /* add jump to stopper */ | ||
1196 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
1197 | buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma); | ||
1198 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||
1199 | |||
1200 | if (list_empty(&cx88q->active)) { | ||
1201 | dprintk( 1, "queue is empty - first active\n" ); | ||
1202 | list_add_tail(&buf->vb.queue, &cx88q->active); | ||
1203 | cx23885_start_dma(port, cx88q, buf); | ||
1204 | buf->vb.state = STATE_ACTIVE; | ||
1205 | buf->count = cx88q->count++; | ||
1206 | mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT); | ||
1207 | dprintk(1, "[%p/%d] %s - first active\n", | ||
1208 | buf, buf->vb.i, __FUNCTION__); | ||
1209 | } else { | ||
1210 | dprintk( 1, "queue is not empty - append to active\n" ); | ||
1211 | prev = list_entry(cx88q->active.prev, struct cx23885_buffer, | ||
1212 | vb.queue); | ||
1213 | list_add_tail(&buf->vb.queue, &cx88q->active); | ||
1214 | buf->vb.state = STATE_ACTIVE; | ||
1215 | buf->count = cx88q->count++; | ||
1216 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
1217 | prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */ | ||
1218 | dprintk( 1, "[%p/%d] %s - append to active\n", | ||
1219 | buf, buf->vb.i, __FUNCTION__); | ||
1220 | } | ||
1221 | } | ||
1222 | |||
1223 | /* ----------------------------------------------------------- */ | ||
1224 | |||
1225 | static void do_cancel_buffers(struct cx23885_tsport *port, char *reason, | ||
1226 | int restart) | ||
1227 | { | ||
1228 | struct cx23885_dev *dev = port->dev; | ||
1229 | struct cx23885_dmaqueue *q = &port->mpegq; | ||
1230 | struct cx23885_buffer *buf; | ||
1231 | unsigned long flags; | ||
1232 | |||
1233 | spin_lock_irqsave(&port->slock, flags); | ||
1234 | while (!list_empty(&q->active)) { | ||
1235 | buf = list_entry(q->active.next, struct cx23885_buffer, | ||
1236 | vb.queue); | ||
1237 | list_del(&buf->vb.queue); | ||
1238 | buf->vb.state = STATE_ERROR; | ||
1239 | wake_up(&buf->vb.done); | ||
1240 | dprintk(1, "[%p/%d] %s - dma=0x%08lx\n", | ||
1241 | buf, buf->vb.i, reason, (unsigned long)buf->risc.dma); | ||
1242 | } | ||
1243 | if (restart) { | ||
1244 | dprintk(1, "restarting queue\n" ); | ||
1245 | cx23885_restart_queue(port, q); | ||
1246 | } | ||
1247 | spin_unlock_irqrestore(&port->slock, flags); | ||
1248 | } | ||
1249 | |||
1250 | void cx23885_cancel_buffers(struct cx23885_tsport *port) | ||
1251 | { | ||
1252 | struct cx23885_dev *dev = port->dev; | ||
1253 | struct cx23885_dmaqueue *q = &port->mpegq; | ||
1254 | |||
1255 | dprintk(1, "%s()\n", __FUNCTION__); | ||
1256 | del_timer_sync(&q->timeout); | ||
1257 | cx23885_stop_dma(port); | ||
1258 | do_cancel_buffers(port, "cancel", 0); | ||
1259 | } | ||
1260 | |||
1261 | static void cx23885_timeout(unsigned long data) | ||
1262 | { | ||
1263 | struct cx23885_tsport *port = (struct cx23885_tsport *)data; | ||
1264 | struct cx23885_dev *dev = port->dev; | ||
1265 | |||
1266 | dprintk(1, "%s()\n",__FUNCTION__); | ||
1267 | |||
1268 | if (debug > 5) | ||
1269 | cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]); | ||
1270 | |||
1271 | cx23885_stop_dma(port); | ||
1272 | do_cancel_buffers(port, "timeout", 1); | ||
1273 | } | ||
1274 | |||
1275 | static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status) | ||
1276 | { | ||
1277 | struct cx23885_dev *dev = port->dev; | ||
1278 | int handled = 0; | ||
1279 | u32 count; | ||
1280 | |||
1281 | if ( (status & VID_BC_MSK_OPC_ERR) || | ||
1282 | (status & VID_BC_MSK_BAD_PKT) || | ||
1283 | (status & VID_BC_MSK_SYNC) || | ||
1284 | (status & VID_BC_MSK_OF)) | ||
1285 | { | ||
1286 | if (status & VID_BC_MSK_OPC_ERR) | ||
1287 | dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR); | ||
1288 | if (status & VID_BC_MSK_BAD_PKT) | ||
1289 | dprintk(7, " (VID_BC_MSK_BAD_PKT 0x%08x)\n", VID_BC_MSK_BAD_PKT); | ||
1290 | if (status & VID_BC_MSK_SYNC) | ||
1291 | dprintk(7, " (VID_BC_MSK_SYNC 0x%08x)\n", VID_BC_MSK_SYNC); | ||
1292 | if (status & VID_BC_MSK_OF) | ||
1293 | dprintk(7, " (VID_BC_MSK_OF 0x%08x)\n", VID_BC_MSK_OF); | ||
1294 | |||
1295 | printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name); | ||
1296 | |||
1297 | cx_clear(port->reg_dma_ctl, port->dma_ctl_val); | ||
1298 | cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]); | ||
1299 | |||
1300 | } else if (status & VID_BC_MSK_RISCI1) { | ||
1301 | |||
1302 | dprintk(7, " (RISCI1 0x%08x)\n", VID_BC_MSK_RISCI1); | ||
1303 | |||
1304 | spin_lock(&port->slock); | ||
1305 | count = cx_read(port->reg_gpcnt); | ||
1306 | cx23885_wakeup(port, &port->mpegq, count); | ||
1307 | spin_unlock(&port->slock); | ||
1308 | |||
1309 | } else if (status & VID_BC_MSK_RISCI2) { | ||
1310 | |||
1311 | dprintk(7, " (RISCI2 0x%08x)\n", VID_BC_MSK_RISCI2); | ||
1312 | |||
1313 | spin_lock(&port->slock); | ||
1314 | cx23885_restart_queue(port, &port->mpegq); | ||
1315 | spin_unlock(&port->slock); | ||
1316 | |||
1317 | } | ||
1318 | if (status) { | ||
1319 | cx_write(port->reg_ts_int_stat, status); | ||
1320 | handled = 1; | ||
1321 | } | ||
1322 | |||
1323 | return handled; | ||
1324 | } | ||
1325 | |||
1326 | static irqreturn_t cx23885_irq(int irq, void *dev_id) | ||
1327 | { | ||
1328 | struct cx23885_dev *dev = dev_id; | ||
1329 | struct cx23885_tsport *ts1 = &dev->ts1; | ||
1330 | struct cx23885_tsport *ts2 = &dev->ts2; | ||
1331 | u32 pci_status, pci_mask; | ||
1332 | u32 ts1_status, ts1_mask; | ||
1333 | u32 ts2_status, ts2_mask; | ||
1334 | int ts1_count = 0, ts2_count = 0, handled = 0; | ||
1335 | |||
1336 | pci_status = cx_read(PCI_INT_STAT); | ||
1337 | pci_mask = cx_read(PCI_INT_MSK); | ||
1338 | ts1_status = cx_read(VID_B_INT_STAT); | ||
1339 | ts1_mask = cx_read(VID_B_INT_MSK); | ||
1340 | ts2_status = cx_read(VID_C_INT_STAT); | ||
1341 | ts2_mask = cx_read(VID_C_INT_MSK); | ||
1342 | |||
1343 | if ( (pci_status == 0) && (ts2_status == 0) && (ts1_status == 0) ) | ||
1344 | goto out; | ||
1345 | |||
1346 | ts1_count = cx_read(ts1->reg_gpcnt); | ||
1347 | ts2_count = cx_read(ts2->reg_gpcnt); | ||
1348 | dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n", pci_status, pci_mask ); | ||
1349 | dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n", ts1_status, ts1_mask, ts1_count ); | ||
1350 | dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", ts2_status, ts2_mask, ts2_count ); | ||
1351 | |||
1352 | if ( (pci_status & PCI_MSK_RISC_RD) || | ||
1353 | (pci_status & PCI_MSK_RISC_WR) || | ||
1354 | (pci_status & PCI_MSK_AL_RD) || | ||
1355 | (pci_status & PCI_MSK_AL_WR) || | ||
1356 | (pci_status & PCI_MSK_APB_DMA) || | ||
1357 | (pci_status & PCI_MSK_VID_C) || | ||
1358 | (pci_status & PCI_MSK_VID_B) || | ||
1359 | (pci_status & PCI_MSK_VID_A) || | ||
1360 | (pci_status & PCI_MSK_AUD_INT) || | ||
1361 | (pci_status & PCI_MSK_AUD_EXT) ) | ||
1362 | { | ||
1363 | |||
1364 | if (pci_status & PCI_MSK_RISC_RD) | ||
1365 | dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", PCI_MSK_RISC_RD); | ||
1366 | if (pci_status & PCI_MSK_RISC_WR) | ||
1367 | dprintk(7, " (PCI_MSK_RISC_WR 0x%08x)\n", PCI_MSK_RISC_WR); | ||
1368 | if (pci_status & PCI_MSK_AL_RD) | ||
1369 | dprintk(7, " (PCI_MSK_AL_RD 0x%08x)\n", PCI_MSK_AL_RD); | ||
1370 | if (pci_status & PCI_MSK_AL_WR) | ||
1371 | dprintk(7, " (PCI_MSK_AL_WR 0x%08x)\n", PCI_MSK_AL_WR); | ||
1372 | if (pci_status & PCI_MSK_APB_DMA) | ||
1373 | dprintk(7, " (PCI_MSK_APB_DMA 0x%08x)\n", PCI_MSK_APB_DMA); | ||
1374 | if (pci_status & PCI_MSK_VID_C) | ||
1375 | dprintk(7, " (PCI_MSK_VID_C 0x%08x)\n", PCI_MSK_VID_C); | ||
1376 | if (pci_status & PCI_MSK_VID_B) | ||
1377 | dprintk(7, " (PCI_MSK_VID_B 0x%08x)\n", PCI_MSK_VID_B); | ||
1378 | if (pci_status & PCI_MSK_VID_A) | ||
1379 | dprintk(7, " (PCI_MSK_VID_A 0x%08x)\n", PCI_MSK_VID_A); | ||
1380 | if (pci_status & PCI_MSK_AUD_INT) | ||
1381 | dprintk(7, " (PCI_MSK_AUD_INT 0x%08x)\n", PCI_MSK_AUD_INT); | ||
1382 | if (pci_status & PCI_MSK_AUD_EXT) | ||
1383 | dprintk(7, " (PCI_MSK_AUD_EXT 0x%08x)\n", PCI_MSK_AUD_EXT); | ||
1384 | |||
1385 | } | ||
1386 | |||
1387 | if (ts1_status) | ||
1388 | handled += cx23885_irq_ts(ts1, ts1_status); | ||
1389 | |||
1390 | if (ts2_status) | ||
1391 | handled += cx23885_irq_ts(ts2, ts2_status); | ||
1392 | |||
1393 | if (handled) | ||
1394 | cx_write(PCI_INT_STAT, pci_status); | ||
1395 | out: | ||
1396 | return IRQ_RETVAL(handled); | ||
1397 | } | ||
1398 | |||
1399 | static int __devinit cx23885_initdev(struct pci_dev *pci_dev, | ||
1400 | const struct pci_device_id *pci_id) | ||
1401 | { | ||
1402 | struct cx23885_dev *dev; | ||
1403 | int err; | ||
1404 | |||
1405 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
1406 | if (NULL == dev) | ||
1407 | return -ENOMEM; | ||
1408 | |||
1409 | /* pci init */ | ||
1410 | dev->pci = pci_dev; | ||
1411 | if (pci_enable_device(pci_dev)) { | ||
1412 | err = -EIO; | ||
1413 | goto fail_free; | ||
1414 | } | ||
1415 | |||
1416 | if (cx23885_dev_setup(dev) < 0) { | ||
1417 | err = -EINVAL; | ||
1418 | goto fail_free; | ||
1419 | } | ||
1420 | |||
1421 | /* print pci info */ | ||
1422 | pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); | ||
1423 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); | ||
1424 | printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " | ||
1425 | "latency: %d, mmio: 0x%llx\n", dev->name, | ||
1426 | pci_name(pci_dev), dev->pci_rev, pci_dev->irq, | ||
1427 | dev->pci_lat, (unsigned long long)pci_resource_start(pci_dev,0)); | ||
1428 | |||
1429 | pci_set_master(pci_dev); | ||
1430 | if (!pci_dma_supported(pci_dev, 0xffffffff)) { | ||
1431 | printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); | ||
1432 | err = -EIO; | ||
1433 | goto fail_irq; | ||
1434 | } | ||
1435 | |||
1436 | err = request_irq(pci_dev->irq, cx23885_irq, | ||
1437 | IRQF_SHARED | IRQF_DISABLED, dev->name, dev); | ||
1438 | if (err < 0) { | ||
1439 | printk(KERN_ERR "%s: can't get IRQ %d\n", | ||
1440 | dev->name, pci_dev->irq); | ||
1441 | goto fail_irq; | ||
1442 | } | ||
1443 | |||
1444 | pci_set_drvdata(pci_dev, dev); | ||
1445 | return 0; | ||
1446 | |||
1447 | fail_irq: | ||
1448 | cx23885_dev_unregister(dev); | ||
1449 | fail_free: | ||
1450 | kfree(dev); | ||
1451 | return err; | ||
1452 | } | ||
1453 | |||
1454 | static void __devexit cx23885_finidev(struct pci_dev *pci_dev) | ||
1455 | { | ||
1456 | struct cx23885_dev *dev = pci_get_drvdata(pci_dev); | ||
1457 | |||
1458 | cx23885_shutdown(dev); | ||
1459 | |||
1460 | pci_disable_device(pci_dev); | ||
1461 | |||
1462 | /* unregister stuff */ | ||
1463 | free_irq(pci_dev->irq, dev); | ||
1464 | pci_set_drvdata(pci_dev, NULL); | ||
1465 | |||
1466 | mutex_lock(&devlist); | ||
1467 | list_del(&dev->devlist); | ||
1468 | mutex_unlock(&devlist); | ||
1469 | |||
1470 | cx23885_dev_unregister(dev); | ||
1471 | kfree(dev); | ||
1472 | } | ||
1473 | |||
1474 | static struct pci_device_id cx23885_pci_tbl[] = { | ||
1475 | { | ||
1476 | /* CX23885 */ | ||
1477 | .vendor = 0x14f1, | ||
1478 | .device = 0x8852, | ||
1479 | .subvendor = PCI_ANY_ID, | ||
1480 | .subdevice = PCI_ANY_ID, | ||
1481 | },{ | ||
1482 | /* CX23887 Rev 2 */ | ||
1483 | .vendor = 0x14f1, | ||
1484 | .device = 0x8880, | ||
1485 | .subvendor = PCI_ANY_ID, | ||
1486 | .subdevice = PCI_ANY_ID, | ||
1487 | },{ | ||
1488 | /* --- end of list --- */ | ||
1489 | } | ||
1490 | }; | ||
1491 | MODULE_DEVICE_TABLE(pci, cx23885_pci_tbl); | ||
1492 | |||
1493 | static struct pci_driver cx23885_pci_driver = { | ||
1494 | .name = "cx23885", | ||
1495 | .id_table = cx23885_pci_tbl, | ||
1496 | .probe = cx23885_initdev, | ||
1497 | .remove = __devexit_p(cx23885_finidev), | ||
1498 | /* TODO */ | ||
1499 | .suspend = NULL, | ||
1500 | .resume = NULL, | ||
1501 | }; | ||
1502 | |||
1503 | static int cx23885_init(void) | ||
1504 | { | ||
1505 | printk(KERN_INFO "cx23885 driver version %d.%d.%d loaded\n", | ||
1506 | (CX23885_VERSION_CODE >> 16) & 0xff, | ||
1507 | (CX23885_VERSION_CODE >> 8) & 0xff, | ||
1508 | CX23885_VERSION_CODE & 0xff); | ||
1509 | #ifdef SNAPSHOT | ||
1510 | printk(KERN_INFO "cx23885: snapshot date %04d-%02d-%02d\n", | ||
1511 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | ||
1512 | #endif | ||
1513 | return pci_register_driver(&cx23885_pci_driver); | ||
1514 | } | ||
1515 | |||
1516 | static void cx23885_fini(void) | ||
1517 | { | ||
1518 | pci_unregister_driver(&cx23885_pci_driver); | ||
1519 | } | ||
1520 | |||
1521 | module_init(cx23885_init); | ||
1522 | module_exit(cx23885_fini); | ||
1523 | |||
1524 | /* ----------------------------------------------------------- */ | ||
1525 | /* | ||
1526 | * Local variables: | ||
1527 | * c-basic-offset: 8 | ||
1528 | * End: | ||
1529 | * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off | ||
1530 | */ | ||
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c new file mode 100644 index 000000000000..eda8c05d0931 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-dvb.c | |||
@@ -0,0 +1,213 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885 PCIe bridge | ||
3 | * | ||
4 | * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/device.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/kthread.h> | ||
27 | #include <linux/file.h> | ||
28 | #include <linux/suspend.h> | ||
29 | |||
30 | #include "cx23885.h" | ||
31 | #include <media/v4l2-common.h> | ||
32 | |||
33 | #include "s5h1409.h" | ||
34 | #include "mt2131.h" | ||
35 | #include "lgdt330x.h" | ||
36 | #include "dvb-pll.h" | ||
37 | |||
38 | static unsigned int debug = 0; | ||
39 | |||
40 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | ||
41 | printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg) | ||
42 | |||
43 | /* ------------------------------------------------------------------ */ | ||
44 | |||
45 | static int dvb_buf_setup(struct videobuf_queue *q, | ||
46 | unsigned int *count, unsigned int *size) | ||
47 | { | ||
48 | struct cx23885_tsport *port = q->priv_data; | ||
49 | |||
50 | port->ts_packet_size = 188 * 4; | ||
51 | port->ts_packet_count = 32; | ||
52 | |||
53 | *size = port->ts_packet_size * port->ts_packet_count; | ||
54 | *count = 32; | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static int dvb_buf_prepare(struct videobuf_queue *q, | ||
59 | struct videobuf_buffer *vb, enum v4l2_field field) | ||
60 | { | ||
61 | struct cx23885_tsport *port = q->priv_data; | ||
62 | return cx23885_buf_prepare(q, port, (struct cx23885_buffer*)vb, field); | ||
63 | } | ||
64 | |||
65 | static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
66 | { | ||
67 | struct cx23885_tsport *port = q->priv_data; | ||
68 | cx23885_buf_queue(port, (struct cx23885_buffer*)vb); | ||
69 | } | ||
70 | |||
71 | static void dvb_buf_release(struct videobuf_queue *q, | ||
72 | struct videobuf_buffer *vb) | ||
73 | { | ||
74 | cx23885_free_buffer(q, (struct cx23885_buffer*)vb); | ||
75 | } | ||
76 | |||
77 | static struct videobuf_queue_ops dvb_qops = { | ||
78 | .buf_setup = dvb_buf_setup, | ||
79 | .buf_prepare = dvb_buf_prepare, | ||
80 | .buf_queue = dvb_buf_queue, | ||
81 | .buf_release = dvb_buf_release, | ||
82 | }; | ||
83 | |||
84 | static struct s5h1409_config hauppauge_generic_config = { | ||
85 | .demod_address = 0x32 >> 1, | ||
86 | .output_mode = S5H1409_SERIAL_OUTPUT, | ||
87 | .gpio = S5H1409_GPIO_ON, | ||
88 | .if_freq = 44000, | ||
89 | .inversion = S5H1409_INVERSION_OFF, | ||
90 | .status_mode = S5H1409_DEMODLOCKING | ||
91 | }; | ||
92 | |||
93 | static struct s5h1409_config hauppauge_hvr1800lp_config = { | ||
94 | .demod_address = 0x32 >> 1, | ||
95 | .output_mode = S5H1409_SERIAL_OUTPUT, | ||
96 | .gpio = S5H1409_GPIO_OFF, | ||
97 | .if_freq = 44000, | ||
98 | .inversion = S5H1409_INVERSION_OFF, | ||
99 | .status_mode = S5H1409_DEMODLOCKING | ||
100 | }; | ||
101 | |||
102 | static struct mt2131_config hauppauge_generic_tunerconfig = { | ||
103 | 0x61 | ||
104 | }; | ||
105 | |||
106 | static struct lgdt330x_config fusionhdtv_5_express = { | ||
107 | .demod_address = 0x0e, | ||
108 | .demod_chip = LGDT3303, | ||
109 | .serial_mpeg = 0x40, | ||
110 | }; | ||
111 | |||
112 | static int dvb_register(struct cx23885_tsport *port) | ||
113 | { | ||
114 | struct cx23885_dev *dev = port->dev; | ||
115 | struct cx23885_i2c *i2c_bus = NULL; | ||
116 | |||
117 | /* init struct videobuf_dvb */ | ||
118 | port->dvb.name = dev->name; | ||
119 | |||
120 | /* init frontend */ | ||
121 | switch (dev->board) { | ||
122 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | ||
123 | case CX23885_BOARD_HAUPPAUGE_HVR1800: | ||
124 | i2c_bus = &dev->i2c_bus[0]; | ||
125 | port->dvb.frontend = dvb_attach(s5h1409_attach, | ||
126 | &hauppauge_generic_config, | ||
127 | &i2c_bus->i2c_adap); | ||
128 | if (port->dvb.frontend != NULL) { | ||
129 | dvb_attach(mt2131_attach, port->dvb.frontend, | ||
130 | &i2c_bus->i2c_adap, | ||
131 | &hauppauge_generic_tunerconfig, 0); | ||
132 | } | ||
133 | break; | ||
134 | case CX23885_BOARD_HAUPPAUGE_HVR1800lp: | ||
135 | i2c_bus = &dev->i2c_bus[0]; | ||
136 | port->dvb.frontend = dvb_attach(s5h1409_attach, | ||
137 | &hauppauge_hvr1800lp_config, | ||
138 | &i2c_bus->i2c_adap); | ||
139 | if (port->dvb.frontend != NULL) { | ||
140 | dvb_attach(mt2131_attach, port->dvb.frontend, | ||
141 | &i2c_bus->i2c_adap, | ||
142 | &hauppauge_generic_tunerconfig, 0); | ||
143 | } | ||
144 | break; | ||
145 | case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP: | ||
146 | i2c_bus = &dev->i2c_bus[0]; | ||
147 | port->dvb.frontend = dvb_attach(lgdt330x_attach, | ||
148 | &fusionhdtv_5_express, | ||
149 | &i2c_bus->i2c_adap); | ||
150 | if (port->dvb.frontend != NULL) { | ||
151 | dvb_attach(dvb_pll_attach, port->dvb.frontend, 0x61, | ||
152 | &i2c_bus->i2c_adap, DVB_PLL_LG_TDVS_H06XF); | ||
153 | } | ||
154 | break; | ||
155 | default: | ||
156 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", | ||
157 | dev->name); | ||
158 | break; | ||
159 | } | ||
160 | if (NULL == port->dvb.frontend) { | ||
161 | printk("%s: frontend initialization failed\n", dev->name); | ||
162 | return -1; | ||
163 | } | ||
164 | |||
165 | /* Put the analog decoder in standby to keep it quiet */ | ||
166 | cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL); | ||
167 | |||
168 | /* register everything */ | ||
169 | return videobuf_dvb_register(&port->dvb, THIS_MODULE, port, | ||
170 | &dev->pci->dev); | ||
171 | } | ||
172 | |||
173 | int cx23885_dvb_register(struct cx23885_tsport *port) | ||
174 | { | ||
175 | struct cx23885_dev *dev = port->dev; | ||
176 | int err; | ||
177 | |||
178 | dprintk(1, "%s\n", __FUNCTION__); | ||
179 | dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", | ||
180 | dev->board, | ||
181 | dev->name, | ||
182 | dev->pci_bus, | ||
183 | dev->pci_slot); | ||
184 | |||
185 | err = -ENODEV; | ||
186 | |||
187 | /* dvb stuff */ | ||
188 | printk("%s: cx23885 based dvb card\n", dev->name); | ||
189 | videobuf_queue_pci_init(&port->dvb.dvbq, &dvb_qops, dev->pci, &port->slock, | ||
190 | V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, | ||
191 | sizeof(struct cx23885_buffer), port); | ||
192 | err = dvb_register(port); | ||
193 | if (err != 0) | ||
194 | printk("%s() dvb_register failed err = %d\n", __FUNCTION__, err); | ||
195 | |||
196 | return err; | ||
197 | } | ||
198 | |||
199 | int cx23885_dvb_unregister(struct cx23885_tsport *port) | ||
200 | { | ||
201 | /* dvb */ | ||
202 | if(port->dvb.frontend) | ||
203 | videobuf_dvb_unregister(&port->dvb); | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | /* | ||
209 | * Local variables: | ||
210 | * c-basic-offset: 8 | ||
211 | * End: | ||
212 | * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off | ||
213 | */ | ||
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c new file mode 100644 index 000000000000..b517c8b5a566 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-i2c.c | |||
@@ -0,0 +1,382 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885 PCIe bridge | ||
3 | * | ||
4 | * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/moduleparam.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <asm/io.h> | ||
27 | |||
28 | #include "cx23885.h" | ||
29 | |||
30 | #include <media/v4l2-common.h> | ||
31 | |||
32 | static unsigned int i2c_debug = 0; | ||
33 | module_param(i2c_debug, int, 0644); | ||
34 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | ||
35 | |||
36 | static unsigned int i2c_scan = 0; | ||
37 | module_param(i2c_scan, int, 0444); | ||
38 | MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); | ||
39 | |||
40 | #define dprintk(level,fmt, arg...) if (i2c_debug >= level) \ | ||
41 | printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg) | ||
42 | |||
43 | #define I2C_WAIT_DELAY 32 | ||
44 | #define I2C_WAIT_RETRY 64 | ||
45 | |||
46 | #define I2C_EXTEND (1 << 3) | ||
47 | #define I2C_NOSTOP (1 << 4) | ||
48 | |||
49 | static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap) | ||
50 | { | ||
51 | struct cx23885_i2c *bus = i2c_adap->algo_data; | ||
52 | struct cx23885_dev *dev = bus->dev; | ||
53 | return cx_read(bus->reg_stat) & 0x01; | ||
54 | } | ||
55 | |||
56 | static inline int i2c_is_busy(struct i2c_adapter *i2c_adap) | ||
57 | { | ||
58 | struct cx23885_i2c *bus = i2c_adap->algo_data; | ||
59 | struct cx23885_dev *dev = bus->dev; | ||
60 | return cx_read(bus->reg_stat) & 0x02 ? 1 : 0; | ||
61 | } | ||
62 | |||
63 | static int i2c_wait_done(struct i2c_adapter *i2c_adap) | ||
64 | { | ||
65 | int count; | ||
66 | |||
67 | for (count = 0; count < I2C_WAIT_RETRY; count++) { | ||
68 | if (!i2c_is_busy(i2c_adap)) | ||
69 | break; | ||
70 | udelay(I2C_WAIT_DELAY); | ||
71 | } | ||
72 | |||
73 | if (I2C_WAIT_RETRY == count) | ||
74 | return 0; | ||
75 | |||
76 | return 1; | ||
77 | } | ||
78 | |||
79 | static int i2c_sendbytes(struct i2c_adapter *i2c_adap, | ||
80 | const struct i2c_msg *msg, int last) | ||
81 | { | ||
82 | struct cx23885_i2c *bus = i2c_adap->algo_data; | ||
83 | struct cx23885_dev *dev = bus->dev; | ||
84 | u32 wdata, addr, ctrl; | ||
85 | int retval, cnt; | ||
86 | |||
87 | dprintk(1, "%s()\n", __FUNCTION__); | ||
88 | /* Deal with i2c probe functions with zero payload */ | ||
89 | if (msg->len == 0) { | ||
90 | cx_write(bus->reg_addr, msg->addr << 25); | ||
91 | cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2)); | ||
92 | if (!i2c_wait_done(i2c_adap)) | ||
93 | return -EIO; | ||
94 | if (!i2c_slave_did_ack(i2c_adap)) | ||
95 | return -EIO; | ||
96 | |||
97 | dprintk(1, "%s() returns 0\n", __FUNCTION__); | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | |||
102 | /* dev, reg + first byte */ | ||
103 | addr = (msg->addr << 25) | msg->buf[0]; | ||
104 | wdata = msg->buf[0]; | ||
105 | ctrl = bus->i2c_period | (1 << 12) | (1 << 2); | ||
106 | |||
107 | if (msg->len > 1) | ||
108 | ctrl |= I2C_NOSTOP | I2C_EXTEND; | ||
109 | |||
110 | cx_write(bus->reg_addr, addr); | ||
111 | cx_write(bus->reg_wdata, wdata); | ||
112 | cx_write(bus->reg_ctrl, ctrl); | ||
113 | |||
114 | retval = i2c_wait_done(i2c_adap); | ||
115 | if (retval < 0) | ||
116 | goto err; | ||
117 | if (retval == 0) | ||
118 | goto eio; | ||
119 | if (i2c_debug) { | ||
120 | printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]); | ||
121 | if (!(ctrl & I2C_NOSTOP)) | ||
122 | printk(" >\n"); | ||
123 | } | ||
124 | |||
125 | for (cnt = 1; cnt < msg->len; cnt++ ) { | ||
126 | /* following bytes */ | ||
127 | wdata = msg->buf[cnt]; | ||
128 | ctrl = bus->i2c_period | (1 << 12) | (1 << 2); | ||
129 | |||
130 | if (cnt < msg->len-1 || !last) | ||
131 | ctrl |= I2C_NOSTOP | I2C_EXTEND; | ||
132 | |||
133 | cx_write(bus->reg_addr, addr); | ||
134 | cx_write(bus->reg_wdata, wdata); | ||
135 | cx_write(bus->reg_ctrl, ctrl); | ||
136 | |||
137 | retval = i2c_wait_done(i2c_adap); | ||
138 | if (retval < 0) | ||
139 | goto err; | ||
140 | if (retval == 0) | ||
141 | goto eio; | ||
142 | if (i2c_debug) { | ||
143 | printk(" %02x", msg->buf[cnt]); | ||
144 | if (!(ctrl & I2C_NOSTOP)) | ||
145 | printk(" >\n"); | ||
146 | } | ||
147 | } | ||
148 | return msg->len; | ||
149 | |||
150 | eio: | ||
151 | retval = -EIO; | ||
152 | err: | ||
153 | printk(" ERR: %d\n", retval); | ||
154 | return retval; | ||
155 | } | ||
156 | |||
157 | static int i2c_readbytes(struct i2c_adapter *i2c_adap, | ||
158 | const struct i2c_msg *msg, int last) | ||
159 | { | ||
160 | struct cx23885_i2c *bus = i2c_adap->algo_data; | ||
161 | struct cx23885_dev *dev = bus->dev; | ||
162 | u32 ctrl, cnt; | ||
163 | int retval; | ||
164 | |||
165 | dprintk(1, "%s()\n", __FUNCTION__); | ||
166 | |||
167 | /* Deal with i2c probe functions with zero payload */ | ||
168 | if (msg->len == 0) { | ||
169 | cx_write(bus->reg_addr, msg->addr << 25); | ||
170 | cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1); | ||
171 | if (!i2c_wait_done(i2c_adap)) | ||
172 | return -EIO; | ||
173 | if (!i2c_slave_did_ack(i2c_adap)) | ||
174 | return -EIO; | ||
175 | |||
176 | |||
177 | dprintk(1, "%s() returns 0\n", __FUNCTION__); | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | for(cnt = 0; cnt < msg->len; cnt++) { | ||
182 | |||
183 | ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1; | ||
184 | |||
185 | if (cnt < msg->len-1 || !last) | ||
186 | ctrl |= I2C_NOSTOP | I2C_EXTEND; | ||
187 | |||
188 | cx_write(bus->reg_addr, msg->addr << 25); | ||
189 | cx_write(bus->reg_ctrl, ctrl); | ||
190 | |||
191 | retval = i2c_wait_done(i2c_adap); | ||
192 | if (retval < 0) | ||
193 | goto err; | ||
194 | if (retval == 0) | ||
195 | goto eio; | ||
196 | msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff; | ||
197 | if (i2c_debug) { | ||
198 | if (!(ctrl & I2C_NOSTOP)) | ||
199 | printk(" <R %02x", (msg->addr << 1) +1); | ||
200 | printk(" =%02x", msg->buf[cnt]); | ||
201 | if (!(ctrl & I2C_NOSTOP)) | ||
202 | printk(" >\n"); | ||
203 | } | ||
204 | } | ||
205 | return msg->len; | ||
206 | |||
207 | eio: | ||
208 | retval = -EIO; | ||
209 | err: | ||
210 | printk(" ERR: %d\n", retval); | ||
211 | return retval; | ||
212 | } | ||
213 | |||
214 | static int i2c_xfer(struct i2c_adapter *i2c_adap, | ||
215 | struct i2c_msg *msgs, int num) | ||
216 | { | ||
217 | struct cx23885_i2c *bus = i2c_adap->algo_data; | ||
218 | struct cx23885_dev *dev = bus->dev; | ||
219 | int i, retval = 0; | ||
220 | |||
221 | dprintk(1, "%s(num = %d)\n", __FUNCTION__, num); | ||
222 | |||
223 | for (i = 0 ; i < num; i++) { | ||
224 | dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n", | ||
225 | __FUNCTION__, num, msgs[i].addr, msgs[i].len); | ||
226 | if (msgs[i].flags & I2C_M_RD) { | ||
227 | /* read */ | ||
228 | retval = i2c_readbytes(i2c_adap, &msgs[i], i+1 == num); | ||
229 | if (retval < 0) | ||
230 | goto err; | ||
231 | } else { | ||
232 | /* write */ | ||
233 | retval = i2c_sendbytes(i2c_adap, &msgs[i], i+1 == num); | ||
234 | if (retval < 0) | ||
235 | goto err; | ||
236 | } | ||
237 | } | ||
238 | return num; | ||
239 | |||
240 | err: | ||
241 | return retval; | ||
242 | } | ||
243 | |||
244 | static int attach_inform(struct i2c_client *client) | ||
245 | { | ||
246 | struct cx23885_dev *dev = i2c_get_adapdata(client->adapter); | ||
247 | |||
248 | dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", | ||
249 | client->driver->driver.name, client->addr, client->name); | ||
250 | |||
251 | if (!client->driver->command) | ||
252 | return 0; | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static int detach_inform(struct i2c_client *client) | ||
258 | { | ||
259 | struct cx23885_dev *dev = i2c_get_adapdata(client->adapter); | ||
260 | |||
261 | dprintk(1, "i2c detach [client=%s]\n", client->name); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | void cx23885_call_i2c_clients(struct cx23885_i2c *bus, | ||
267 | unsigned int cmd, void *arg) | ||
268 | { | ||
269 | if (bus->i2c_rc != 0) | ||
270 | return; | ||
271 | |||
272 | i2c_clients_command(&bus->i2c_adap, cmd, arg); | ||
273 | } | ||
274 | |||
275 | static int cx23885_algo_control(struct i2c_adapter *adap, | ||
276 | unsigned int cmd, unsigned long arg) | ||
277 | { | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static u32 cx23885_functionality(struct i2c_adapter *adap) | ||
282 | { | ||
283 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; | ||
284 | } | ||
285 | |||
286 | static struct i2c_algorithm cx23885_i2c_algo_template = { | ||
287 | .master_xfer = i2c_xfer, | ||
288 | .algo_control = cx23885_algo_control, | ||
289 | .functionality = cx23885_functionality, | ||
290 | }; | ||
291 | |||
292 | /* ----------------------------------------------------------------------- */ | ||
293 | |||
294 | static struct i2c_adapter cx23885_i2c_adap_template = { | ||
295 | .name = "cx23885", | ||
296 | .owner = THIS_MODULE, | ||
297 | .id = I2C_HW_B_CX23885, | ||
298 | .algo = &cx23885_i2c_algo_template, | ||
299 | .client_register = attach_inform, | ||
300 | .client_unregister = detach_inform, | ||
301 | }; | ||
302 | |||
303 | static struct i2c_client cx23885_i2c_client_template = { | ||
304 | .name = "cx23885 internal", | ||
305 | }; | ||
306 | |||
307 | static char *i2c_devs[128] = { | ||
308 | [ 0x1c >> 1 ] = "lgdt3303", | ||
309 | [ 0x86 >> 1 ] = "tda9887", | ||
310 | [ 0x32 >> 1 ] = "cx24227", | ||
311 | [ 0x88 >> 1 ] = "cx25837", | ||
312 | [ 0x84 >> 1 ] = "tda8295", | ||
313 | [ 0xa0 >> 1 ] = "eeprom", | ||
314 | [ 0xc0 >> 1 ] = "tuner/mt2131/tda8275", | ||
315 | [ 0xc2 >> 1 ] = "tuner/mt2131/tda8275", | ||
316 | }; | ||
317 | |||
318 | static void do_i2c_scan(char *name, struct i2c_client *c) | ||
319 | { | ||
320 | unsigned char buf; | ||
321 | int i, rc; | ||
322 | |||
323 | for (i = 0; i < 128; i++) { | ||
324 | c->addr = i; | ||
325 | rc = i2c_master_recv(c, &buf, 0); | ||
326 | if (rc < 0) | ||
327 | continue; | ||
328 | printk("%s: i2c scan: found device @ 0x%x [%s]\n", | ||
329 | name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | /* init + register i2c algo-bit adapter */ | ||
334 | int cx23885_i2c_register(struct cx23885_i2c *bus) | ||
335 | { | ||
336 | struct cx23885_dev *dev = bus->dev; | ||
337 | |||
338 | dprintk(1, "%s(bus = %d)\n", __FUNCTION__, bus->nr); | ||
339 | |||
340 | memcpy(&bus->i2c_adap, &cx23885_i2c_adap_template, | ||
341 | sizeof(bus->i2c_adap)); | ||
342 | memcpy(&bus->i2c_algo, &cx23885_i2c_algo_template, | ||
343 | sizeof(bus->i2c_algo)); | ||
344 | memcpy(&bus->i2c_client, &cx23885_i2c_client_template, | ||
345 | sizeof(bus->i2c_client)); | ||
346 | |||
347 | bus->i2c_adap.dev.parent = &dev->pci->dev; | ||
348 | |||
349 | strlcpy(bus->i2c_adap.name, bus->dev->name, | ||
350 | sizeof(bus->i2c_adap.name)); | ||
351 | |||
352 | bus->i2c_algo.data = bus; | ||
353 | bus->i2c_adap.algo_data = bus; | ||
354 | i2c_add_adapter(&bus->i2c_adap); | ||
355 | |||
356 | bus->i2c_client.adapter = &bus->i2c_adap; | ||
357 | |||
358 | if (0 == bus->i2c_rc) { | ||
359 | printk("%s: i2c bus %d registered\n", dev->name, bus->nr); | ||
360 | if (i2c_scan) | ||
361 | do_i2c_scan(dev->name, &bus->i2c_client); | ||
362 | } else | ||
363 | printk("%s: i2c bus %d register FAILED\n", dev->name, bus->nr); | ||
364 | |||
365 | return bus->i2c_rc; | ||
366 | } | ||
367 | |||
368 | int cx23885_i2c_unregister(struct cx23885_i2c *bus) | ||
369 | { | ||
370 | i2c_del_adapter(&bus->i2c_adap); | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | /* ----------------------------------------------------------------------- */ | ||
375 | |||
376 | EXPORT_SYMBOL(cx23885_call_i2c_clients); | ||
377 | |||
378 | /* | ||
379 | * Local variables: | ||
380 | * c-basic-offset: 8 | ||
381 | * End: | ||
382 | */ | ||
diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h new file mode 100644 index 000000000000..162169f9091b --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-reg.h | |||
@@ -0,0 +1,431 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885 PCIe bridge | ||
3 | * | ||
4 | * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef _CX23885_REG_H_ | ||
23 | #define _CX23885_REG_H_ | ||
24 | |||
25 | /* | ||
26 | Address Map | ||
27 | 0x00000000 -> 0x00009000 TX SRAM (Fifos) | ||
28 | 0x00010000 -> 0x00013c00 RX SRAM CMDS + CDT | ||
29 | |||
30 | EACH CMDS struct is 0x80 bytes long | ||
31 | |||
32 | DMAx_PTR1 = 0x03040 address of first cluster | ||
33 | DMAx_PTR2 = 0x10600 address of the CDT | ||
34 | DMAx_CNT1 = cluster size in (bytes >> 4) -1 | ||
35 | DMAx_CNT2 = total cdt size for all entries >> 3 | ||
36 | |||
37 | Cluster Descriptor entry = 4 DWORDS | ||
38 | DWORD 0 -> ptr to cluster | ||
39 | DWORD 1 Reserved | ||
40 | DWORD 2 Reserved | ||
41 | DWORD 3 Reserved | ||
42 | |||
43 | Channel manager Data Structure entry = 20 DWORD | ||
44 | 0 IntialProgramCounterLow | ||
45 | 1 IntialProgramCounterHigh | ||
46 | 2 ClusterDescriptorTableBase | ||
47 | 3 ClusterDescriptorTableSize | ||
48 | 4 InstructionQueueBase | ||
49 | 5 InstructionQueueSize | ||
50 | ... Reserved | ||
51 | 19 Reserved | ||
52 | */ | ||
53 | |||
54 | /* Risc Instructions */ | ||
55 | #define RISC_CNT_INC 0x00010000 | ||
56 | #define RISC_CNT_RESET 0x00030000 | ||
57 | #define RISC_IRQ1 0x01000000 | ||
58 | #define RISC_IRQ2 0x02000000 | ||
59 | #define RISC_EOL 0x04000000 | ||
60 | #define RISC_SOL 0x08000000 | ||
61 | #define RISC_WRITE 0x10000000 | ||
62 | #define RISC_SKIP 0x20000000 | ||
63 | #define RISC_JUMP 0x70000000 | ||
64 | #define RISC_SYNC 0x80000000 | ||
65 | #define RISC_RESYNC 0x80008000 | ||
66 | #define RISC_READ 0x90000000 | ||
67 | #define RISC_WRITERM 0xB0000000 | ||
68 | #define RISC_WRITECM 0xC0000000 | ||
69 | #define RISC_WRITECR 0xD0000000 | ||
70 | #define RISC_WRITEC 0x50000000 | ||
71 | #define RISC_READC 0xA0000000 | ||
72 | |||
73 | |||
74 | /* Audio and Video Core */ | ||
75 | #define HOST_REG1 0x00000000 | ||
76 | #define HOST_REG2 0x00000001 | ||
77 | #define HOST_REG3 0x00000002 | ||
78 | |||
79 | /* Chip Configuration Registers */ | ||
80 | #define CHIP_CTRL 0x00000100 | ||
81 | #define AFE_CTRL 0x00000104 | ||
82 | #define VID_PLL_INT_POST 0x00000108 | ||
83 | #define VID_PLL_FRAC 0x0000010C | ||
84 | #define AUX_PLL_INT_POST 0x00000110 | ||
85 | #define AUX_PLL_FRAC 0x00000114 | ||
86 | #define SYS_PLL_INT_POST 0x00000118 | ||
87 | #define SYS_PLL_FRAC 0x0000011C | ||
88 | #define PIN_CTRL 0x00000120 | ||
89 | #define AUD_IO_CTRL 0x00000124 | ||
90 | #define AUD_LOCK1 0x00000128 | ||
91 | #define AUD_LOCK2 0x0000012C | ||
92 | #define POWER_CTRL 0x00000130 | ||
93 | #define AFE_DIAG_CTRL1 0x00000134 | ||
94 | #define AFE_DIAG_CTRL3 0x0000013C | ||
95 | #define PLL_DIAG_CTRL 0x00000140 | ||
96 | #define AFE_CLK_OUT_CTRL 0x00000144 | ||
97 | #define DLL1_DIAG_CTRL 0x0000015C | ||
98 | |||
99 | /* GPIO[23:19] Output Enable */ | ||
100 | #define GPIO2_OUT_EN_REG 0x00000160 | ||
101 | /* GPIO[23:19] Data Registers */ | ||
102 | #define GPIO2 0x00000164 | ||
103 | |||
104 | #define IFADC_CTRL 0x00000180 | ||
105 | |||
106 | /* Infrared Remote Registers */ | ||
107 | #define IR_CNTRL_REG 0x00000200 | ||
108 | #define IR_TXCLK_REG 0x00000204 | ||
109 | #define IR_RXCLK_REG 0x00000208 | ||
110 | #define IR_CDUTY_REG 0x0000020C | ||
111 | #define IR_STAT_REG 0x00000210 | ||
112 | #define IR_IRQEN_REG 0x00000214 | ||
113 | #define IR_FILTR_REG 0x00000218 | ||
114 | #define IR_FIFO_REG 0x0000023C | ||
115 | |||
116 | /* Video Decoder Registers */ | ||
117 | #define MODE_CTRL 0x00000400 | ||
118 | #define OUT_CTRL1 0x00000404 | ||
119 | #define OUT_CTRL2 0x00000408 | ||
120 | #define GEN_STAT 0x0000040C | ||
121 | #define INT_STAT_MASK 0x00000410 | ||
122 | #define LUMA_CTRL 0x00000414 | ||
123 | #define HSCALE_CTRL 0x00000418 | ||
124 | #define VSCALE_CTRL 0x0000041C | ||
125 | #define CHROMA_CTRL 0x00000420 | ||
126 | #define VBI_LINE_CTRL1 0x00000424 | ||
127 | #define VBI_LINE_CTRL2 0x00000428 | ||
128 | #define VBI_LINE_CTRL3 0x0000042C | ||
129 | #define VBI_LINE_CTRL4 0x00000430 | ||
130 | #define VBI_LINE_CTRL5 0x00000434 | ||
131 | #define VBI_FC_CFG 0x00000438 | ||
132 | #define VBI_MISC_CFG1 0x0000043C | ||
133 | #define VBI_MISC_CFG2 0x00000440 | ||
134 | #define VBI_PAY1 0x00000444 | ||
135 | #define VBI_PAY2 0x00000448 | ||
136 | #define VBI_CUST1_CFG1 0x0000044C | ||
137 | #define VBI_CUST1_CFG2 0x00000450 | ||
138 | #define VBI_CUST1_CFG3 0x00000454 | ||
139 | #define VBI_CUST2_CFG1 0x00000458 | ||
140 | #define VBI_CUST2_CFG2 0x0000045C | ||
141 | #define VBI_CUST2_CFG3 0x00000460 | ||
142 | #define VBI_CUST3_CFG1 0x00000464 | ||
143 | #define VBI_CUST3_CFG2 0x00000468 | ||
144 | #define VBI_CUST3_CFG3 0x0000046C | ||
145 | #define HORIZ_TIM_CTRL 0x00000470 | ||
146 | #define VERT_TIM_CTRL 0x00000474 | ||
147 | #define SRC_COMB_CFG 0x00000478 | ||
148 | #define CHROMA_VBIOFF_CFG 0x0000047C | ||
149 | #define FIELD_COUNT 0x00000480 | ||
150 | #define MISC_TIM_CTRL 0x00000484 | ||
151 | #define DFE_CTRL1 0x00000488 | ||
152 | #define DFE_CTRL2 0x0000048C | ||
153 | #define DFE_CTRL3 0x00000490 | ||
154 | #define PLL_CTRL 0x00000494 | ||
155 | #define HTL_CTRL 0x00000498 | ||
156 | #define COMB_CTRL 0x0000049C | ||
157 | #define CRUSH_CTRL 0x000004A0 | ||
158 | #define SOFT_RST_CTRL 0x000004A4 | ||
159 | #define CX885_VERSION 0x000004B4 | ||
160 | #define VBI_PASS_CTRL 0x000004BC | ||
161 | |||
162 | /* Audio Decoder Registers */ | ||
163 | /* 8051 Configuration */ | ||
164 | #define DL_CTL 0x00000800 | ||
165 | #define STD_DET_STATUS 0x00000804 | ||
166 | #define STD_DET_CTL 0x00000808 | ||
167 | #define DW8051_INT 0x0000080C | ||
168 | #define GENERAL_CTL 0x00000810 | ||
169 | #define AAGC_CTL 0x00000814 | ||
170 | #define DEMATRIX_CTL 0x000008CC | ||
171 | #define PATH1_CTL1 0x000008D0 | ||
172 | #define PATH1_VOL_CTL 0x000008D4 | ||
173 | #define PATH1_EQ_CTL 0x000008D8 | ||
174 | #define PATH1_SC_CTL 0x000008DC | ||
175 | #define PATH2_CTL1 0x000008E0 | ||
176 | #define PATH2_VOL_CTL 0x000008E4 | ||
177 | #define PATH2_EQ_CTL 0x000008E8 | ||
178 | #define PATH2_SC_CTL 0x000008EC | ||
179 | |||
180 | /* Sample Rate Converter */ | ||
181 | #define SRC_CTL 0x000008F0 | ||
182 | #define SRC_LF_COEF 0x000008F4 | ||
183 | #define SRC1_CTL 0x000008F8 | ||
184 | #define SRC2_CTL 0x000008FC | ||
185 | #define SRC3_CTL 0x00000900 | ||
186 | #define SRC4_CTL 0x00000904 | ||
187 | #define SRC5_CTL 0x00000908 | ||
188 | #define SRC6_CTL 0x0000090C | ||
189 | #define BAND_OUT_SEL 0x00000910 | ||
190 | #define I2S_N_CTL 0x00000914 | ||
191 | #define I2S_OUT_CTL 0x00000918 | ||
192 | #define AUTOCONFIG_REG 0x000009C4 | ||
193 | |||
194 | /* Audio ADC Registers */ | ||
195 | #define DSM_CTRL1 0x00000000 | ||
196 | #define DSM_CTRL2 0x00000001 | ||
197 | #define CHP_EN_CTRL 0x00000002 | ||
198 | #define CHP_CLK_CTRL1 0x00000004 | ||
199 | #define CHP_CLK_CTRL2 0x00000005 | ||
200 | #define BG_REF_CTRL 0x00000006 | ||
201 | #define SD2_SW_CTRL1 0x00000008 | ||
202 | #define SD2_SW_CTRL2 0x00000009 | ||
203 | #define SD2_BIAS_CTRL 0x0000000A | ||
204 | #define AMP_BIAS_CTRL 0x0000000C | ||
205 | #define CH_PWR_CTRL1 0x0000000E | ||
206 | #define CH_PWR_CTRL2 0x0000000F | ||
207 | #define DSM_STATUS1 0x00000010 | ||
208 | #define DSM_STATUS2 0x00000011 | ||
209 | #define DIG_CTL1 0x00000012 | ||
210 | #define DIG_CTL2 0x00000013 | ||
211 | #define I2S_TX_CFG 0x0000001A | ||
212 | |||
213 | #define DEV_CNTRL2 0x00040000 | ||
214 | |||
215 | #define PCI_MSK_APB_DMA (1 << 12) | ||
216 | #define PCI_MSK_AL_WR (1 << 11) | ||
217 | #define PCI_MSK_AL_RD (1 << 10) | ||
218 | #define PCI_MSK_RISC_WR (1 << 9) | ||
219 | #define PCI_MSK_RISC_RD (1 << 8) | ||
220 | #define PCI_MSK_AUD_EXT (1 << 4) | ||
221 | #define PCI_MSK_AUD_INT (1 << 3) | ||
222 | #define PCI_MSK_VID_C (1 << 2) | ||
223 | #define PCI_MSK_VID_B (1 << 1) | ||
224 | #define PCI_MSK_VID_A 1 | ||
225 | #define PCI_INT_MSK 0x00040010 | ||
226 | |||
227 | #define PCI_INT_STAT 0x00040014 | ||
228 | #define PCI_INT_MSTAT 0x00040018 | ||
229 | |||
230 | #define VID_A_INT_MSK 0x00040020 | ||
231 | #define VID_A_INT_STAT 0x00040024 | ||
232 | #define VID_A_INT_MSTAT 0x00040028 | ||
233 | #define VID_A_INT_SSTAT 0x0004002C | ||
234 | |||
235 | #define VID_B_INT_MSK 0x00040030 | ||
236 | #define VID_B_INT_STAT 0x00040034 | ||
237 | #define VID_B_INT_MSTAT 0x00040038 | ||
238 | #define VID_B_INT_SSTAT 0x0004003C | ||
239 | |||
240 | #define VID_B_MSK_BAD_PKT (1 << 20) | ||
241 | #define VID_B_MSK_OPC_ERR (1 << 16) | ||
242 | #define VID_B_MSK_SYNC (1 << 12) | ||
243 | #define VID_B_MSK_OF (1 << 8) | ||
244 | #define VID_B_MSK_RISCI2 (1 << 4) | ||
245 | #define VID_B_MSK_RISCI1 1 | ||
246 | |||
247 | #define VID_C_MSK_BAD_PKT (1 << 20) | ||
248 | #define VID_C_MSK_OPC_ERR (1 << 16) | ||
249 | #define VID_C_MSK_SYNC (1 << 12) | ||
250 | #define VID_C_MSK_OF (1 << 8) | ||
251 | #define VID_C_MSK_RISCI2 (1 << 4) | ||
252 | #define VID_C_MSK_RISCI1 1 | ||
253 | |||
254 | /* A superset for testing purposes */ | ||
255 | #define VID_BC_MSK_BAD_PKT (1 << 20) | ||
256 | #define VID_BC_MSK_OPC_ERR (1 << 16) | ||
257 | #define VID_BC_MSK_SYNC (1 << 12) | ||
258 | #define VID_BC_MSK_OF (1 << 8) | ||
259 | #define VID_BC_MSK_RISCI2 (1 << 4) | ||
260 | #define VID_BC_MSK_RISCI1 1 | ||
261 | |||
262 | #define VID_C_INT_MSK 0x00040040 | ||
263 | #define VID_C_INT_STAT 0x00040044 | ||
264 | #define VID_C_INT_MSTAT 0x00040048 | ||
265 | #define VID_C_INT_SSTAT 0x0004004C | ||
266 | |||
267 | #define AUDIO_INT_INT_MSK 0x00040050 | ||
268 | #define AUDIO_INT_INT_STAT 0x00040054 | ||
269 | #define AUDIO_INT_INT_MSTAT 0x00040058 | ||
270 | #define AUDIO_INT_INT_SSTAT 0x0004005C | ||
271 | |||
272 | #define AUDIO_EXT_INT_MSK 0x00040060 | ||
273 | #define AUDIO_EXT_INT_STAT 0x00040064 | ||
274 | #define AUDIO_EXT_INT_MSTAT 0x00040068 | ||
275 | #define AUDIO_EXT_INT_SSTAT 0x0004006C | ||
276 | |||
277 | #define RDR_CFG0 0x00050000 | ||
278 | #define RDR_CFG1 0x00050004 | ||
279 | #define RDR_TLCTL0 0x00050318 | ||
280 | |||
281 | /* APB DMAC Current Buffer Pointer */ | ||
282 | #define DMA1_PTR1 0x00100000 | ||
283 | #define DMA2_PTR1 0x00100004 | ||
284 | #define DMA3_PTR1 0x00100008 | ||
285 | #define DMA4_PTR1 0x0010000C | ||
286 | #define DMA5_PTR1 0x00100010 | ||
287 | #define DMA6_PTR1 0x00100014 | ||
288 | #define DMA7_PTR1 0x00100018 | ||
289 | #define DMA8_PTR1 0x0010001C | ||
290 | |||
291 | /* APB DMAC Current Table Pointer */ | ||
292 | #define DMA1_PTR2 0x00100040 | ||
293 | #define DMA2_PTR2 0x00100044 | ||
294 | #define DMA3_PTR2 0x00100048 | ||
295 | #define DMA4_PTR2 0x0010004C | ||
296 | #define DMA5_PTR2 0x00100050 | ||
297 | #define DMA6_PTR2 0x00100054 | ||
298 | #define DMA7_PTR2 0x00100058 | ||
299 | #define DMA8_PTR2 0x0010005C | ||
300 | |||
301 | /* APB DMAC Buffer Limit */ | ||
302 | #define DMA1_CNT1 0x00100080 | ||
303 | #define DMA2_CNT1 0x00100084 | ||
304 | #define DMA3_CNT1 0x00100088 | ||
305 | #define DMA4_CNT1 0x0010008C | ||
306 | #define DMA5_CNT1 0x00100090 | ||
307 | #define DMA6_CNT1 0x00100094 | ||
308 | #define DMA7_CNT1 0x00100098 | ||
309 | #define DMA8_CNT1 0x0010009C | ||
310 | |||
311 | /* APB DMAC Table Size */ | ||
312 | #define DMA1_CNT2 0x001000C0 | ||
313 | #define DMA2_CNT2 0x001000C4 | ||
314 | #define DMA3_CNT2 0x001000C8 | ||
315 | #define DMA4_CNT2 0x001000CC | ||
316 | #define DMA5_CNT2 0x001000D0 | ||
317 | #define DMA6_CNT2 0x001000D4 | ||
318 | #define DMA7_CNT2 0x001000D8 | ||
319 | #define DMA8_CNT2 0x001000DC | ||
320 | |||
321 | /* Timer Counters */ | ||
322 | #define TM_CNT_LDW 0x00110000 | ||
323 | #define TM_CNT_UW 0x00110004 | ||
324 | #define TM_LMT_LDW 0x00110008 | ||
325 | #define TM_LMT_UW 0x0011000C | ||
326 | |||
327 | /* GPIO */ | ||
328 | #define GP0_IO 0x00110010 | ||
329 | #define GPIO_ISM 0x00110014 | ||
330 | #define SOFT_RESET 0x0011001C | ||
331 | |||
332 | /* GPIO (417 Microsoftcontroller) RW Data */ | ||
333 | #define MC417_RWD 0x00110020 | ||
334 | |||
335 | /* GPIO (417 Microsoftcontroller) Output Enable, Low Active */ | ||
336 | #define MC417_OEN 0x00110024 | ||
337 | #define MC417_CTL 0x00110028 | ||
338 | #define CLK_DELAY 0x00110048 | ||
339 | #define PAD_CTRL 0x0011004C | ||
340 | |||
341 | /* Video A Interface */ | ||
342 | #define VID_A_GPCNT 0x00130020 | ||
343 | #define VBI_A_GPCNT 0x00130024 | ||
344 | #define VID_A_GPCNT_CTL 0x00130030 | ||
345 | #define VBI_A_GPCNT_CTL 0x00130034 | ||
346 | #define VID_A_DMA_CTL 0x00130040 | ||
347 | #define VID_A_VIP_CTRL 0x00130080 | ||
348 | #define VID_A_PIXEL_FRMT 0x00130084 | ||
349 | #define VID_A_VBI_CTRL 0x00130088 | ||
350 | |||
351 | /* Video B Interface */ | ||
352 | #define VID_B_DMA 0x00130100 | ||
353 | #define VBI_B_DMA 0x00130108 | ||
354 | #define VID_B_GPCNT 0x00130120 | ||
355 | #define VBI_B_GPCNT 0x00130124 | ||
356 | #define VID_B_GPCNT_CTL 0x00130134 | ||
357 | #define VBI_B_GPCNT_CTL 0x00130138 | ||
358 | #define VID_B_DMA_CTL 0x00130140 | ||
359 | #define VID_B_SRC_SEL 0x00130144 | ||
360 | #define VID_B_LNGTH 0x00130150 | ||
361 | #define VID_B_HW_SOP_CTL 0x00130154 | ||
362 | #define VID_B_GEN_CTL 0x00130158 | ||
363 | #define VID_B_BD_PKT_STATUS 0x0013015C | ||
364 | #define VID_B_SOP_STATUS 0x00130160 | ||
365 | #define VID_B_FIFO_OVFL_STAT 0x00130164 | ||
366 | #define VID_B_VLD_MISC 0x00130168 | ||
367 | #define VID_B_TS_CLK_EN 0x0013016C | ||
368 | #define VID_B_VIP_CTRL 0x00130180 | ||
369 | #define VID_B_PIXEL_FRMT 0x00130184 | ||
370 | |||
371 | /* Video C Interface */ | ||
372 | #define VID_C_GPCNT 0x00130220 | ||
373 | #define VID_C_GPCNT_CTL 0x00130230 | ||
374 | #define VBI_C_GPCNT_CTL 0x00130234 | ||
375 | #define VID_C_DMA_CTL 0x00130240 | ||
376 | #define VID_C_LNGTH 0x00130250 | ||
377 | #define VID_C_HW_SOP_CTL 0x00130254 | ||
378 | #define VID_C_GEN_CTL 0x00130258 | ||
379 | #define VID_C_BD_PKT_STATUS 0x0013025C | ||
380 | #define VID_C_SOP_STATUS 0x00130260 | ||
381 | #define VID_C_FIFO_OVFL_STAT 0x00130264 | ||
382 | #define VID_C_VLD_MISC 0x00130268 | ||
383 | #define VID_C_TS_CLK_EN 0x0013026C | ||
384 | |||
385 | /* Internal Audio Interface */ | ||
386 | #define AUD_INT_A_GPCNT 0x00140020 | ||
387 | #define AUD_INT_B_GPCNT 0x00140024 | ||
388 | #define AUD_INT_A_GPCNT_CTL 0x00140030 | ||
389 | #define AUD_INT_B_GPCNT_CTL 0x00140034 | ||
390 | #define AUD_INT_DMA_CTL 0x00140040 | ||
391 | #define AUD_INT_A_LNGTH 0x00140050 | ||
392 | #define AUD_INT_B_LNGTH 0x00140054 | ||
393 | #define AUD_INT_A_MODE 0x00140058 | ||
394 | #define AUD_INT_B_MODE 0x0014005C | ||
395 | |||
396 | /* External Audio Interface */ | ||
397 | #define AUD_EXT_DMA 0x00140100 | ||
398 | #define AUD_EXT_GPCNT 0x00140120 | ||
399 | #define AUD_EXT_GPCNT_CTL 0x00140130 | ||
400 | #define AUD_EXT_DMA_CTL 0x00140140 | ||
401 | #define AUD_EXT_LNGTH 0x00140150 | ||
402 | #define AUD_EXT_A_MODE 0x00140158 | ||
403 | |||
404 | /* I2C Bus 1 */ | ||
405 | #define I2C1_ADDR 0x00180000 | ||
406 | #define I2C1_WDATA 0x00180004 | ||
407 | #define I2C1_CTRL 0x00180008 | ||
408 | #define I2C1_RDATA 0x0018000C | ||
409 | #define I2C1_STAT 0x00180010 | ||
410 | |||
411 | /* I2C Bus 2 */ | ||
412 | #define I2C2_ADDR 0x00190000 | ||
413 | #define I2C2_WDATA 0x00190004 | ||
414 | #define I2C2_CTRL 0x00190008 | ||
415 | #define I2C2_RDATA 0x0019000C | ||
416 | #define I2C2_STAT 0x00190010 | ||
417 | |||
418 | /* I2C Bus 3 */ | ||
419 | #define I2C3_ADDR 0x001A0000 | ||
420 | #define I2C3_WDATA 0x001A0004 | ||
421 | #define I2C3_CTRL 0x001A0008 | ||
422 | #define I2C3_RDATA 0x001A000C | ||
423 | #define I2C3_STAT 0x001A0010 | ||
424 | |||
425 | /* UART */ | ||
426 | #define UART_CTL 0x001B0000 | ||
427 | #define UART_BRD 0x001B0004 | ||
428 | #define UART_ISR 0x001B000C | ||
429 | #define UART_CNT 0x001B0010 | ||
430 | |||
431 | #endif /* _CX23885_REG_H_ */ | ||
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h new file mode 100644 index 000000000000..dec4dc2fcbb4 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885.h | |||
@@ -0,0 +1,301 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885 PCIe bridge | ||
3 | * | ||
4 | * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/pci.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/i2c-algo-bit.h> | ||
25 | #include <linux/kdev_t.h> | ||
26 | |||
27 | #include <media/v4l2-common.h> | ||
28 | #include <media/tuner.h> | ||
29 | #include <media/tveeprom.h> | ||
30 | #include <media/videobuf-dma-sg.h> | ||
31 | #include <media/videobuf-dvb.h> | ||
32 | |||
33 | #include "btcx-risc.h" | ||
34 | #include "cx23885-reg.h" | ||
35 | |||
36 | #include <linux/version.h> | ||
37 | #include <linux/mutex.h> | ||
38 | |||
39 | #define CX23885_VERSION_CODE KERNEL_VERSION(0,0,1) | ||
40 | |||
41 | #define UNSET (-1U) | ||
42 | |||
43 | #define CX23885_MAXBOARDS 8 | ||
44 | |||
45 | /* Max number of inputs by card */ | ||
46 | #define MAX_CX23885_INPUT 8 | ||
47 | |||
48 | #define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */ | ||
49 | |||
50 | #define CX23885_BOARD_NOAUTO UNSET | ||
51 | #define CX23885_BOARD_UNKNOWN 0 | ||
52 | #define CX23885_BOARD_HAUPPAUGE_HVR1800lp 1 | ||
53 | #define CX23885_BOARD_HAUPPAUGE_HVR1800 2 | ||
54 | #define CX23885_BOARD_HAUPPAUGE_HVR1250 3 | ||
55 | #define CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP 4 | ||
56 | |||
57 | enum cx23885_itype { | ||
58 | CX23885_VMUX_COMPOSITE1 = 1, | ||
59 | CX23885_VMUX_COMPOSITE2, | ||
60 | CX23885_VMUX_COMPOSITE3, | ||
61 | CX23885_VMUX_COMPOSITE4, | ||
62 | CX23885_VMUX_SVIDEO, | ||
63 | CX23885_VMUX_TELEVISION, | ||
64 | CX23885_VMUX_CABLE, | ||
65 | CX23885_VMUX_DVB, | ||
66 | CX23885_VMUX_DEBUG, | ||
67 | CX23885_RADIO, | ||
68 | }; | ||
69 | |||
70 | enum cx23885_src_sel_type { | ||
71 | CX23885_SRC_SEL_EXT_656_VIDEO = 0, | ||
72 | CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO | ||
73 | }; | ||
74 | |||
75 | /* buffer for one video frame */ | ||
76 | struct cx23885_buffer { | ||
77 | /* common v4l buffer stuff -- must be first */ | ||
78 | struct videobuf_buffer vb; | ||
79 | |||
80 | /* cx23885 specific */ | ||
81 | unsigned int bpl; | ||
82 | struct btcx_riscmem risc; | ||
83 | struct cx23885_fmt *fmt; | ||
84 | u32 count; | ||
85 | }; | ||
86 | |||
87 | struct cx23885_input { | ||
88 | enum cx23885_itype type; | ||
89 | unsigned int vmux; | ||
90 | u32 gpio0, gpio1, gpio2, gpio3; | ||
91 | }; | ||
92 | |||
93 | typedef enum { | ||
94 | CX23885_MPEG_UNDEFINED = 0, | ||
95 | CX23885_MPEG_DVB | ||
96 | } port_t; | ||
97 | |||
98 | struct cx23885_board { | ||
99 | char *name; | ||
100 | port_t portb, portc; | ||
101 | struct cx23885_input input[MAX_CX23885_INPUT]; | ||
102 | }; | ||
103 | |||
104 | struct cx23885_subid { | ||
105 | u16 subvendor; | ||
106 | u16 subdevice; | ||
107 | u32 card; | ||
108 | }; | ||
109 | |||
110 | struct cx23885_i2c { | ||
111 | struct cx23885_dev *dev; | ||
112 | |||
113 | int nr; | ||
114 | |||
115 | /* i2c i/o */ | ||
116 | struct i2c_adapter i2c_adap; | ||
117 | struct i2c_algo_bit_data i2c_algo; | ||
118 | struct i2c_client i2c_client; | ||
119 | u32 i2c_rc; | ||
120 | |||
121 | /* 885 registers used for raw addess */ | ||
122 | u32 i2c_period; | ||
123 | u32 reg_ctrl; | ||
124 | u32 reg_stat; | ||
125 | u32 reg_addr; | ||
126 | u32 reg_rdata; | ||
127 | u32 reg_wdata; | ||
128 | }; | ||
129 | |||
130 | struct cx23885_dmaqueue { | ||
131 | struct list_head active; | ||
132 | struct list_head queued; | ||
133 | struct timer_list timeout; | ||
134 | struct btcx_riscmem stopper; | ||
135 | u32 count; | ||
136 | }; | ||
137 | |||
138 | struct cx23885_tsport { | ||
139 | struct cx23885_dev *dev; | ||
140 | |||
141 | int nr; | ||
142 | int sram_chno; | ||
143 | |||
144 | struct videobuf_dvb dvb; | ||
145 | |||
146 | /* dma queues */ | ||
147 | struct cx23885_dmaqueue mpegq; | ||
148 | u32 ts_packet_size; | ||
149 | u32 ts_packet_count; | ||
150 | |||
151 | int width; | ||
152 | int height; | ||
153 | |||
154 | spinlock_t slock; | ||
155 | |||
156 | /* registers */ | ||
157 | u32 reg_gpcnt; | ||
158 | u32 reg_gpcnt_ctl; | ||
159 | u32 reg_dma_ctl; | ||
160 | u32 reg_lngth; | ||
161 | u32 reg_hw_sop_ctrl; | ||
162 | u32 reg_gen_ctrl; | ||
163 | u32 reg_bd_pkt_status; | ||
164 | u32 reg_sop_status; | ||
165 | u32 reg_fifo_ovfl_stat; | ||
166 | u32 reg_vld_misc; | ||
167 | u32 reg_ts_clk_en; | ||
168 | u32 reg_ts_int_msk; | ||
169 | u32 reg_ts_int_stat; | ||
170 | u32 reg_src_sel; | ||
171 | |||
172 | /* Default register vals */ | ||
173 | int pci_irqmask; | ||
174 | u32 dma_ctl_val; | ||
175 | u32 ts_int_msk_val; | ||
176 | u32 gen_ctrl_val; | ||
177 | u32 ts_clk_en_val; | ||
178 | u32 src_sel_val; | ||
179 | }; | ||
180 | |||
181 | struct cx23885_dev { | ||
182 | struct list_head devlist; | ||
183 | atomic_t refcount; | ||
184 | |||
185 | /* pci stuff */ | ||
186 | struct pci_dev *pci; | ||
187 | unsigned char pci_rev, pci_lat; | ||
188 | int pci_bus, pci_slot; | ||
189 | u32 __iomem *lmmio; | ||
190 | u8 __iomem *bmmio; | ||
191 | int pci_irqmask; | ||
192 | |||
193 | /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ | ||
194 | struct cx23885_i2c i2c_bus[3]; | ||
195 | |||
196 | int nr; | ||
197 | struct mutex lock; | ||
198 | |||
199 | /* board details */ | ||
200 | unsigned int board; | ||
201 | char name[32]; | ||
202 | |||
203 | struct cx23885_tsport ts1, ts2; | ||
204 | |||
205 | /* sram configuration */ | ||
206 | struct sram_channel *sram_channels; | ||
207 | |||
208 | enum { | ||
209 | CX23885_BRIDGE_UNDEFINED = 0, | ||
210 | CX23885_BRIDGE_885 = 885, | ||
211 | CX23885_BRIDGE_887 = 887, | ||
212 | } bridge; | ||
213 | }; | ||
214 | |||
215 | #define SRAM_CH01 0 /* Video A */ | ||
216 | #define SRAM_CH02 1 /* VBI A */ | ||
217 | #define SRAM_CH03 2 /* Video B */ | ||
218 | #define SRAM_CH04 3 /* Transport via B */ | ||
219 | #define SRAM_CH05 4 /* VBI B */ | ||
220 | #define SRAM_CH06 5 /* Video C */ | ||
221 | #define SRAM_CH07 6 /* Transport via C */ | ||
222 | #define SRAM_CH08 7 /* Audio Internal A */ | ||
223 | #define SRAM_CH09 8 /* Audio Internal B */ | ||
224 | #define SRAM_CH10 9 /* Audio External */ | ||
225 | #define SRAM_CH11 10 /* COMB_3D_N */ | ||
226 | #define SRAM_CH12 11 /* Comb 3D N1 */ | ||
227 | #define SRAM_CH13 12 /* Comb 3D N2 */ | ||
228 | #define SRAM_CH14 13 /* MOE Vid */ | ||
229 | #define SRAM_CH15 14 /* MOE RSLT */ | ||
230 | |||
231 | struct sram_channel { | ||
232 | char *name; | ||
233 | u32 cmds_start; | ||
234 | u32 ctrl_start; | ||
235 | u32 cdt; | ||
236 | u32 fifo_start;; | ||
237 | u32 fifo_size; | ||
238 | u32 ptr1_reg; | ||
239 | u32 ptr2_reg; | ||
240 | u32 cnt1_reg; | ||
241 | u32 cnt2_reg; | ||
242 | u32 jumponly; | ||
243 | }; | ||
244 | |||
245 | /* ----------------------------------------------------------- */ | ||
246 | |||
247 | #define cx_read(reg) readl(dev->lmmio + ((reg)>>2)) | ||
248 | #define cx_write(reg,value) writel((value), dev->lmmio + ((reg)>>2)) | ||
249 | |||
250 | #define cx_andor(reg,mask,value) \ | ||
251 | writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\ | ||
252 | ((value) & (mask)), dev->lmmio+((reg)>>2)) | ||
253 | |||
254 | #define cx_set(reg,bit) cx_andor((reg),(bit),(bit)) | ||
255 | #define cx_clear(reg,bit) cx_andor((reg),(bit),0) | ||
256 | |||
257 | extern int cx23885_sram_channel_setup(struct cx23885_dev *dev, | ||
258 | struct sram_channel *ch, | ||
259 | unsigned int bpl, u32 risc); | ||
260 | |||
261 | /* ----------------------------------------------------------- */ | ||
262 | /* cx23885-cards.c */ | ||
263 | |||
264 | extern struct cx23885_board cx23885_boards[]; | ||
265 | extern const unsigned int cx23885_bcount; | ||
266 | |||
267 | extern struct cx23885_subid cx23885_subids[]; | ||
268 | extern const unsigned int cx23885_idcount; | ||
269 | |||
270 | extern void cx23885_card_list(struct cx23885_dev *dev); | ||
271 | extern int cx23885_ir_init(struct cx23885_dev *dev); | ||
272 | extern void cx23885_gpio_setup(struct cx23885_dev *dev); | ||
273 | extern void cx23885_card_setup(struct cx23885_dev *dev); | ||
274 | extern void cx23885_card_setup_pre_i2c(struct cx23885_dev *dev); | ||
275 | |||
276 | extern int cx23885_dvb_register(struct cx23885_tsport *port); | ||
277 | extern int cx23885_dvb_unregister(struct cx23885_tsport *port); | ||
278 | |||
279 | extern int cx23885_buf_prepare(struct videobuf_queue *q, | ||
280 | struct cx23885_tsport *port, | ||
281 | struct cx23885_buffer *buf, | ||
282 | enum v4l2_field field); | ||
283 | |||
284 | extern void cx23885_buf_queue(struct cx23885_tsport *port, | ||
285 | struct cx23885_buffer *buf); | ||
286 | extern void cx23885_free_buffer(struct videobuf_queue *q, | ||
287 | struct cx23885_buffer *buf); | ||
288 | |||
289 | /* ----------------------------------------------------------- */ | ||
290 | /* cx23885-i2c.c */ | ||
291 | extern int cx23885_i2c_register(struct cx23885_i2c *bus); | ||
292 | extern int cx23885_i2c_unregister(struct cx23885_i2c *bus); | ||
293 | extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd, | ||
294 | void *arg); | ||
295 | |||
296 | /* | ||
297 | * Local variables: | ||
298 | * c-basic-offset: 8 | ||
299 | * End: | ||
300 | * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off | ||
301 | */ | ||
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index f897c1ebd5f3..3d46a776df36 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c | |||
@@ -157,13 +157,12 @@ void cx25840_audio_set_path(struct i2c_client *client) | |||
157 | { | 157 | { |
158 | struct cx25840_state *state = i2c_get_clientdata(client); | 158 | struct cx25840_state *state = i2c_get_clientdata(client); |
159 | 159 | ||
160 | /* assert soft reset */ | ||
161 | cx25840_and_or(client, 0x810, ~0x1, 0x01); | ||
162 | |||
160 | /* stop microcontroller */ | 163 | /* stop microcontroller */ |
161 | cx25840_and_or(client, 0x803, ~0x10, 0); | 164 | cx25840_and_or(client, 0x803, ~0x10, 0); |
162 | 165 | ||
163 | /* assert soft reset */ | ||
164 | if (!state->is_cx25836) | ||
165 | cx25840_and_or(client, 0x810, ~0x1, 0x01); | ||
166 | |||
167 | /* Mute everything to prevent the PFFT! */ | 166 | /* Mute everything to prevent the PFFT! */ |
168 | cx25840_write(client, 0x8d3, 0x1f); | 167 | cx25840_write(client, 0x8d3, 0x1f); |
169 | 168 | ||
@@ -181,32 +180,46 @@ void cx25840_audio_set_path(struct i2c_client *client) | |||
181 | 180 | ||
182 | set_audclk_freq(client, state->audclk_freq); | 181 | set_audclk_freq(client, state->audclk_freq); |
183 | 182 | ||
184 | /* deassert soft reset */ | ||
185 | if (!state->is_cx25836) | ||
186 | cx25840_and_or(client, 0x810, ~0x1, 0x00); | ||
187 | |||
188 | if (state->aud_input != CX25840_AUDIO_SERIAL) { | 183 | if (state->aud_input != CX25840_AUDIO_SERIAL) { |
189 | /* When the microcontroller detects the | 184 | /* When the microcontroller detects the |
190 | * audio format, it will unmute the lines */ | 185 | * audio format, it will unmute the lines */ |
191 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | 186 | cx25840_and_or(client, 0x803, ~0x10, 0x10); |
192 | } | 187 | } |
188 | |||
189 | /* deassert soft reset */ | ||
190 | cx25840_and_or(client, 0x810, ~0x1, 0x00); | ||
193 | } | 191 | } |
194 | 192 | ||
195 | static int get_volume(struct i2c_client *client) | 193 | static int get_volume(struct i2c_client *client) |
196 | { | 194 | { |
195 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
196 | int vol; | ||
197 | |||
198 | if (state->unmute_volume >= 0) | ||
199 | return state->unmute_volume; | ||
200 | |||
197 | /* Volume runs +18dB to -96dB in 1/2dB steps | 201 | /* Volume runs +18dB to -96dB in 1/2dB steps |
198 | * change to fit the msp3400 -114dB to +12dB range */ | 202 | * change to fit the msp3400 -114dB to +12dB range */ |
199 | 203 | ||
200 | /* check PATH1_VOLUME */ | 204 | /* check PATH1_VOLUME */ |
201 | int vol = 228 - cx25840_read(client, 0x8d4); | 205 | vol = 228 - cx25840_read(client, 0x8d4); |
202 | vol = (vol / 2) + 23; | 206 | vol = (vol / 2) + 23; |
203 | return vol << 9; | 207 | return vol << 9; |
204 | } | 208 | } |
205 | 209 | ||
206 | static void set_volume(struct i2c_client *client, int volume) | 210 | static void set_volume(struct i2c_client *client, int volume) |
207 | { | 211 | { |
208 | /* First convert the volume to msp3400 values (0-127) */ | 212 | struct cx25840_state *state = i2c_get_clientdata(client); |
209 | int vol = volume >> 9; | 213 | int vol; |
214 | |||
215 | if (state->unmute_volume >= 0) { | ||
216 | state->unmute_volume = volume; | ||
217 | return; | ||
218 | } | ||
219 | |||
220 | /* Convert the volume to msp3400 values (0-127) */ | ||
221 | vol = volume >> 9; | ||
222 | |||
210 | /* now scale it up to cx25840 values | 223 | /* now scale it up to cx25840 values |
211 | * -114dB to -96dB maps to 0 | 224 | * -114dB to -96dB maps to 0 |
212 | * this should be 19, but in my testing that was 4dB too loud */ | 225 | * this should be 19, but in my testing that was 4dB too loud */ |
@@ -284,30 +297,26 @@ static void set_balance(struct i2c_client *client, int balance) | |||
284 | 297 | ||
285 | static int get_mute(struct i2c_client *client) | 298 | static int get_mute(struct i2c_client *client) |
286 | { | 299 | { |
287 | /* check SRC1_MUTE_EN */ | 300 | struct cx25840_state *state = i2c_get_clientdata(client); |
288 | return cx25840_read(client, 0x8d3) & 0x2 ? 1 : 0; | 301 | |
302 | return state->unmute_volume >= 0; | ||
289 | } | 303 | } |
290 | 304 | ||
291 | static void set_mute(struct i2c_client *client, int mute) | 305 | static void set_mute(struct i2c_client *client, int mute) |
292 | { | 306 | { |
293 | struct cx25840_state *state = i2c_get_clientdata(client); | 307 | struct cx25840_state *state = i2c_get_clientdata(client); |
294 | 308 | ||
295 | if (state->aud_input != CX25840_AUDIO_SERIAL) { | 309 | if (mute && state->unmute_volume == -1) { |
296 | /* Must turn off microcontroller in order to mute sound. | 310 | int vol = get_volume(client); |
297 | * Not sure if this is the best method, but it does work. | 311 | |
298 | * If the microcontroller is running, then it will undo any | 312 | set_volume(client, 0); |
299 | * changes to the mute register. */ | 313 | state->unmute_volume = vol; |
300 | if (mute) { | 314 | } |
301 | /* disable microcontroller */ | 315 | else if (!mute && state->unmute_volume != -1) { |
302 | cx25840_and_or(client, 0x803, ~0x10, 0x00); | 316 | int vol = state->unmute_volume; |
303 | cx25840_write(client, 0x8d3, 0x1f); | 317 | |
304 | } else { | 318 | state->unmute_volume = -1; |
305 | /* enable microcontroller */ | 319 | set_volume(client, vol); |
306 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
307 | } | ||
308 | } else { | ||
309 | /* SRC1_MUTE_EN */ | ||
310 | cx25840_and_or(client, 0x8d3, ~0x2, mute ? 0x02 : 0x00); | ||
311 | } | 320 | } |
312 | } | 321 | } |
313 | 322 | ||
@@ -319,18 +328,18 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) | |||
319 | 328 | ||
320 | switch (cmd) { | 329 | switch (cmd) { |
321 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | 330 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: |
331 | if (!state->is_cx25836) | ||
332 | cx25840_and_or(client, 0x810, ~0x1, 1); | ||
322 | if (state->aud_input != CX25840_AUDIO_SERIAL) { | 333 | if (state->aud_input != CX25840_AUDIO_SERIAL) { |
323 | cx25840_and_or(client, 0x803, ~0x10, 0); | 334 | cx25840_and_or(client, 0x803, ~0x10, 0); |
324 | cx25840_write(client, 0x8d3, 0x1f); | 335 | cx25840_write(client, 0x8d3, 0x1f); |
325 | } | 336 | } |
326 | if (!state->is_cx25836) | ||
327 | cx25840_and_or(client, 0x810, ~0x1, 1); | ||
328 | retval = set_audclk_freq(client, *(u32 *)arg); | 337 | retval = set_audclk_freq(client, *(u32 *)arg); |
329 | if (!state->is_cx25836) | ||
330 | cx25840_and_or(client, 0x810, ~0x1, 0); | ||
331 | if (state->aud_input != CX25840_AUDIO_SERIAL) { | 338 | if (state->aud_input != CX25840_AUDIO_SERIAL) { |
332 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | 339 | cx25840_and_or(client, 0x803, ~0x10, 0x10); |
333 | } | 340 | } |
341 | if (!state->is_cx25836) | ||
342 | cx25840_and_or(client, 0x810, ~0x1, 0); | ||
334 | return retval; | 343 | return retval; |
335 | 344 | ||
336 | case VIDIOC_G_CTRL: | 345 | case VIDIOC_G_CTRL: |
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 67bda9f9a44b..15f191e170d2 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/videodev2.h> | 35 | #include <linux/videodev2.h> |
36 | #include <linux/i2c.h> | 36 | #include <linux/i2c.h> |
37 | #include <linux/delay.h> | ||
37 | #include <media/v4l2-common.h> | 38 | #include <media/v4l2-common.h> |
38 | #include <media/v4l2-chip-ident.h> | 39 | #include <media/v4l2-chip-ident.h> |
39 | #include <media/cx25840.h> | 40 | #include <media/cx25840.h> |
@@ -133,7 +134,9 @@ static void init_dll1(struct i2c_client *client) | |||
133 | cx25840_write(client, 0x159, 0x23); | 134 | cx25840_write(client, 0x159, 0x23); |
134 | cx25840_write(client, 0x15a, 0x87); | 135 | cx25840_write(client, 0x15a, 0x87); |
135 | cx25840_write(client, 0x15b, 0x06); | 136 | cx25840_write(client, 0x15b, 0x06); |
137 | udelay(10); | ||
136 | cx25840_write(client, 0x159, 0xe1); | 138 | cx25840_write(client, 0x159, 0xe1); |
139 | udelay(10); | ||
137 | cx25840_write(client, 0x15a, 0x86); | 140 | cx25840_write(client, 0x15a, 0x86); |
138 | cx25840_write(client, 0x159, 0xe0); | 141 | cx25840_write(client, 0x159, 0xe0); |
139 | cx25840_write(client, 0x159, 0xe1); | 142 | cx25840_write(client, 0x159, 0xe1); |
@@ -147,6 +150,7 @@ static void init_dll2(struct i2c_client *client) | |||
147 | cx25840_write(client, 0x15d, 0xe3); | 150 | cx25840_write(client, 0x15d, 0xe3); |
148 | cx25840_write(client, 0x15e, 0x86); | 151 | cx25840_write(client, 0x15e, 0x86); |
149 | cx25840_write(client, 0x15f, 0x06); | 152 | cx25840_write(client, 0x15f, 0x06); |
153 | udelay(10); | ||
150 | cx25840_write(client, 0x15d, 0xe1); | 154 | cx25840_write(client, 0x15d, 0xe1); |
151 | cx25840_write(client, 0x15d, 0xe0); | 155 | cx25840_write(client, 0x15d, 0xe0); |
152 | cx25840_write(client, 0x15d, 0xe1); | 156 | cx25840_write(client, 0x15d, 0xe1); |
@@ -165,9 +169,7 @@ static void cx25836_initialize(struct i2c_client *client) | |||
165 | /* 3c. */ | 169 | /* 3c. */ |
166 | cx25840_and_or(client, 0x159, ~0x02, 0x02); | 170 | cx25840_and_or(client, 0x159, ~0x02, 0x02); |
167 | /* 3d. */ | 171 | /* 3d. */ |
168 | /* There should be a 10-us delay here, but since the | 172 | udelay(10); |
169 | i2c bus already has a 10-us delay we don't need to do | ||
170 | anything */ | ||
171 | /* 3e. */ | 173 | /* 3e. */ |
172 | cx25840_and_or(client, 0x159, ~0x02, 0x00); | 174 | cx25840_and_or(client, 0x159, ~0x02, 0x00); |
173 | /* 3f. */ | 175 | /* 3f. */ |
@@ -179,9 +181,18 @@ static void cx25836_initialize(struct i2c_client *client) | |||
179 | cx25840_and_or(client, 0x15b, ~0x1e, 0x10); | 181 | cx25840_and_or(client, 0x15b, ~0x1e, 0x10); |
180 | } | 182 | } |
181 | 183 | ||
182 | static void cx25840_initialize(struct i2c_client *client, int loadfw) | 184 | static void cx25840_work_handler(struct work_struct *work) |
183 | { | 185 | { |
186 | struct cx25840_state *state = container_of(work, struct cx25840_state, fw_work); | ||
187 | cx25840_loadfw(state->c); | ||
188 | wake_up(&state->fw_wait); | ||
189 | } | ||
190 | |||
191 | static void cx25840_initialize(struct i2c_client *client) | ||
192 | { | ||
193 | DEFINE_WAIT(wait); | ||
184 | struct cx25840_state *state = i2c_get_clientdata(client); | 194 | struct cx25840_state *state = i2c_get_clientdata(client); |
195 | struct workqueue_struct *q; | ||
185 | 196 | ||
186 | /* datasheet startup in numbered steps, refer to page 3-77 */ | 197 | /* datasheet startup in numbered steps, refer to page 3-77 */ |
187 | /* 2. */ | 198 | /* 2. */ |
@@ -197,8 +208,19 @@ static void cx25840_initialize(struct i2c_client *client, int loadfw) | |||
197 | cx25840_write(client, 0x13c, 0x01); | 208 | cx25840_write(client, 0x13c, 0x01); |
198 | cx25840_write(client, 0x13c, 0x00); | 209 | cx25840_write(client, 0x13c, 0x00); |
199 | /* 5. */ | 210 | /* 5. */ |
200 | if (loadfw) | 211 | /* Do the firmware load in a work handler to prevent. |
201 | cx25840_loadfw(client); | 212 | Otherwise the kernel is blocked waiting for the |
213 | bit-banging i2c interface to finish uploading the | ||
214 | firmware. */ | ||
215 | INIT_WORK(&state->fw_work, cx25840_work_handler); | ||
216 | init_waitqueue_head(&state->fw_wait); | ||
217 | q = create_singlethread_workqueue("cx25840_fw"); | ||
218 | prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE); | ||
219 | queue_work(q, &state->fw_work); | ||
220 | schedule(); | ||
221 | finish_wait(&state->fw_wait, &wait); | ||
222 | destroy_workqueue(q); | ||
223 | |||
202 | /* 6. */ | 224 | /* 6. */ |
203 | cx25840_write(client, 0x115, 0x8c); | 225 | cx25840_write(client, 0x115, 0x8c); |
204 | cx25840_write(client, 0x116, 0x07); | 226 | cx25840_write(client, 0x116, 0x07); |
@@ -251,8 +273,13 @@ static void input_change(struct i2c_client *client) | |||
251 | } | 273 | } |
252 | cx25840_and_or(client, 0x401, ~0x60, 0); | 274 | cx25840_and_or(client, 0x401, ~0x60, 0); |
253 | cx25840_and_or(client, 0x401, ~0x60, 0x60); | 275 | cx25840_and_or(client, 0x401, ~0x60, 0x60); |
276 | cx25840_and_or(client, 0x810, ~0x01, 1); | ||
254 | 277 | ||
255 | if (std & V4L2_STD_525_60) { | 278 | if (state->radio) { |
279 | cx25840_write(client, 0x808, 0xf9); | ||
280 | cx25840_write(client, 0x80b, 0x00); | ||
281 | } | ||
282 | else if (std & V4L2_STD_525_60) { | ||
256 | /* Certain Hauppauge PVR150 models have a hardware bug | 283 | /* Certain Hauppauge PVR150 models have a hardware bug |
257 | that causes audio to drop out. For these models the | 284 | that causes audio to drop out. For these models the |
258 | audio standard must be set explicitly. | 285 | audio standard must be set explicitly. |
@@ -281,11 +308,7 @@ static void input_change(struct i2c_client *client) | |||
281 | cx25840_write(client, 0x80b, 0x10); | 308 | cx25840_write(client, 0x80b, 0x10); |
282 | } | 309 | } |
283 | 310 | ||
284 | if (cx25840_read(client, 0x803) & 0x10) { | 311 | cx25840_and_or(client, 0x810, ~0x01, 0); |
285 | /* restart audio decoder microcontroller */ | ||
286 | cx25840_and_or(client, 0x803, ~0x10, 0x00); | ||
287 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
288 | } | ||
289 | } | 312 | } |
290 | 313 | ||
291 | static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, | 314 | static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, |
@@ -625,6 +648,22 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
625 | struct v4l2_tuner *vt = arg; | 648 | struct v4l2_tuner *vt = arg; |
626 | struct v4l2_routing *route = arg; | 649 | struct v4l2_routing *route = arg; |
627 | 650 | ||
651 | /* ignore these commands */ | ||
652 | switch (cmd) { | ||
653 | case TUNER_SET_TYPE_ADDR: | ||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | if (!state->is_initialized) { | ||
658 | v4l_dbg(1, cx25840_debug, client, "cmd %08x triggered fw load\n", cmd); | ||
659 | /* initialize on first use */ | ||
660 | state->is_initialized = 1; | ||
661 | if (state->is_cx25836) | ||
662 | cx25836_initialize(client); | ||
663 | else | ||
664 | cx25840_initialize(client); | ||
665 | } | ||
666 | |||
628 | switch (cmd) { | 667 | switch (cmd) { |
629 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 668 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
630 | /* ioctls to allow direct access to the | 669 | /* ioctls to allow direct access to the |
@@ -825,7 +864,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
825 | if (state->is_cx25836) | 864 | if (state->is_cx25836) |
826 | cx25836_initialize(client); | 865 | cx25836_initialize(client); |
827 | else | 866 | else |
828 | cx25840_initialize(client, 0); | 867 | cx25840_initialize(client); |
829 | break; | 868 | break; |
830 | 869 | ||
831 | case VIDIOC_G_CHIP_IDENT: | 870 | case VIDIOC_G_CHIP_IDENT: |
@@ -856,17 +895,16 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, | |||
856 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) | 895 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) |
857 | return 0; | 896 | return 0; |
858 | 897 | ||
859 | state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); | 898 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); |
860 | if (state == 0) | 899 | if (client == 0) |
861 | return -ENOMEM; | 900 | return -ENOMEM; |
862 | 901 | ||
863 | client = &state->c; | ||
864 | client->addr = address; | 902 | client->addr = address; |
865 | client->adapter = adapter; | 903 | client->adapter = adapter; |
866 | client->driver = &i2c_driver_cx25840; | 904 | client->driver = &i2c_driver_cx25840; |
867 | snprintf(client->name, sizeof(client->name) - 1, "cx25840"); | 905 | snprintf(client->name, sizeof(client->name) - 1, "cx25840"); |
868 | 906 | ||
869 | v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", address << 1); | 907 | v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", client->addr << 1); |
870 | 908 | ||
871 | device_id = cx25840_read(client, 0x101) << 8; | 909 | device_id = cx25840_read(client, 0x101) << 8; |
872 | device_id |= cx25840_read(client, 0x100); | 910 | device_id |= cx25840_read(client, 0x100); |
@@ -875,42 +913,44 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, | |||
875 | * 0x83 for the cx2583x and 0x84 for the cx2584x */ | 913 | * 0x83 for the cx2583x and 0x84 for the cx2584x */ |
876 | if ((device_id & 0xff00) == 0x8300) { | 914 | if ((device_id & 0xff00) == 0x8300) { |
877 | id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; | 915 | id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; |
878 | state->is_cx25836 = 1; | ||
879 | } | 916 | } |
880 | else if ((device_id & 0xff00) == 0x8400) { | 917 | else if ((device_id & 0xff00) == 0x8400) { |
881 | id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); | 918 | id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); |
882 | state->is_cx25836 = 0; | ||
883 | } | 919 | } |
884 | else { | 920 | else { |
885 | v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); | 921 | v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); |
886 | kfree(state); | 922 | kfree(client); |
887 | return 0; | 923 | return 0; |
888 | } | 924 | } |
889 | 925 | ||
926 | state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); | ||
927 | if (state == NULL) { | ||
928 | kfree(client); | ||
929 | return -ENOMEM; | ||
930 | } | ||
931 | |||
890 | /* Note: revision '(device_id & 0x0f) == 2' was never built. The | 932 | /* Note: revision '(device_id & 0x0f) == 2' was never built. The |
891 | marking skips from 0x1 == 22 to 0x3 == 23. */ | 933 | marking skips from 0x1 == 22 to 0x3 == 23. */ |
892 | v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", | 934 | v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", |
893 | (device_id & 0xfff0) >> 4, | 935 | (device_id & 0xfff0) >> 4, |
894 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 0x0f), | 936 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 0x0f), |
895 | address << 1, adapter->name); | 937 | client->addr << 1, client->adapter->name); |
896 | 938 | ||
897 | i2c_set_clientdata(client, state); | 939 | i2c_set_clientdata(client, state); |
940 | state->c = client; | ||
941 | state->is_cx25836 = ((device_id & 0xff00) == 0x8300); | ||
898 | state->vid_input = CX25840_COMPOSITE7; | 942 | state->vid_input = CX25840_COMPOSITE7; |
899 | state->aud_input = CX25840_AUDIO8; | 943 | state->aud_input = CX25840_AUDIO8; |
900 | state->audclk_freq = 48000; | 944 | state->audclk_freq = 48000; |
901 | state->pvr150_workaround = 0; | 945 | state->pvr150_workaround = 0; |
902 | state->audmode = V4L2_TUNER_MODE_LANG1; | 946 | state->audmode = V4L2_TUNER_MODE_LANG1; |
947 | state->unmute_volume = -1; | ||
903 | state->vbi_line_offset = 8; | 948 | state->vbi_line_offset = 8; |
904 | state->id = id; | 949 | state->id = id; |
905 | state->rev = device_id; | 950 | state->rev = device_id; |
906 | 951 | ||
907 | i2c_attach_client(client); | 952 | i2c_attach_client(client); |
908 | 953 | ||
909 | if (state->is_cx25836) | ||
910 | cx25836_initialize(client); | ||
911 | else | ||
912 | cx25840_initialize(client, 1); | ||
913 | |||
914 | return 0; | 954 | return 0; |
915 | } | 955 | } |
916 | 956 | ||
@@ -932,6 +972,7 @@ static int cx25840_detach_client(struct i2c_client *client) | |||
932 | } | 972 | } |
933 | 973 | ||
934 | kfree(state); | 974 | kfree(state); |
975 | kfree(client); | ||
935 | 976 | ||
936 | return 0; | 977 | return 0; |
937 | } | 978 | } |
@@ -1056,9 +1097,10 @@ static void log_audio_status(struct i2c_client *client) | |||
1056 | } | 1097 | } |
1057 | v4l_info(client, "Detected audio standard: %s\n", p); | 1098 | v4l_info(client, "Detected audio standard: %s\n", p); |
1058 | v4l_info(client, "Audio muted: %s\n", | 1099 | v4l_info(client, "Audio muted: %s\n", |
1059 | (mute_ctl & 0x2) ? "yes" : "no"); | 1100 | (state->unmute_volume >= 0) ? "yes" : "no"); |
1060 | v4l_info(client, "Audio microcontroller: %s\n", | 1101 | v4l_info(client, "Audio microcontroller: %s\n", |
1061 | (download_ctl & 0x10) ? "running" : "stopped"); | 1102 | (download_ctl & 0x10) ? |
1103 | ((mute_ctl & 0x2) ? "detecting" : "running") : "stopped"); | ||
1062 | 1104 | ||
1063 | switch (audio_config >> 4) { | 1105 | switch (audio_config >> 4) { |
1064 | case 0x00: p = "undefined"; break; | 1106 | case 0x00: p = "undefined"; break; |
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h index f4b56d2fd6b6..ea669b1f084d 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/video/cx25840/cx25840-core.h | |||
@@ -35,17 +35,21 @@ extern int cx25840_debug; | |||
35 | #define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0) | 35 | #define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0) |
36 | 36 | ||
37 | struct cx25840_state { | 37 | struct cx25840_state { |
38 | struct i2c_client c; | 38 | struct i2c_client *c; |
39 | int pvr150_workaround; | 39 | int pvr150_workaround; |
40 | int radio; | 40 | int radio; |
41 | enum cx25840_video_input vid_input; | 41 | enum cx25840_video_input vid_input; |
42 | enum cx25840_audio_input aud_input; | 42 | enum cx25840_audio_input aud_input; |
43 | u32 audclk_freq; | 43 | u32 audclk_freq; |
44 | int audmode; | 44 | int audmode; |
45 | int unmute_volume; /* -1 if not muted */ | ||
45 | int vbi_line_offset; | 46 | int vbi_line_offset; |
46 | u32 id; | 47 | u32 id; |
47 | u32 rev; | 48 | u32 rev; |
48 | int is_cx25836; | 49 | int is_cx25836; |
50 | int is_initialized; | ||
51 | wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ | ||
52 | struct work_struct fw_work; /* work entry for fw load */ | ||
49 | }; | 53 | }; |
50 | 54 | ||
51 | /* ----------------------------------------------------------------------- */ | 55 | /* ----------------------------------------------------------------------- */ |
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index f750a543c961..eeb5224ca101 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
@@ -4,7 +4,7 @@ config VIDEO_CX88 | |||
4 | select I2C_ALGOBIT | 4 | select I2C_ALGOBIT |
5 | select FW_LOADER | 5 | select FW_LOADER |
6 | select VIDEO_BTCX | 6 | select VIDEO_BTCX |
7 | select VIDEO_BUF | 7 | select VIDEOBUF_DMA_SG |
8 | select VIDEO_TUNER | 8 | select VIDEO_TUNER |
9 | select VIDEO_TVEEPROM | 9 | select VIDEO_TVEEPROM |
10 | select VIDEO_IR | 10 | select VIDEO_IR |
@@ -46,7 +46,7 @@ config VIDEO_CX88_BLACKBIRD | |||
46 | config VIDEO_CX88_DVB | 46 | config VIDEO_CX88_DVB |
47 | tristate "DVB/ATSC Support for cx2388x based TV cards" | 47 | tristate "DVB/ATSC Support for cx2388x based TV cards" |
48 | depends on VIDEO_CX88 && DVB_CORE | 48 | depends on VIDEO_CX88 && DVB_CORE |
49 | select VIDEO_BUF_DVB | 49 | select VIDEOBUF_DVB |
50 | select DVB_PLL if !DVB_FE_CUSTOMISE | 50 | select DVB_PLL if !DVB_FE_CUSTOMISE |
51 | select DVB_MT352 if !DVB_FE_CUSTOMISE | 51 | select DVB_MT352 if !DVB_FE_CUSTOMISE |
52 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 52 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 2d666b56020c..90c36c5705c3 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * Support for audio capture | 3 | * Support for audio capture |
4 | * PCI function #1 of the cx2388x. | 4 | * PCI function #1 of the cx2388x. |
5 | * | 5 | * |
6 | * (c) 2007 Trent Piepho <xyzzy@speakeasy.org> | ||
6 | * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org> | 7 | * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org> |
7 | * (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org> | 8 | * (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org> |
8 | * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org> | 9 | * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org> |
@@ -27,7 +28,9 @@ | |||
27 | #include <linux/init.h> | 28 | #include <linux/init.h> |
28 | #include <linux/device.h> | 29 | #include <linux/device.h> |
29 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
31 | #include <linux/vmalloc.h> | ||
30 | #include <linux/dma-mapping.h> | 32 | #include <linux/dma-mapping.h> |
33 | #include <linux/pci.h> | ||
31 | 34 | ||
32 | #include <asm/delay.h> | 35 | #include <asm/delay.h> |
33 | #include <sound/driver.h> | 36 | #include <sound/driver.h> |
@@ -46,21 +49,16 @@ | |||
46 | #define dprintk_core(level,fmt, arg...) if (debug >= level) \ | 49 | #define dprintk_core(level,fmt, arg...) if (debug >= level) \ |
47 | printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg) | 50 | printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg) |
48 | 51 | ||
49 | |||
50 | /**************************************************************************** | 52 | /**************************************************************************** |
51 | Data type declarations - Can be moded to a header file later | 53 | Data type declarations - Can be moded to a header file later |
52 | ****************************************************************************/ | 54 | ****************************************************************************/ |
53 | 55 | ||
54 | /* These can be replaced after done */ | ||
55 | #define MIXER_ADDR_LAST MAX_CX88_INPUT | ||
56 | |||
57 | struct cx88_audio_dev { | 56 | struct cx88_audio_dev { |
58 | struct cx88_core *core; | 57 | struct cx88_core *core; |
59 | struct cx88_dmaqueue q; | 58 | struct cx88_dmaqueue q; |
60 | 59 | ||
61 | /* pci i/o */ | 60 | /* pci i/o */ |
62 | struct pci_dev *pci; | 61 | struct pci_dev *pci; |
63 | unsigned char pci_rev,pci_lat; | ||
64 | 62 | ||
65 | /* audio controls */ | 63 | /* audio controls */ |
66 | int irq; | 64 | int irq; |
@@ -68,24 +66,17 @@ struct cx88_audio_dev { | |||
68 | struct snd_card *card; | 66 | struct snd_card *card; |
69 | 67 | ||
70 | spinlock_t reg_lock; | 68 | spinlock_t reg_lock; |
69 | atomic_t count; | ||
71 | 70 | ||
72 | unsigned int dma_size; | 71 | unsigned int dma_size; |
73 | unsigned int period_size; | 72 | unsigned int period_size; |
74 | unsigned int num_periods; | 73 | unsigned int num_periods; |
75 | 74 | ||
76 | struct videobuf_dmabuf dma_risc; | 75 | struct videobuf_dmabuf *dma_risc; |
77 | |||
78 | int mixer_volume[MIXER_ADDR_LAST+1][2]; | ||
79 | int capture_source[MIXER_ADDR_LAST+1][2]; | ||
80 | |||
81 | long int read_count; | ||
82 | long int read_offset; | ||
83 | |||
84 | struct cx88_buffer *buf; | ||
85 | 76 | ||
86 | long opened; | 77 | struct cx88_buffer *buf; |
87 | struct snd_pcm_substream *substream; | ||
88 | 78 | ||
79 | struct snd_pcm_substream *substream; | ||
89 | }; | 80 | }; |
90 | typedef struct cx88_audio_dev snd_cx88_card_t; | 81 | typedef struct cx88_audio_dev snd_cx88_card_t; |
91 | 82 | ||
@@ -98,7 +89,6 @@ typedef struct cx88_audio_dev snd_cx88_card_t; | |||
98 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 89 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
99 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 90 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
100 | static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; | 91 | static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; |
101 | static struct snd_card *snd_cx88_cards[SNDRV_CARDS]; | ||
102 | 92 | ||
103 | module_param_array(enable, bool, NULL, 0444); | 93 | module_param_array(enable, bool, NULL, 0444); |
104 | MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled."); | 94 | MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled."); |
@@ -136,38 +126,39 @@ static int _cx88_start_audio_dma(snd_cx88_card_t *chip) | |||
136 | struct cx88_core *core=chip->core; | 126 | struct cx88_core *core=chip->core; |
137 | struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; | 127 | struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; |
138 | 128 | ||
139 | 129 | /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ | |
140 | dprintk(1, "Starting audio DMA for %i bytes/line and %i (%i) lines at address %08x\n",buf->bpl, chip->num_periods, audio_ch->fifo_size / buf->bpl, audio_ch->fifo_start); | 130 | cx_clear(MO_AUD_DMACNTRL, 0x11); |
141 | 131 | ||
142 | /* setup fifo + format - out channel */ | 132 | /* setup fifo + format - out channel */ |
143 | cx88_sram_channel_setup(chip->core, &cx88_sram_channels[SRAM_CH25], | 133 | cx88_sram_channel_setup(chip->core, audio_ch, buf->bpl, buf->risc.dma); |
144 | buf->bpl, buf->risc.dma); | ||
145 | 134 | ||
146 | /* sets bpl size */ | 135 | /* sets bpl size */ |
147 | cx_write(MO_AUDD_LNGTH, buf->bpl); | 136 | cx_write(MO_AUDD_LNGTH, buf->bpl); |
148 | 137 | ||
149 | /* reset counter */ | 138 | /* reset counter */ |
150 | cx_write(MO_AUDD_GPCNTRL,GP_COUNT_CONTROL_RESET); | 139 | cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET); |
151 | 140 | atomic_set(&chip->count, 0); | |
152 | dprintk(1,"Enabling IRQ, setting mask from 0x%x to 0x%x\n",chip->core->pci_irqmask,(chip->core->pci_irqmask | 0x02)); | ||
153 | /* enable irqs */ | ||
154 | cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | 0x02); | ||
155 | 141 | ||
142 | dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d " | ||
143 | "byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start + 8)>>1, | ||
144 | chip->num_periods, buf->bpl * chip->num_periods); | ||
156 | 145 | ||
157 | /* Enables corresponding bits at AUD_INT_STAT */ | 146 | /* Enables corresponding bits at AUD_INT_STAT */ |
158 | cx_write(MO_AUD_INTMSK, | 147 | cx_write(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | |
159 | (1<<16)| | 148 | AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); |
160 | (1<<12)| | 149 | |
161 | (1<<4)| | 150 | /* Clean any pending interrupt bits already set */ |
162 | (1<<0) | 151 | cx_write(MO_AUD_INTSTAT, ~0); |
163 | ); | 152 | |
153 | /* enable audio irqs */ | ||
154 | cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | PCI_INT_AUDINT); | ||
164 | 155 | ||
165 | /* start dma */ | 156 | /* start dma */ |
166 | cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */ | 157 | cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */ |
167 | cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */ | 158 | cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */ |
168 | 159 | ||
169 | if (debug) | 160 | if (debug) |
170 | cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); | 161 | cx88_sram_channel_dump(chip->core, audio_ch); |
171 | 162 | ||
172 | return 0; | 163 | return 0; |
173 | } | 164 | } |
@@ -184,13 +175,9 @@ static int _cx88_stop_audio_dma(snd_cx88_card_t *chip) | |||
184 | cx_clear(MO_AUD_DMACNTRL, 0x11); | 175 | cx_clear(MO_AUD_DMACNTRL, 0x11); |
185 | 176 | ||
186 | /* disable irqs */ | 177 | /* disable irqs */ |
187 | cx_clear(MO_PCI_INTMSK, 0x02); | 178 | cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT); |
188 | cx_clear(MO_AUD_INTMSK, | 179 | cx_clear(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | |
189 | (1<<16)| | 180 | AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); |
190 | (1<<12)| | ||
191 | (1<<4)| | ||
192 | (1<<0) | ||
193 | ); | ||
194 | 181 | ||
195 | if (debug) | 182 | if (debug) |
196 | cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); | 183 | cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); |
@@ -198,7 +185,7 @@ static int _cx88_stop_audio_dma(snd_cx88_card_t *chip) | |||
198 | return 0; | 185 | return 0; |
199 | } | 186 | } |
200 | 187 | ||
201 | #define MAX_IRQ_LOOP 10 | 188 | #define MAX_IRQ_LOOP 50 |
202 | 189 | ||
203 | /* | 190 | /* |
204 | * BOARD Specific: IRQ dma bits | 191 | * BOARD Specific: IRQ dma bits |
@@ -223,42 +210,32 @@ static void cx8801_aud_irq(snd_cx88_card_t *chip) | |||
223 | { | 210 | { |
224 | struct cx88_core *core = chip->core; | 211 | struct cx88_core *core = chip->core; |
225 | u32 status, mask; | 212 | u32 status, mask; |
226 | u32 count; | ||
227 | 213 | ||
228 | status = cx_read(MO_AUD_INTSTAT); | 214 | status = cx_read(MO_AUD_INTSTAT); |
229 | mask = cx_read(MO_AUD_INTMSK); | 215 | mask = cx_read(MO_AUD_INTMSK); |
230 | if (0 == (status & mask)) { | 216 | if (0 == (status & mask)) |
231 | spin_unlock(&chip->reg_lock); | ||
232 | return; | 217 | return; |
233 | } | ||
234 | cx_write(MO_AUD_INTSTAT, status); | 218 | cx_write(MO_AUD_INTSTAT, status); |
235 | if (debug > 1 || (status & mask & ~0xff)) | 219 | if (debug > 1 || (status & mask & ~0xff)) |
236 | cx88_print_irqbits(core->name, "irq aud", | 220 | cx88_print_irqbits(core->name, "irq aud", |
237 | cx88_aud_irqs, ARRAY_SIZE(cx88_aud_irqs), | 221 | cx88_aud_irqs, ARRAY_SIZE(cx88_aud_irqs), |
238 | status, mask); | 222 | status, mask); |
239 | /* risc op code error */ | 223 | /* risc op code error */ |
240 | if (status & (1 << 16)) { | 224 | if (status & AUD_INT_OPC_ERR) { |
241 | printk(KERN_WARNING "%s/0: audio risc op code error\n",core->name); | 225 | printk(KERN_WARNING "%s/1: Audio risc op code error\n",core->name); |
242 | cx_clear(MO_AUD_DMACNTRL, 0x11); | 226 | cx_clear(MO_AUD_DMACNTRL, 0x11); |
243 | cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]); | 227 | cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]); |
244 | } | 228 | } |
245 | 229 | if (status & AUD_INT_DN_SYNC) { | |
246 | /* risc1 downstream */ | 230 | dprintk(1, "Downstream sync error\n"); |
247 | if (status & 0x01) { | 231 | cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET); |
248 | spin_lock(&chip->reg_lock); | 232 | return; |
249 | count = cx_read(MO_AUDD_GPCNT); | ||
250 | spin_unlock(&chip->reg_lock); | ||
251 | if (chip->read_count == 0) | ||
252 | chip->read_count += chip->dma_size; | ||
253 | } | 233 | } |
254 | 234 | /* risc1 downstream */ | |
255 | if (chip->read_count >= chip->period_size) { | 235 | if (status & AUD_INT_DN_RISCI1) { |
256 | dprintk(2, "Elapsing period\n"); | 236 | atomic_set(&chip->count, cx_read(MO_AUDD_GPCNT)); |
257 | snd_pcm_period_elapsed(chip->substream); | 237 | snd_pcm_period_elapsed(chip->substream); |
258 | } | 238 | } |
259 | |||
260 | dprintk(3,"Leaving audio IRQ handler...\n"); | ||
261 | |||
262 | /* FIXME: Any other status should deserve a special handling? */ | 239 | /* FIXME: Any other status should deserve a special handling? */ |
263 | } | 240 | } |
264 | 241 | ||
@@ -273,27 +250,26 @@ static irqreturn_t cx8801_irq(int irq, void *dev_id) | |||
273 | int loop, handled = 0; | 250 | int loop, handled = 0; |
274 | 251 | ||
275 | for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { | 252 | for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { |
276 | status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x02); | 253 | status = cx_read(MO_PCI_INTSTAT) & |
254 | (core->pci_irqmask | PCI_INT_AUDINT); | ||
277 | if (0 == status) | 255 | if (0 == status) |
278 | goto out; | 256 | goto out; |
279 | dprintk( 3, "cx8801_irq\n" ); | 257 | dprintk(3, "cx8801_irq loop %d/%d, status %x\n", |
280 | dprintk( 3, " loop: %d/%d\n", loop, MAX_IRQ_LOOP ); | 258 | loop, MAX_IRQ_LOOP, status); |
281 | dprintk( 3, " status: %d\n", status ); | ||
282 | handled = 1; | 259 | handled = 1; |
283 | cx_write(MO_PCI_INTSTAT, status); | 260 | cx_write(MO_PCI_INTSTAT, status); |
284 | 261 | ||
285 | if (status & 0x02) | 262 | if (status & core->pci_irqmask) |
286 | { | 263 | cx88_core_irq(core, status); |
287 | dprintk( 2, " ALSA IRQ handling\n" ); | 264 | if (status & PCI_INT_AUDINT) |
288 | cx8801_aud_irq(chip); | 265 | cx8801_aud_irq(chip); |
289 | } | 266 | } |
290 | }; | ||
291 | 267 | ||
292 | if (MAX_IRQ_LOOP == loop) { | 268 | if (MAX_IRQ_LOOP == loop) { |
293 | dprintk( 0, "clearing mask\n" ); | 269 | printk(KERN_ERR |
294 | dprintk(1,"%s/0: irq loop -- clearing mask\n", | 270 | "%s/1: IRQ loop detected, disabling interrupts\n", |
295 | core->name); | 271 | core->name); |
296 | cx_clear(MO_PCI_INTMSK,0x02); | 272 | cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT); |
297 | } | 273 | } |
298 | 274 | ||
299 | out: | 275 | out: |
@@ -306,14 +282,15 @@ static int dsp_buffer_free(snd_cx88_card_t *chip) | |||
306 | BUG_ON(!chip->dma_size); | 282 | BUG_ON(!chip->dma_size); |
307 | 283 | ||
308 | dprintk(2,"Freeing buffer\n"); | 284 | dprintk(2,"Freeing buffer\n"); |
309 | videobuf_pci_dma_unmap(chip->pci, &chip->dma_risc); | 285 | videobuf_pci_dma_unmap(chip->pci, chip->dma_risc); |
310 | videobuf_dma_free(&chip->dma_risc); | 286 | videobuf_dma_free(chip->dma_risc); |
311 | btcx_riscmem_free(chip->pci,&chip->buf->risc); | 287 | btcx_riscmem_free(chip->pci,&chip->buf->risc); |
312 | kfree(chip->buf); | 288 | kfree(chip->buf); |
313 | 289 | ||
290 | chip->dma_risc = NULL; | ||
314 | chip->dma_size = 0; | 291 | chip->dma_size = 0; |
315 | 292 | ||
316 | return 0; | 293 | return 0; |
317 | } | 294 | } |
318 | 295 | ||
319 | /**************************************************************************** | 296 | /**************************************************************************** |
@@ -323,6 +300,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip) | |||
323 | /* | 300 | /* |
324 | * Digital hardware definition | 301 | * Digital hardware definition |
325 | */ | 302 | */ |
303 | #define DEFAULT_FIFO_SIZE 4096 | ||
326 | static struct snd_pcm_hardware snd_cx88_digital_hw = { | 304 | static struct snd_pcm_hardware snd_cx88_digital_hw = { |
327 | .info = SNDRV_PCM_INFO_MMAP | | 305 | .info = SNDRV_PCM_INFO_MMAP | |
328 | SNDRV_PCM_INFO_INTERLEAVED | | 306 | SNDRV_PCM_INFO_INTERLEAVED | |
@@ -333,22 +311,18 @@ static struct snd_pcm_hardware snd_cx88_digital_hw = { | |||
333 | .rates = SNDRV_PCM_RATE_48000, | 311 | .rates = SNDRV_PCM_RATE_48000, |
334 | .rate_min = 48000, | 312 | .rate_min = 48000, |
335 | .rate_max = 48000, | 313 | .rate_max = 48000, |
336 | .channels_min = 1, | 314 | .channels_min = 2, |
337 | .channels_max = 2, | 315 | .channels_max = 2, |
338 | .buffer_bytes_max = (2*2048), | 316 | /* Analog audio output will be full of clicks and pops if there |
339 | .period_bytes_min = 2048, | 317 | are not exactly four lines in the SRAM FIFO buffer. */ |
340 | .period_bytes_max = 2048, | 318 | .period_bytes_min = DEFAULT_FIFO_SIZE/4, |
341 | .periods_min = 2, | 319 | .period_bytes_max = DEFAULT_FIFO_SIZE/4, |
342 | .periods_max = 2, | 320 | .periods_min = 1, |
321 | .periods_max = 1024, | ||
322 | .buffer_bytes_max = (1024*1024), | ||
343 | }; | 323 | }; |
344 | 324 | ||
345 | /* | 325 | /* |
346 | * audio pcm capture runtime free | ||
347 | */ | ||
348 | static void snd_card_cx88_runtime_free(struct snd_pcm_runtime *runtime) | ||
349 | { | ||
350 | } | ||
351 | /* | ||
352 | * audio pcm capture open callback | 326 | * audio pcm capture open callback |
353 | */ | 327 | */ |
354 | static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) | 328 | static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) |
@@ -357,26 +331,24 @@ static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) | |||
357 | struct snd_pcm_runtime *runtime = substream->runtime; | 331 | struct snd_pcm_runtime *runtime = substream->runtime; |
358 | int err; | 332 | int err; |
359 | 333 | ||
360 | if (test_and_set_bit(0, &chip->opened)) | 334 | err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); |
361 | return -EBUSY; | ||
362 | |||
363 | err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
364 | if (err < 0) | 335 | if (err < 0) |
365 | goto _error; | 336 | goto _error; |
366 | 337 | ||
367 | chip->substream = substream; | 338 | chip->substream = substream; |
368 | 339 | ||
369 | chip->read_count = 0; | ||
370 | chip->read_offset = 0; | ||
371 | |||
372 | runtime->private_free = snd_card_cx88_runtime_free; | ||
373 | runtime->hw = snd_cx88_digital_hw; | 340 | runtime->hw = snd_cx88_digital_hw; |
374 | 341 | ||
342 | if (cx88_sram_channels[SRAM_CH25].fifo_size != DEFAULT_FIFO_SIZE) { | ||
343 | unsigned int bpl = cx88_sram_channels[SRAM_CH25].fifo_size / 4; | ||
344 | bpl &= ~7; /* must be multiple of 8 */ | ||
345 | runtime->hw.period_bytes_min = bpl; | ||
346 | runtime->hw.period_bytes_max = bpl; | ||
347 | } | ||
348 | |||
375 | return 0; | 349 | return 0; |
376 | _error: | 350 | _error: |
377 | dprintk(1,"Error opening PCM!\n"); | 351 | dprintk(1,"Error opening PCM!\n"); |
378 | clear_bit(0, &chip->opened); | ||
379 | smp_mb__after_clear_bit(); | ||
380 | return err; | 352 | return err; |
381 | } | 353 | } |
382 | 354 | ||
@@ -385,11 +357,6 @@ _error: | |||
385 | */ | 357 | */ |
386 | static int snd_cx88_close(struct snd_pcm_substream *substream) | 358 | static int snd_cx88_close(struct snd_pcm_substream *substream) |
387 | { | 359 | { |
388 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | ||
389 | |||
390 | clear_bit(0, &chip->opened); | ||
391 | smp_mb__after_clear_bit(); | ||
392 | |||
393 | return 0; | 360 | return 0; |
394 | } | 361 | } |
395 | 362 | ||
@@ -400,55 +367,67 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, | |||
400 | struct snd_pcm_hw_params * hw_params) | 367 | struct snd_pcm_hw_params * hw_params) |
401 | { | 368 | { |
402 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | 369 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); |
370 | struct videobuf_dmabuf *dma; | ||
371 | |||
403 | struct cx88_buffer *buf; | 372 | struct cx88_buffer *buf; |
373 | int ret; | ||
404 | 374 | ||
405 | if (substream->runtime->dma_area) { | 375 | if (substream->runtime->dma_area) { |
406 | dsp_buffer_free(chip); | 376 | dsp_buffer_free(chip); |
407 | substream->runtime->dma_area = NULL; | 377 | substream->runtime->dma_area = NULL; |
408 | } | 378 | } |
409 | 379 | ||
410 | |||
411 | chip->period_size = params_period_bytes(hw_params); | 380 | chip->period_size = params_period_bytes(hw_params); |
412 | chip->num_periods = params_periods(hw_params); | 381 | chip->num_periods = params_periods(hw_params); |
413 | chip->dma_size = chip->period_size * params_periods(hw_params); | 382 | chip->dma_size = chip->period_size * params_periods(hw_params); |
414 | 383 | ||
415 | BUG_ON(!chip->dma_size); | 384 | BUG_ON(!chip->dma_size); |
385 | BUG_ON(chip->num_periods & (chip->num_periods-1)); | ||
416 | 386 | ||
417 | dprintk(1,"Setting buffer\n"); | 387 | buf = videobuf_pci_alloc(sizeof(*buf)); |
418 | |||
419 | buf = kzalloc(sizeof(*buf),GFP_KERNEL); | ||
420 | if (NULL == buf) | 388 | if (NULL == buf) |
421 | return -ENOMEM; | 389 | return -ENOMEM; |
422 | 390 | ||
423 | buf->vb.memory = V4L2_MEMORY_MMAP; | 391 | buf->vb.memory = V4L2_MEMORY_MMAP; |
392 | buf->vb.field = V4L2_FIELD_NONE; | ||
424 | buf->vb.width = chip->period_size; | 393 | buf->vb.width = chip->period_size; |
394 | buf->bpl = chip->period_size; | ||
425 | buf->vb.height = chip->num_periods; | 395 | buf->vb.height = chip->num_periods; |
426 | buf->vb.size = chip->dma_size; | 396 | buf->vb.size = chip->dma_size; |
427 | buf->vb.field = V4L2_FIELD_NONE; | ||
428 | 397 | ||
429 | videobuf_dma_init(&buf->vb.dma); | 398 | dma=videobuf_to_dma(&buf->vb); |
430 | videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE, | 399 | videobuf_dma_init(dma); |
400 | ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, | ||
431 | (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); | 401 | (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); |
402 | if (ret < 0) | ||
403 | goto error; | ||
432 | 404 | ||
433 | videobuf_pci_dma_map(chip->pci,&buf->vb.dma); | 405 | ret = videobuf_pci_dma_map(chip->pci,dma); |
406 | if (ret < 0) | ||
407 | goto error; | ||
434 | 408 | ||
409 | ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist, | ||
410 | buf->vb.width, buf->vb.height, 1); | ||
411 | if (ret < 0) | ||
412 | goto error; | ||
435 | 413 | ||
436 | cx88_risc_databuffer(chip->pci, &buf->risc, | 414 | /* Loop back to start of program */ |
437 | buf->vb.dma.sglist, | 415 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); |
438 | buf->vb.width, buf->vb.height); | ||
439 | |||
440 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
441 | buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | 416 | buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); |
442 | 417 | ||
443 | buf->vb.state = STATE_PREPARED; | 418 | buf->vb.state = STATE_PREPARED; |
444 | 419 | ||
445 | buf->bpl = chip->period_size; | ||
446 | chip->buf = buf; | 420 | chip->buf = buf; |
447 | chip->dma_risc = buf->vb.dma; | 421 | chip->dma_risc = dma; |
448 | 422 | ||
449 | dprintk(1,"Buffer ready at %u\n",chip->dma_risc.nr_pages); | 423 | substream->runtime->dma_area = chip->dma_risc->vmalloc; |
450 | substream->runtime->dma_area = chip->dma_risc.vmalloc; | 424 | substream->runtime->dma_bytes = chip->dma_size; |
425 | substream->runtime->dma_addr = 0; | ||
451 | return 0; | 426 | return 0; |
427 | |||
428 | error: | ||
429 | kfree(buf); | ||
430 | return ret; | ||
452 | } | 431 | } |
453 | 432 | ||
454 | /* | 433 | /* |
@@ -475,7 +454,6 @@ static int snd_cx88_prepare(struct snd_pcm_substream *substream) | |||
475 | return 0; | 454 | return 0; |
476 | } | 455 | } |
477 | 456 | ||
478 | |||
479 | /* | 457 | /* |
480 | * trigger callback | 458 | * trigger callback |
481 | */ | 459 | */ |
@@ -484,6 +462,7 @@ static int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd) | |||
484 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | 462 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); |
485 | int err; | 463 | int err; |
486 | 464 | ||
465 | /* Local interrupts are already disabled by ALSA */ | ||
487 | spin_lock(&chip->reg_lock); | 466 | spin_lock(&chip->reg_lock); |
488 | 467 | ||
489 | switch (cmd) { | 468 | switch (cmd) { |
@@ -510,17 +489,24 @@ static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream) | |||
510 | { | 489 | { |
511 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | 490 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); |
512 | struct snd_pcm_runtime *runtime = substream->runtime; | 491 | struct snd_pcm_runtime *runtime = substream->runtime; |
492 | u16 count; | ||
513 | 493 | ||
514 | if (chip->read_count) { | 494 | count = atomic_read(&chip->count); |
515 | chip->read_count -= snd_pcm_lib_period_bytes(substream); | ||
516 | chip->read_offset += snd_pcm_lib_period_bytes(substream); | ||
517 | if (chip->read_offset == chip->dma_size) | ||
518 | chip->read_offset = 0; | ||
519 | } | ||
520 | 495 | ||
521 | dprintk(2, "Pointer time, will return %li, read %li\n",chip->read_offset,chip->read_count); | 496 | // dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __FUNCTION__, |
522 | return bytes_to_frames(runtime, chip->read_offset); | 497 | // count, new, count & (runtime->periods-1), |
498 | // runtime->period_size * (count & (runtime->periods-1))); | ||
499 | return runtime->period_size * (count & (runtime->periods-1)); | ||
500 | } | ||
523 | 501 | ||
502 | /* | ||
503 | * page callback (needed for mmap) | ||
504 | */ | ||
505 | static struct page *snd_cx88_page(struct snd_pcm_substream *substream, | ||
506 | unsigned long offset) | ||
507 | { | ||
508 | void *pageptr = substream->runtime->dma_area + offset; | ||
509 | return vmalloc_to_page(pageptr); | ||
524 | } | 510 | } |
525 | 511 | ||
526 | /* | 512 | /* |
@@ -535,6 +521,7 @@ static struct snd_pcm_ops snd_cx88_pcm_ops = { | |||
535 | .prepare = snd_cx88_prepare, | 521 | .prepare = snd_cx88_prepare, |
536 | .trigger = snd_cx88_card_trigger, | 522 | .trigger = snd_cx88_card_trigger, |
537 | .pointer = snd_cx88_pointer, | 523 | .pointer = snd_cx88_pointer, |
524 | .page = snd_cx88_page, | ||
538 | }; | 525 | }; |
539 | 526 | ||
540 | /* | 527 | /* |
@@ -562,7 +549,7 @@ static int snd_cx88_capture_volume_info(struct snd_kcontrol *kcontrol, | |||
562 | struct snd_ctl_elem_info *info) | 549 | struct snd_ctl_elem_info *info) |
563 | { | 550 | { |
564 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 551 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
565 | info->count = 1; | 552 | info->count = 2; |
566 | info->value.integer.min = 0; | 553 | info->value.integer.min = 0; |
567 | info->value.integer.max = 0x3f; | 554 | info->value.integer.max = 0x3f; |
568 | 555 | ||
@@ -575,8 +562,12 @@ static int snd_cx88_capture_volume_get(struct snd_kcontrol *kcontrol, | |||
575 | { | 562 | { |
576 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 563 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); |
577 | struct cx88_core *core=chip->core; | 564 | struct cx88_core *core=chip->core; |
565 | int vol = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f), | ||
566 | bal = cx_read(AUD_BAL_CTL); | ||
578 | 567 | ||
579 | value->value.integer.value[0] = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f); | 568 | value->value.integer.value[(bal & 0x40) ? 0 : 1] = vol; |
569 | vol -= (bal & 0x3f); | ||
570 | value->value.integer.value[(bal & 0x40) ? 1 : 0] = vol < 0 ? 0 : vol; | ||
580 | 571 | ||
581 | return 0; | 572 | return 0; |
582 | } | 573 | } |
@@ -587,16 +578,31 @@ static int snd_cx88_capture_volume_put(struct snd_kcontrol *kcontrol, | |||
587 | { | 578 | { |
588 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 579 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); |
589 | struct cx88_core *core=chip->core; | 580 | struct cx88_core *core=chip->core; |
590 | int v; | 581 | int v, b; |
591 | u32 old_control; | 582 | int changed = 0; |
592 | 583 | u32 old; | |
584 | |||
585 | b = value->value.integer.value[1] - value->value.integer.value[0]; | ||
586 | if (b < 0) { | ||
587 | v = 0x3f - value->value.integer.value[0]; | ||
588 | b = (-b) | 0x40; | ||
589 | } else { | ||
590 | v = 0x3f - value->value.integer.value[1]; | ||
591 | } | ||
592 | /* Do we really know this will always be called with IRQs on? */ | ||
593 | spin_lock_irq(&chip->reg_lock); | 593 | spin_lock_irq(&chip->reg_lock); |
594 | old_control = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f); | 594 | old = cx_read(AUD_VOL_CTL); |
595 | v = 0x3f - (value->value.integer.value[0] & 0x3f); | 595 | if (v != (old & 0x3f)) { |
596 | cx_andor(AUD_VOL_CTL, 0x3f, v); | 596 | cx_write(AUD_VOL_CTL, (old & ~0x3f) | v); |
597 | changed = 1; | ||
598 | } | ||
599 | if (cx_read(AUD_BAL_CTL) != b) { | ||
600 | cx_write(AUD_BAL_CTL, b); | ||
601 | changed = 1; | ||
602 | } | ||
597 | spin_unlock_irq(&chip->reg_lock); | 603 | spin_unlock_irq(&chip->reg_lock); |
598 | 604 | ||
599 | return v != old_control; | 605 | return changed; |
600 | } | 606 | } |
601 | 607 | ||
602 | static struct snd_kcontrol_new snd_cx88_capture_volume = { | 608 | static struct snd_kcontrol_new snd_cx88_capture_volume = { |
@@ -665,6 +671,7 @@ static int __devinit snd_cx88_create(struct snd_card *card, | |||
665 | snd_cx88_card_t *chip; | 671 | snd_cx88_card_t *chip; |
666 | struct cx88_core *core; | 672 | struct cx88_core *core; |
667 | int err; | 673 | int err; |
674 | unsigned char pci_lat; | ||
668 | 675 | ||
669 | *rchip = NULL; | 676 | *rchip = NULL; |
670 | 677 | ||
@@ -709,13 +716,12 @@ static int __devinit snd_cx88_create(struct snd_card *card, | |||
709 | } | 716 | } |
710 | 717 | ||
711 | /* print pci info */ | 718 | /* print pci info */ |
712 | pci_read_config_byte(pci, PCI_CLASS_REVISION, &chip->pci_rev); | 719 | pci_read_config_byte(pci, PCI_LATENCY_TIMER, &pci_lat); |
713 | pci_read_config_byte(pci, PCI_LATENCY_TIMER, &chip->pci_lat); | ||
714 | 720 | ||
715 | dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, " | 721 | dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, " |
716 | "latency: %d, mmio: 0x%llx\n", core->name, devno, | 722 | "latency: %d, mmio: 0x%llx\n", core->name, devno, |
717 | pci_name(pci), chip->pci_rev, pci->irq, | 723 | pci_name(pci), pci->revision, pci->irq, |
718 | chip->pci_lat,(unsigned long long)pci_resource_start(pci,0)); | 724 | pci_lat, (unsigned long long)pci_resource_start(pci,0)); |
719 | 725 | ||
720 | chip->irq = pci->irq; | 726 | chip->irq = pci->irq; |
721 | synchronize_irq(chip->irq); | 727 | synchronize_irq(chip->irq); |
@@ -753,17 +759,12 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, | |||
753 | return (err); | 759 | return (err); |
754 | 760 | ||
755 | err = snd_cx88_pcm(chip, 0, "CX88 Digital"); | 761 | err = snd_cx88_pcm(chip, 0, "CX88 Digital"); |
756 | 762 | if (err < 0) | |
757 | if (err < 0) { | 763 | goto error; |
758 | snd_card_free(card); | ||
759 | return (err); | ||
760 | } | ||
761 | 764 | ||
762 | err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip)); | 765 | err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip)); |
763 | if (err < 0) { | 766 | if (err < 0) |
764 | snd_card_free(card); | 767 | goto error; |
765 | return (err); | ||
766 | } | ||
767 | 768 | ||
768 | strcpy (card->driver, "CX88x"); | 769 | strcpy (card->driver, "CX88x"); |
769 | sprintf(card->shortname, "Conexant CX%x", pci->device); | 770 | sprintf(card->shortname, "Conexant CX%x", pci->device); |
@@ -775,16 +776,16 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, | |||
775 | card->driver,devno); | 776 | card->driver,devno); |
776 | 777 | ||
777 | err = snd_card_register(card); | 778 | err = snd_card_register(card); |
778 | if (err < 0) { | 779 | if (err < 0) |
779 | snd_card_free(card); | 780 | goto error; |
780 | return (err); | ||
781 | } | ||
782 | snd_cx88_cards[devno] = card; | ||
783 | |||
784 | pci_set_drvdata(pci,card); | 781 | pci_set_drvdata(pci,card); |
785 | 782 | ||
786 | devno++; | 783 | devno++; |
787 | return 0; | 784 | return 0; |
785 | |||
786 | error: | ||
787 | snd_card_free(card); | ||
788 | return err; | ||
788 | } | 789 | } |
789 | /* | 790 | /* |
790 | * ALSA destructor | 791 | * ALSA destructor |
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index f2fcdb92ecce..6d6f5048d762 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
@@ -27,7 +27,6 @@ | |||
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/moduleparam.h> | ||
31 | #include <linux/init.h> | 30 | #include <linux/init.h> |
32 | #include <linux/fs.h> | 31 | #include <linux/fs.h> |
33 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
@@ -734,14 +733,14 @@ static int vidioc_querycap (struct file *file, void *priv, | |||
734 | struct cx88_core *core = dev->core; | 733 | struct cx88_core *core = dev->core; |
735 | 734 | ||
736 | strcpy(cap->driver, "cx88_blackbird"); | 735 | strcpy(cap->driver, "cx88_blackbird"); |
737 | strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card)); | 736 | strlcpy(cap->card, core->board.name, sizeof(cap->card)); |
738 | sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); | 737 | sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); |
739 | cap->version = CX88_VERSION_CODE; | 738 | cap->version = CX88_VERSION_CODE; |
740 | cap->capabilities = | 739 | cap->capabilities = |
741 | V4L2_CAP_VIDEO_CAPTURE | | 740 | V4L2_CAP_VIDEO_CAPTURE | |
742 | V4L2_CAP_READWRITE | | 741 | V4L2_CAP_READWRITE | |
743 | V4L2_CAP_STREAMING; | 742 | V4L2_CAP_STREAMING; |
744 | if (UNSET != core->tuner_type) | 743 | if (UNSET != core->board.tuner_type) |
745 | cap->capabilities |= V4L2_CAP_TUNER; | 744 | cap->capabilities |= V4L2_CAP_TUNER; |
746 | return 0; | 745 | return 0; |
747 | } | 746 | } |
@@ -877,7 +876,7 @@ static int vidioc_g_ext_ctrls (struct file *file, void *priv, | |||
877 | 876 | ||
878 | if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) | 877 | if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
879 | return -EINVAL; | 878 | return -EINVAL; |
880 | return cx2341x_ext_ctrls(&dev->params, f, VIDIOC_G_EXT_CTRLS); | 879 | return cx2341x_ext_ctrls(&dev->params, 0, f, VIDIOC_G_EXT_CTRLS); |
881 | } | 880 | } |
882 | 881 | ||
883 | static int vidioc_s_ext_ctrls (struct file *file, void *priv, | 882 | static int vidioc_s_ext_ctrls (struct file *file, void *priv, |
@@ -890,7 +889,7 @@ static int vidioc_s_ext_ctrls (struct file *file, void *priv, | |||
890 | if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) | 889 | if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
891 | return -EINVAL; | 890 | return -EINVAL; |
892 | p = dev->params; | 891 | p = dev->params; |
893 | err = cx2341x_ext_ctrls(&p, f, VIDIOC_S_EXT_CTRLS); | 892 | err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS); |
894 | if (!err) { | 893 | if (!err) { |
895 | err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p); | 894 | err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p); |
896 | dev->params = p; | 895 | dev->params = p; |
@@ -908,7 +907,7 @@ static int vidioc_try_ext_ctrls (struct file *file, void *priv, | |||
908 | if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) | 907 | if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
909 | return -EINVAL; | 908 | return -EINVAL; |
910 | p = dev->params; | 909 | p = dev->params; |
911 | err = cx2341x_ext_ctrls(&p, f, VIDIOC_TRY_EXT_CTRLS); | 910 | err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS); |
912 | 911 | ||
913 | return err; | 912 | return err; |
914 | } | 913 | } |
@@ -990,7 +989,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, | |||
990 | struct cx8802_fh *fh = priv; | 989 | struct cx8802_fh *fh = priv; |
991 | struct cx88_core *core = fh->dev->core; | 990 | struct cx88_core *core = fh->dev->core; |
992 | 991 | ||
993 | if (unlikely(UNSET == core->tuner_type)) | 992 | if (unlikely(UNSET == core->board.tuner_type)) |
994 | return -EINVAL; | 993 | return -EINVAL; |
995 | 994 | ||
996 | f->type = V4L2_TUNER_ANALOG_TV; | 995 | f->type = V4L2_TUNER_ANALOG_TV; |
@@ -1028,7 +1027,7 @@ static int vidioc_g_tuner (struct file *file, void *priv, | |||
1028 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 1027 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; |
1029 | u32 reg; | 1028 | u32 reg; |
1030 | 1029 | ||
1031 | if (unlikely(UNSET == core->tuner_type)) | 1030 | if (unlikely(UNSET == core->board.tuner_type)) |
1032 | return -EINVAL; | 1031 | return -EINVAL; |
1033 | if (0 != t->index) | 1032 | if (0 != t->index) |
1034 | return -EINVAL; | 1033 | return -EINVAL; |
@@ -1049,7 +1048,7 @@ static int vidioc_s_tuner (struct file *file, void *priv, | |||
1049 | { | 1048 | { |
1050 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 1049 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; |
1051 | 1050 | ||
1052 | if (UNSET == core->tuner_type) | 1051 | if (UNSET == core->board.tuner_type) |
1053 | return -EINVAL; | 1052 | return -EINVAL; |
1054 | if (0 != t->index) | 1053 | if (0 != t->index) |
1055 | return -EINVAL; | 1054 | return -EINVAL; |
@@ -1078,7 +1077,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
1078 | struct cx8802_driver *drv = NULL; | 1077 | struct cx8802_driver *drv = NULL; |
1079 | int err; | 1078 | int err; |
1080 | 1079 | ||
1081 | dev = cx8802_get_device(inode); | 1080 | dev = cx8802_get_device(inode); |
1082 | 1081 | ||
1083 | dprintk( 1, "%s\n", __FUNCTION__); | 1082 | dprintk( 1, "%s\n", __FUNCTION__); |
1084 | 1083 | ||
@@ -1112,7 +1111,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
1112 | file->private_data = fh; | 1111 | file->private_data = fh; |
1113 | fh->dev = dev; | 1112 | fh->dev = dev; |
1114 | 1113 | ||
1115 | videobuf_queue_init(&fh->mpegq, &blackbird_qops, | 1114 | videobuf_queue_pci_init(&fh->mpegq, &blackbird_qops, |
1116 | dev->pci, &dev->slock, | 1115 | dev->pci, &dev->slock, |
1117 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 1116 | V4L2_BUF_TYPE_VIDEO_CAPTURE, |
1118 | V4L2_FIELD_INTERLACED, | 1117 | V4L2_FIELD_INTERLACED, |
@@ -1235,7 +1234,7 @@ static struct video_device cx8802_mpeg_template = | |||
1235 | .vidioc_s_tuner = vidioc_s_tuner, | 1234 | .vidioc_s_tuner = vidioc_s_tuner, |
1236 | .vidioc_s_std = vidioc_s_std, | 1235 | .vidioc_s_std = vidioc_s_std, |
1237 | .tvnorms = CX88_NORMS, | 1236 | .tvnorms = CX88_NORMS, |
1238 | .current_norm = V4L2_STD_NTSC_M, | 1237 | .current_norm = V4L2_STD_NTSC_M, |
1239 | }; | 1238 | }; |
1240 | 1239 | ||
1241 | /* ------------------------------------------------------------------ */ | 1240 | /* ------------------------------------------------------------------ */ |
@@ -1246,7 +1245,7 @@ static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv) | |||
1246 | struct cx88_core *core = drv->core; | 1245 | struct cx88_core *core = drv->core; |
1247 | int err = 0; | 1246 | int err = 0; |
1248 | 1247 | ||
1249 | switch (core->board) { | 1248 | switch (core->boardnr) { |
1250 | case CX88_BOARD_HAUPPAUGE_HVR1300: | 1249 | case CX88_BOARD_HAUPPAUGE_HVR1300: |
1251 | /* By default, core setup will leave the cx22702 out of reset, on the bus. | 1250 | /* By default, core setup will leave the cx22702 out of reset, on the bus. |
1252 | * We left the hardware on power up with the cx22702 active. | 1251 | * We left the hardware on power up with the cx22702 active. |
@@ -1268,7 +1267,7 @@ static int cx8802_blackbird_advise_release(struct cx8802_driver *drv) | |||
1268 | struct cx88_core *core = drv->core; | 1267 | struct cx88_core *core = drv->core; |
1269 | int err = 0; | 1268 | int err = 0; |
1270 | 1269 | ||
1271 | switch (core->board) { | 1270 | switch (core->boardnr) { |
1272 | case CX88_BOARD_HAUPPAUGE_HVR1300: | 1271 | case CX88_BOARD_HAUPPAUGE_HVR1300: |
1273 | /* Exit leaving the cx23416 on the bus */ | 1272 | /* Exit leaving the cx23416 on the bus */ |
1274 | break; | 1273 | break; |
@@ -1316,13 +1315,13 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) | |||
1316 | 1315 | ||
1317 | dprintk( 1, "%s\n", __FUNCTION__); | 1316 | dprintk( 1, "%s\n", __FUNCTION__); |
1318 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", | 1317 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", |
1319 | core->board, | 1318 | core->boardnr, |
1320 | core->name, | 1319 | core->name, |
1321 | core->pci_bus, | 1320 | core->pci_bus, |
1322 | core->pci_slot); | 1321 | core->pci_slot); |
1323 | 1322 | ||
1324 | err = -ENODEV; | 1323 | err = -ENODEV; |
1325 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD)) | 1324 | if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD)) |
1326 | goto fail_core; | 1325 | goto fail_core; |
1327 | 1326 | ||
1328 | dev->width = 720; | 1327 | dev->width = 720; |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 6a136ddbccf8..a4eb6a87a761 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -27,10 +27,26 @@ | |||
27 | 27 | ||
28 | #include "cx88.h" | 28 | #include "cx88.h" |
29 | 29 | ||
30 | static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; | ||
31 | static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; | ||
32 | static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; | ||
33 | |||
34 | module_param_array(tuner, int, NULL, 0444); | ||
35 | module_param_array(radio, int, NULL, 0444); | ||
36 | module_param_array(card, int, NULL, 0444); | ||
37 | |||
38 | MODULE_PARM_DESC(tuner,"tuner type"); | ||
39 | MODULE_PARM_DESC(radio,"radio tuner type"); | ||
40 | MODULE_PARM_DESC(card,"card type"); | ||
41 | |||
42 | static unsigned int latency = UNSET; | ||
43 | module_param(latency,int,0444); | ||
44 | MODULE_PARM_DESC(latency,"pci latency timer"); | ||
45 | |||
30 | /* ------------------------------------------------------------------ */ | 46 | /* ------------------------------------------------------------------ */ |
31 | /* board config info */ | 47 | /* board config info */ |
32 | 48 | ||
33 | struct cx88_board cx88_boards[] = { | 49 | static const struct cx88_board cx88_boards[] = { |
34 | [CX88_BOARD_UNKNOWN] = { | 50 | [CX88_BOARD_UNKNOWN] = { |
35 | .name = "UNKNOWN/GENERIC", | 51 | .name = "UNKNOWN/GENERIC", |
36 | .tuner_type = UNSET, | 52 | .tuner_type = UNSET, |
@@ -575,35 +591,34 @@ struct cx88_board cx88_boards[] = { | |||
575 | .tuner_addr = ADDR_UNSET, | 591 | .tuner_addr = ADDR_UNSET, |
576 | .radio_addr = ADDR_UNSET, | 592 | .radio_addr = ADDR_UNSET, |
577 | .tda9887_conf = TDA9887_PRESENT, | 593 | .tda9887_conf = TDA9887_PRESENT, |
594 | /* GPIO[2] = audio source for analog audio out connector | ||
595 | * 0 = analog audio input connector | ||
596 | * 1 = CX88 audio DACs | ||
597 | * | ||
598 | * GPIO[7] = input to CX88's audio/chroma ADC | ||
599 | * 0 = FM 10.7 MHz IF | ||
600 | * 1 = Sound 4.5 MHz IF | ||
601 | * | ||
602 | * GPIO[1,5,6] = Oren 51132 pins 27,35,28 respectively | ||
603 | * | ||
604 | * GPIO[16] = Remote control input | ||
605 | */ | ||
578 | .input = {{ | 606 | .input = {{ |
579 | .type = CX88_VMUX_TELEVISION, | 607 | .type = CX88_VMUX_TELEVISION, |
580 | .vmux = 0, | 608 | .vmux = 0, |
581 | .gpio0 = 0x00008484, | 609 | .gpio0 = 0x00008484, |
582 | .gpio1 = 0x00000000, | ||
583 | .gpio2 = 0x00000000, | ||
584 | .gpio3 = 0x00000000, | ||
585 | },{ | 610 | },{ |
586 | .type = CX88_VMUX_COMPOSITE1, | 611 | .type = CX88_VMUX_COMPOSITE1, |
587 | .vmux = 1, | 612 | .vmux = 1, |
588 | .gpio0 = 0x00008400, | 613 | .gpio0 = 0x00008400, |
589 | .gpio1 = 0x00000000, | ||
590 | .gpio2 = 0x00000000, | ||
591 | .gpio3 = 0x00000000, | ||
592 | },{ | 614 | },{ |
593 | .type = CX88_VMUX_SVIDEO, | 615 | .type = CX88_VMUX_SVIDEO, |
594 | .vmux = 2, | 616 | .vmux = 2, |
595 | .gpio0 = 0x00008400, | 617 | .gpio0 = 0x00008400, |
596 | .gpio1 = 0x00000000, | ||
597 | .gpio2 = 0x00000000, | ||
598 | .gpio3 = 0x00000000, | ||
599 | }}, | 618 | }}, |
600 | .radio = { | 619 | .radio = { |
601 | .type = CX88_RADIO, | 620 | .type = CX88_RADIO, |
602 | .vmux = 2, | 621 | .gpio0 = 0x00008404, |
603 | .gpio0 = 0x00008400, | ||
604 | .gpio1 = 0x00000000, | ||
605 | .gpio2 = 0x00000000, | ||
606 | .gpio3 = 0x00000000, | ||
607 | }, | 622 | }, |
608 | .mpeg = CX88_MPEG_DVB, | 623 | .mpeg = CX88_MPEG_DVB, |
609 | }, | 624 | }, |
@@ -1356,12 +1371,11 @@ struct cx88_board cx88_boards[] = { | |||
1356 | }}, | 1371 | }}, |
1357 | }, | 1372 | }, |
1358 | }; | 1373 | }; |
1359 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); | ||
1360 | 1374 | ||
1361 | /* ------------------------------------------------------------------ */ | 1375 | /* ------------------------------------------------------------------ */ |
1362 | /* PCI subsystem IDs */ | 1376 | /* PCI subsystem IDs */ |
1363 | 1377 | ||
1364 | struct cx88_subid cx88_subids[] = { | 1378 | static const struct cx88_subid cx88_subids[] = { |
1365 | { | 1379 | { |
1366 | .subvendor = 0x0070, | 1380 | .subvendor = 0x0070, |
1367 | .subdevice = 0x3400, | 1381 | .subdevice = 0x3400, |
@@ -1667,7 +1681,6 @@ struct cx88_subid cx88_subids[] = { | |||
1667 | .card = CX88_BOARD_ADSTECH_PTV_390, | 1681 | .card = CX88_BOARD_ADSTECH_PTV_390, |
1668 | }, | 1682 | }, |
1669 | }; | 1683 | }; |
1670 | const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); | ||
1671 | 1684 | ||
1672 | /* ----------------------------------------------------------------------- */ | 1685 | /* ----------------------------------------------------------------------- */ |
1673 | /* some leadtek specific stuff */ | 1686 | /* some leadtek specific stuff */ |
@@ -1688,12 +1701,12 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) | |||
1688 | return; | 1701 | return; |
1689 | } | 1702 | } |
1690 | 1703 | ||
1691 | core->has_radio = 1; | 1704 | core->board.tuner_type = (eeprom_data[6] == 0x13) ? |
1692 | core->tuner_type = (eeprom_data[6] == 0x13) ? 43 : 38; | 1705 | TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3; |
1693 | 1706 | ||
1694 | printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: " | 1707 | printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: " |
1695 | "tuner=%d, eeprom[0]=0x%02x\n", | 1708 | "tuner=%d, eeprom[0]=0x%02x\n", |
1696 | core->name, core->tuner_type, eeprom_data[0]); | 1709 | core->name, core->board.tuner_type, eeprom_data[0]); |
1697 | } | 1710 | } |
1698 | 1711 | ||
1699 | static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) | 1712 | static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) |
@@ -1701,9 +1714,9 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) | |||
1701 | struct tveeprom tv; | 1714 | struct tveeprom tv; |
1702 | 1715 | ||
1703 | tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data); | 1716 | tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data); |
1704 | core->tuner_type = tv.tuner_type; | 1717 | core->board.tuner_type = tv.tuner_type; |
1705 | core->tuner_formats = tv.tuner_formats; | 1718 | core->tuner_formats = tv.tuner_formats; |
1706 | core->has_radio = tv.has_radio; | 1719 | core->board.radio.type = tv.has_radio ? CX88_RADIO : 0; |
1707 | 1720 | ||
1708 | /* Make sure we support the board model */ | 1721 | /* Make sure we support the board model */ |
1709 | switch (tv.model) | 1722 | switch (tv.model) |
@@ -1793,8 +1806,9 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) | |||
1793 | name ? name : "unknown"); | 1806 | name ? name : "unknown"); |
1794 | if (NULL == name) | 1807 | if (NULL == name) |
1795 | return; | 1808 | return; |
1796 | core->tuner_type = gdi_tuner[eeprom_data[0x0d]].id; | 1809 | core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id; |
1797 | core->has_radio = gdi_tuner[eeprom_data[0x0d]].fm; | 1810 | core->board.radio.type = gdi_tuner[eeprom_data[0x0d]].fm ? |
1811 | CX88_RADIO : 0; | ||
1798 | } | 1812 | } |
1799 | 1813 | ||
1800 | /* ----------------------------------------------------------------------- */ | 1814 | /* ----------------------------------------------------------------------- */ |
@@ -1833,7 +1847,7 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core) | |||
1833 | 1847 | ||
1834 | /* ----------------------------------------------------------------------- */ | 1848 | /* ----------------------------------------------------------------------- */ |
1835 | 1849 | ||
1836 | void cx88_card_list(struct cx88_core *core, struct pci_dev *pci) | 1850 | static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci) |
1837 | { | 1851 | { |
1838 | int i; | 1852 | int i; |
1839 | 1853 | ||
@@ -1854,14 +1868,14 @@ void cx88_card_list(struct cx88_core *core, struct pci_dev *pci) | |||
1854 | } | 1868 | } |
1855 | printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n", | 1869 | printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n", |
1856 | core->name); | 1870 | core->name); |
1857 | for (i = 0; i < cx88_bcount; i++) | 1871 | for (i = 0; i < ARRAY_SIZE(cx88_boards); i++) |
1858 | printk("%s: card=%d -> %s\n", | 1872 | printk("%s: card=%d -> %s\n", |
1859 | core->name, i, cx88_boards[i].name); | 1873 | core->name, i, cx88_boards[i].name); |
1860 | } | 1874 | } |
1861 | 1875 | ||
1862 | void cx88_card_setup_pre_i2c(struct cx88_core *core) | 1876 | static void cx88_card_setup_pre_i2c(struct cx88_core *core) |
1863 | { | 1877 | { |
1864 | switch (core->board) { | 1878 | switch (core->boardnr) { |
1865 | case CX88_BOARD_HAUPPAUGE_HVR1300: | 1879 | case CX88_BOARD_HAUPPAUGE_HVR1300: |
1866 | /* Bring the 702 demod up before i2c scanning/attach or devices are hidden */ | 1880 | /* Bring the 702 demod up before i2c scanning/attach or devices are hidden */ |
1867 | /* We leave here with the 702 on the bus */ | 1881 | /* We leave here with the 702 on the bus */ |
@@ -1875,7 +1889,7 @@ void cx88_card_setup_pre_i2c(struct cx88_core *core) | |||
1875 | } | 1889 | } |
1876 | } | 1890 | } |
1877 | 1891 | ||
1878 | void cx88_card_setup(struct cx88_core *core) | 1892 | static void cx88_card_setup(struct cx88_core *core) |
1879 | { | 1893 | { |
1880 | static u8 eeprom[256]; | 1894 | static u8 eeprom[256]; |
1881 | 1895 | ||
@@ -1884,7 +1898,7 @@ void cx88_card_setup(struct cx88_core *core) | |||
1884 | tveeprom_read(&core->i2c_client,eeprom,sizeof(eeprom)); | 1898 | tveeprom_read(&core->i2c_client,eeprom,sizeof(eeprom)); |
1885 | } | 1899 | } |
1886 | 1900 | ||
1887 | switch (core->board) { | 1901 | switch (core->boardnr) { |
1888 | case CX88_BOARD_HAUPPAUGE: | 1902 | case CX88_BOARD_HAUPPAUGE: |
1889 | case CX88_BOARD_HAUPPAUGE_ROSLYN: | 1903 | case CX88_BOARD_HAUPPAUGE_ROSLYN: |
1890 | if (0 == core->i2c_rc) | 1904 | if (0 == core->i2c_rc) |
@@ -1928,7 +1942,7 @@ void cx88_card_setup(struct cx88_core *core) | |||
1928 | msleep(1); | 1942 | msleep(1); |
1929 | cx_set(MO_GP0_IO, 0x00000101); | 1943 | cx_set(MO_GP0_IO, 0x00000101); |
1930 | if (0 == core->i2c_rc && | 1944 | if (0 == core->i2c_rc && |
1931 | core->board == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID) | 1945 | core->boardnr == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID) |
1932 | dvico_fusionhdtv_hybrid_init(core); | 1946 | dvico_fusionhdtv_hybrid_init(core); |
1933 | break; | 1947 | break; |
1934 | case CX88_BOARD_KWORLD_DVB_T: | 1948 | case CX88_BOARD_KWORLD_DVB_T: |
@@ -1966,13 +1980,148 @@ void cx88_card_setup(struct cx88_core *core) | |||
1966 | } | 1980 | } |
1967 | break; | 1981 | break; |
1968 | } | 1982 | } |
1969 | if (cx88_boards[core->board].radio.type == CX88_RADIO) | ||
1970 | core->has_radio = 1; | ||
1971 | } | 1983 | } |
1972 | 1984 | ||
1973 | /* ------------------------------------------------------------------ */ | 1985 | /* ------------------------------------------------------------------ */ |
1974 | 1986 | ||
1975 | EXPORT_SYMBOL(cx88_boards); | 1987 | static int cx88_pci_quirks(const char *name, struct pci_dev *pci) |
1988 | { | ||
1989 | unsigned int lat = UNSET; | ||
1990 | u8 ctrl = 0; | ||
1991 | u8 value; | ||
1992 | |||
1993 | /* check pci quirks */ | ||
1994 | if (pci_pci_problems & PCIPCI_TRITON) { | ||
1995 | printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n", | ||
1996 | name); | ||
1997 | ctrl |= CX88X_EN_TBFX; | ||
1998 | } | ||
1999 | if (pci_pci_problems & PCIPCI_NATOMA) { | ||
2000 | printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n", | ||
2001 | name); | ||
2002 | ctrl |= CX88X_EN_TBFX; | ||
2003 | } | ||
2004 | if (pci_pci_problems & PCIPCI_VIAETBF) { | ||
2005 | printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n", | ||
2006 | name); | ||
2007 | ctrl |= CX88X_EN_TBFX; | ||
2008 | } | ||
2009 | if (pci_pci_problems & PCIPCI_VSFX) { | ||
2010 | printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n", | ||
2011 | name); | ||
2012 | ctrl |= CX88X_EN_VSFX; | ||
2013 | } | ||
2014 | #ifdef PCIPCI_ALIMAGIK | ||
2015 | if (pci_pci_problems & PCIPCI_ALIMAGIK) { | ||
2016 | printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n", | ||
2017 | name); | ||
2018 | lat = 0x0A; | ||
2019 | } | ||
2020 | #endif | ||
2021 | |||
2022 | /* check insmod options */ | ||
2023 | if (UNSET != latency) | ||
2024 | lat = latency; | ||
2025 | |||
2026 | /* apply stuff */ | ||
2027 | if (ctrl) { | ||
2028 | pci_read_config_byte(pci, CX88X_DEVCTRL, &value); | ||
2029 | value |= ctrl; | ||
2030 | pci_write_config_byte(pci, CX88X_DEVCTRL, value); | ||
2031 | } | ||
2032 | if (UNSET != lat) { | ||
2033 | printk(KERN_INFO "%s: setting pci latency timer to %d\n", | ||
2034 | name, latency); | ||
2035 | pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency); | ||
2036 | } | ||
2037 | return 0; | ||
2038 | } | ||
2039 | |||
2040 | int cx88_get_resources(const struct cx88_core *core, struct pci_dev *pci) | ||
2041 | { | ||
2042 | if (request_mem_region(pci_resource_start(pci,0), | ||
2043 | pci_resource_len(pci,0), | ||
2044 | core->name)) | ||
2045 | return 0; | ||
2046 | printk(KERN_ERR | ||
2047 | "%s/%d: Can't get MMIO memory @ 0x%llx, subsystem: %04x:%04x\n", | ||
2048 | core->name, PCI_FUNC(pci->devfn), | ||
2049 | (unsigned long long)pci_resource_start(pci, 0), | ||
2050 | pci->subsystem_vendor, pci->subsystem_device); | ||
2051 | return -EBUSY; | ||
2052 | } | ||
2053 | |||
2054 | /* Allocate and initialize the cx88 core struct. One should hold the | ||
2055 | * devlist mutex before calling this. */ | ||
2056 | struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) | ||
2057 | { | ||
2058 | struct cx88_core *core; | ||
2059 | int i; | ||
2060 | |||
2061 | core = kzalloc(sizeof(*core), GFP_KERNEL); | ||
2062 | |||
2063 | atomic_inc(&core->refcount); | ||
2064 | core->pci_bus = pci->bus->number; | ||
2065 | core->pci_slot = PCI_SLOT(pci->devfn); | ||
2066 | core->pci_irqmask = PCI_INT_RISC_RD_BERRINT | PCI_INT_RISC_WR_BERRINT | | ||
2067 | PCI_INT_BRDG_BERRINT | PCI_INT_SRC_DMA_BERRINT | | ||
2068 | PCI_INT_DST_DMA_BERRINT | PCI_INT_IPB_DMA_BERRINT; | ||
2069 | mutex_init(&core->lock); | ||
2070 | |||
2071 | core->nr = nr; | ||
2072 | sprintf(core->name, "cx88[%d]", core->nr); | ||
2073 | if (0 != cx88_get_resources(core, pci)) { | ||
2074 | kfree(core); | ||
2075 | return NULL; | ||
2076 | } | ||
2077 | |||
2078 | /* PCI stuff */ | ||
2079 | cx88_pci_quirks(core->name, pci); | ||
2080 | core->lmmio = ioremap(pci_resource_start(pci, 0), | ||
2081 | pci_resource_len(pci, 0)); | ||
2082 | core->bmmio = (u8 __iomem *)core->lmmio; | ||
2083 | |||
2084 | /* board config */ | ||
2085 | core->boardnr = UNSET; | ||
2086 | if (card[core->nr] < ARRAY_SIZE(cx88_boards)) | ||
2087 | core->boardnr = card[core->nr]; | ||
2088 | for (i = 0; UNSET == core->boardnr && i < ARRAY_SIZE(cx88_subids); i++) | ||
2089 | if (pci->subsystem_vendor == cx88_subids[i].subvendor && | ||
2090 | pci->subsystem_device == cx88_subids[i].subdevice) | ||
2091 | core->boardnr = cx88_subids[i].card; | ||
2092 | if (UNSET == core->boardnr) { | ||
2093 | core->boardnr = CX88_BOARD_UNKNOWN; | ||
2094 | cx88_card_list(core, pci); | ||
2095 | } | ||
2096 | |||
2097 | memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board)); | ||
2098 | |||
2099 | printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", | ||
2100 | core->name,pci->subsystem_vendor, | ||
2101 | pci->subsystem_device, core->board.name, | ||
2102 | core->boardnr, card[core->nr] == core->boardnr ? | ||
2103 | "insmod option" : "autodetected"); | ||
2104 | |||
2105 | if (tuner[core->nr] != UNSET) | ||
2106 | core->board.tuner_type = tuner[core->nr]; | ||
2107 | if (radio[core->nr] != UNSET) | ||
2108 | core->board.radio_type = radio[core->nr]; | ||
2109 | |||
2110 | printk(KERN_INFO "%s: TV tuner type %d, Radio tuner type %d\n", | ||
2111 | core->name, core->board.tuner_type, core->board.radio_type); | ||
2112 | |||
2113 | /* init hardware */ | ||
2114 | cx88_reset(core); | ||
2115 | cx88_card_setup_pre_i2c(core); | ||
2116 | cx88_i2c_init(core, pci); | ||
2117 | cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL); | ||
2118 | cx88_card_setup(core); | ||
2119 | cx88_ir_init(core, pci); | ||
2120 | |||
2121 | return core; | ||
2122 | } | ||
2123 | |||
2124 | /* ------------------------------------------------------------------ */ | ||
1976 | 2125 | ||
1977 | /* | 2126 | /* |
1978 | * Local variables: | 2127 | * Local variables: |
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index f31ec96924b9..62e8dd24c5f5 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
34 | #include <linux/kmod.h> | 33 | #include <linux/kmod.h> |
@@ -52,22 +51,6 @@ static unsigned int core_debug = 0; | |||
52 | module_param(core_debug,int,0644); | 51 | module_param(core_debug,int,0644); |
53 | MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); | 52 | MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); |
54 | 53 | ||
55 | static unsigned int latency = UNSET; | ||
56 | module_param(latency,int,0444); | ||
57 | MODULE_PARM_DESC(latency,"pci latency timer"); | ||
58 | |||
59 | static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; | ||
60 | static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; | ||
61 | static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; | ||
62 | |||
63 | module_param_array(tuner, int, NULL, 0444); | ||
64 | module_param_array(radio, int, NULL, 0444); | ||
65 | module_param_array(card, int, NULL, 0444); | ||
66 | |||
67 | MODULE_PARM_DESC(tuner,"tuner type"); | ||
68 | MODULE_PARM_DESC(radio,"radio tuner type"); | ||
69 | MODULE_PARM_DESC(card,"card type"); | ||
70 | |||
71 | static unsigned int nicam = 0; | 54 | static unsigned int nicam = 0; |
72 | module_param(nicam,int,0644); | 55 | module_param(nicam,int,0644); |
73 | MODULE_PARM_DESC(nicam,"tv audio is nicam"); | 56 | MODULE_PARM_DESC(nicam,"tv audio is nicam"); |
@@ -85,13 +68,15 @@ static DEFINE_MUTEX(devlist); | |||
85 | 68 | ||
86 | #define NO_SYNC_LINE (-1U) | 69 | #define NO_SYNC_LINE (-1U) |
87 | 70 | ||
71 | /* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be | ||
72 | generated _after_ lpi lines are transferred. */ | ||
88 | static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, | 73 | static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, |
89 | unsigned int offset, u32 sync_line, | 74 | unsigned int offset, u32 sync_line, |
90 | unsigned int bpl, unsigned int padding, | 75 | unsigned int bpl, unsigned int padding, |
91 | unsigned int lines) | 76 | unsigned int lines, unsigned int lpi) |
92 | { | 77 | { |
93 | struct scatterlist *sg; | 78 | struct scatterlist *sg; |
94 | unsigned int line,todo; | 79 | unsigned int line,todo,sol; |
95 | 80 | ||
96 | /* sync instruction */ | 81 | /* sync instruction */ |
97 | if (sync_line != NO_SYNC_LINE) | 82 | if (sync_line != NO_SYNC_LINE) |
@@ -104,15 +89,19 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, | |||
104 | offset -= sg_dma_len(sg); | 89 | offset -= sg_dma_len(sg); |
105 | sg++; | 90 | sg++; |
106 | } | 91 | } |
92 | if (lpi && line>0 && !(line % lpi)) | ||
93 | sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC; | ||
94 | else | ||
95 | sol = RISC_SOL; | ||
107 | if (bpl <= sg_dma_len(sg)-offset) { | 96 | if (bpl <= sg_dma_len(sg)-offset) { |
108 | /* fits into current chunk */ | 97 | /* fits into current chunk */ |
109 | *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); | 98 | *(rp++)=cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl); |
110 | *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); | 99 | *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); |
111 | offset+=bpl; | 100 | offset+=bpl; |
112 | } else { | 101 | } else { |
113 | /* scanline needs to be split */ | 102 | /* scanline needs to be split */ |
114 | todo = bpl; | 103 | todo = bpl; |
115 | *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL| | 104 | *(rp++)=cpu_to_le32(RISC_WRITE|sol| |
116 | (sg_dma_len(sg)-offset)); | 105 | (sg_dma_len(sg)-offset)); |
117 | *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); | 106 | *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); |
118 | todo -= (sg_dma_len(sg)-offset); | 107 | todo -= (sg_dma_len(sg)-offset); |
@@ -163,10 +152,10 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |||
163 | rp = risc->cpu; | 152 | rp = risc->cpu; |
164 | if (UNSET != top_offset) | 153 | if (UNSET != top_offset) |
165 | rp = cx88_risc_field(rp, sglist, top_offset, 0, | 154 | rp = cx88_risc_field(rp, sglist, top_offset, 0, |
166 | bpl, padding, lines); | 155 | bpl, padding, lines, 0); |
167 | if (UNSET != bottom_offset) | 156 | if (UNSET != bottom_offset) |
168 | rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200, | 157 | rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200, |
169 | bpl, padding, lines); | 158 | bpl, padding, lines, 0); |
170 | 159 | ||
171 | /* save pointer to jmp instruction address */ | 160 | /* save pointer to jmp instruction address */ |
172 | risc->jmp = rp; | 161 | risc->jmp = rp; |
@@ -176,7 +165,7 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |||
176 | 165 | ||
177 | int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, | 166 | int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, |
178 | struct scatterlist *sglist, unsigned int bpl, | 167 | struct scatterlist *sglist, unsigned int bpl, |
179 | unsigned int lines) | 168 | unsigned int lines, unsigned int lpi) |
180 | { | 169 | { |
181 | u32 instructions; | 170 | u32 instructions; |
182 | u32 *rp; | 171 | u32 *rp; |
@@ -193,7 +182,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |||
193 | 182 | ||
194 | /* write risc instructions */ | 183 | /* write risc instructions */ |
195 | rp = risc->cpu; | 184 | rp = risc->cpu; |
196 | rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines); | 185 | rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi); |
197 | 186 | ||
198 | /* save pointer to jmp instruction address */ | 187 | /* save pointer to jmp instruction address */ |
199 | risc->jmp = rp; | 188 | risc->jmp = rp; |
@@ -224,10 +213,12 @@ int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | |||
224 | void | 213 | void |
225 | cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) | 214 | cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) |
226 | { | 215 | { |
216 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
217 | |||
227 | BUG_ON(in_interrupt()); | 218 | BUG_ON(in_interrupt()); |
228 | videobuf_waiton(&buf->vb,0,0); | 219 | videobuf_waiton(&buf->vb,0,0); |
229 | videobuf_dma_unmap(q, &buf->vb.dma); | 220 | videobuf_dma_unmap(q, dma); |
230 | videobuf_dma_free(&buf->vb.dma); | 221 | videobuf_dma_free(dma); |
231 | btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc); | 222 | btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc); |
232 | buf->vb.state = STATE_NEEDS_INIT; | 223 | buf->vb.state = STATE_NEEDS_INIT; |
233 | } | 224 | } |
@@ -451,10 +442,13 @@ void cx88_sram_channel_dump(struct cx88_core *core, | |||
451 | printk("%s: cmds: %-12s: 0x%08x\n", | 442 | printk("%s: cmds: %-12s: 0x%08x\n", |
452 | core->name,name[i], | 443 | core->name,name[i], |
453 | cx_read(ch->cmds_start + 4*i)); | 444 | cx_read(ch->cmds_start + 4*i)); |
454 | for (i = 0; i < 4; i++) { | 445 | for (n = 1, i = 0; i < 4; i++) { |
455 | risc = cx_read(ch->cmds_start + 4 * (i+11)); | 446 | risc = cx_read(ch->cmds_start + 4 * (i+11)); |
456 | printk("%s: risc%d: ", core->name, i); | 447 | printk("%s: risc%d: ", core->name, i); |
457 | cx88_risc_decode(risc); | 448 | if (--n) |
449 | printk("0x%08x [ arg #%d ]\n", risc, n); | ||
450 | else | ||
451 | n = cx88_risc_decode(risc); | ||
458 | } | 452 | } |
459 | for (i = 0; i < 16; i += n) { | 453 | for (i = 0; i < 16; i += n) { |
460 | risc = cx_read(ch->ctrl_start + 4 * i); | 454 | risc = cx_read(ch->ctrl_start + 4 * i); |
@@ -514,7 +508,7 @@ int cx88_core_irq(struct cx88_core *core, u32 status) | |||
514 | { | 508 | { |
515 | int handled = 0; | 509 | int handled = 0; |
516 | 510 | ||
517 | if (status & (1<<18)) { | 511 | if (status & PCI_INT_IR_SMPINT) { |
518 | cx88_ir_irq(core); | 512 | cx88_ir_irq(core); |
519 | handled++; | 513 | handled++; |
520 | } | 514 | } |
@@ -738,7 +732,7 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig | |||
738 | value |= (1 << 15); | 732 | value |= (1 << 15); |
739 | value |= (1 << 16); | 733 | value |= (1 << 16); |
740 | } | 734 | } |
741 | if (INPUT(core->input)->type == CX88_VMUX_SVIDEO) | 735 | if (INPUT(core->input).type == CX88_VMUX_SVIDEO) |
742 | value |= (1 << 13) | (1 << 5); | 736 | value |= (1 << 13) | (1 << 5); |
743 | if (V4L2_FIELD_INTERLACED == field) | 737 | if (V4L2_FIELD_INTERLACED == field) |
744 | value |= (1 << 3); // VINT (interlaced vertical scaling) | 738 | value |= (1 << 3); // VINT (interlaced vertical scaling) |
@@ -833,7 +827,7 @@ static int set_tvaudio(struct cx88_core *core) | |||
833 | { | 827 | { |
834 | v4l2_std_id norm = core->tvnorm; | 828 | v4l2_std_id norm = core->tvnorm; |
835 | 829 | ||
836 | if (CX88_VMUX_TELEVISION != INPUT(core->input)->type) | 830 | if (CX88_VMUX_TELEVISION != INPUT(core->input).type) |
837 | return 0; | 831 | return 0; |
838 | 832 | ||
839 | if (V4L2_STD_PAL_BG & norm) { | 833 | if (V4L2_STD_PAL_BG & norm) { |
@@ -997,61 +991,6 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) | |||
997 | 991 | ||
998 | /* ------------------------------------------------------------------ */ | 992 | /* ------------------------------------------------------------------ */ |
999 | 993 | ||
1000 | static int cx88_pci_quirks(char *name, struct pci_dev *pci) | ||
1001 | { | ||
1002 | unsigned int lat = UNSET; | ||
1003 | u8 ctrl = 0; | ||
1004 | u8 value; | ||
1005 | |||
1006 | /* check pci quirks */ | ||
1007 | if (pci_pci_problems & PCIPCI_TRITON) { | ||
1008 | printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n", | ||
1009 | name); | ||
1010 | ctrl |= CX88X_EN_TBFX; | ||
1011 | } | ||
1012 | if (pci_pci_problems & PCIPCI_NATOMA) { | ||
1013 | printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n", | ||
1014 | name); | ||
1015 | ctrl |= CX88X_EN_TBFX; | ||
1016 | } | ||
1017 | if (pci_pci_problems & PCIPCI_VIAETBF) { | ||
1018 | printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n", | ||
1019 | name); | ||
1020 | ctrl |= CX88X_EN_TBFX; | ||
1021 | } | ||
1022 | if (pci_pci_problems & PCIPCI_VSFX) { | ||
1023 | printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n", | ||
1024 | name); | ||
1025 | ctrl |= CX88X_EN_VSFX; | ||
1026 | } | ||
1027 | #ifdef PCIPCI_ALIMAGIK | ||
1028 | if (pci_pci_problems & PCIPCI_ALIMAGIK) { | ||
1029 | printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n", | ||
1030 | name); | ||
1031 | lat = 0x0A; | ||
1032 | } | ||
1033 | #endif | ||
1034 | |||
1035 | /* check insmod options */ | ||
1036 | if (UNSET != latency) | ||
1037 | lat = latency; | ||
1038 | |||
1039 | /* apply stuff */ | ||
1040 | if (ctrl) { | ||
1041 | pci_read_config_byte(pci, CX88X_DEVCTRL, &value); | ||
1042 | value |= ctrl; | ||
1043 | pci_write_config_byte(pci, CX88X_DEVCTRL, value); | ||
1044 | } | ||
1045 | if (UNSET != lat) { | ||
1046 | printk(KERN_INFO "%s: setting pci latency timer to %d\n", | ||
1047 | name, latency); | ||
1048 | pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency); | ||
1049 | } | ||
1050 | return 0; | ||
1051 | } | ||
1052 | |||
1053 | /* ------------------------------------------------------------------ */ | ||
1054 | |||
1055 | struct video_device *cx88_vdev_init(struct cx88_core *core, | 994 | struct video_device *cx88_vdev_init(struct cx88_core *core, |
1056 | struct pci_dev *pci, | 995 | struct pci_dev *pci, |
1057 | struct video_device *template, | 996 | struct video_device *template, |
@@ -1067,122 +1006,38 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, | |||
1067 | vfd->dev = &pci->dev; | 1006 | vfd->dev = &pci->dev; |
1068 | vfd->release = video_device_release; | 1007 | vfd->release = video_device_release; |
1069 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", | 1008 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", |
1070 | core->name, type, cx88_boards[core->board].name); | 1009 | core->name, type, core->board.name); |
1071 | return vfd; | 1010 | return vfd; |
1072 | } | 1011 | } |
1073 | 1012 | ||
1074 | static int get_ressources(struct cx88_core *core, struct pci_dev *pci) | ||
1075 | { | ||
1076 | if (request_mem_region(pci_resource_start(pci,0), | ||
1077 | pci_resource_len(pci,0), | ||
1078 | core->name)) | ||
1079 | return 0; | ||
1080 | printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n", | ||
1081 | core->name,(unsigned long long)pci_resource_start(pci,0)); | ||
1082 | return -EBUSY; | ||
1083 | } | ||
1084 | |||
1085 | struct cx88_core* cx88_core_get(struct pci_dev *pci) | 1013 | struct cx88_core* cx88_core_get(struct pci_dev *pci) |
1086 | { | 1014 | { |
1087 | struct cx88_core *core; | 1015 | struct cx88_core *core; |
1088 | struct list_head *item; | ||
1089 | int i; | ||
1090 | 1016 | ||
1091 | mutex_lock(&devlist); | 1017 | mutex_lock(&devlist); |
1092 | list_for_each(item,&cx88_devlist) { | 1018 | list_for_each_entry(core, &cx88_devlist, devlist) { |
1093 | core = list_entry(item, struct cx88_core, devlist); | ||
1094 | if (pci->bus->number != core->pci_bus) | 1019 | if (pci->bus->number != core->pci_bus) |
1095 | continue; | 1020 | continue; |
1096 | if (PCI_SLOT(pci->devfn) != core->pci_slot) | 1021 | if (PCI_SLOT(pci->devfn) != core->pci_slot) |
1097 | continue; | 1022 | continue; |
1098 | 1023 | ||
1099 | if (0 != get_ressources(core,pci)) | 1024 | if (0 != cx88_get_resources(core, pci)) { |
1100 | goto fail_unlock; | 1025 | mutex_unlock(&devlist); |
1026 | return NULL; | ||
1027 | } | ||
1101 | atomic_inc(&core->refcount); | 1028 | atomic_inc(&core->refcount); |
1102 | mutex_unlock(&devlist); | 1029 | mutex_unlock(&devlist); |
1103 | return core; | 1030 | return core; |
1104 | } | 1031 | } |
1105 | core = kzalloc(sizeof(*core),GFP_KERNEL); | 1032 | |
1106 | if (NULL == core) | 1033 | core = cx88_core_create(pci, cx88_devcount); |
1107 | goto fail_unlock; | 1034 | if (NULL != core) { |
1108 | 1035 | cx88_devcount++; | |
1109 | atomic_inc(&core->refcount); | 1036 | list_add_tail(&core->devlist, &cx88_devlist); |
1110 | core->pci_bus = pci->bus->number; | ||
1111 | core->pci_slot = PCI_SLOT(pci->devfn); | ||
1112 | core->pci_irqmask = 0x00fc00; | ||
1113 | mutex_init(&core->lock); | ||
1114 | |||
1115 | core->nr = cx88_devcount++; | ||
1116 | sprintf(core->name,"cx88[%d]",core->nr); | ||
1117 | if (0 != get_ressources(core,pci)) { | ||
1118 | printk(KERN_ERR "CORE %s No more PCI ressources for " | ||
1119 | "subsystem: %04x:%04x, board: %s\n", | ||
1120 | core->name,pci->subsystem_vendor, | ||
1121 | pci->subsystem_device, | ||
1122 | cx88_boards[core->board].name); | ||
1123 | |||
1124 | cx88_devcount--; | ||
1125 | goto fail_free; | ||
1126 | } | ||
1127 | list_add_tail(&core->devlist,&cx88_devlist); | ||
1128 | |||
1129 | /* PCI stuff */ | ||
1130 | cx88_pci_quirks(core->name, pci); | ||
1131 | core->lmmio = ioremap(pci_resource_start(pci,0), | ||
1132 | pci_resource_len(pci,0)); | ||
1133 | core->bmmio = (u8 __iomem *)core->lmmio; | ||
1134 | |||
1135 | /* board config */ | ||
1136 | core->board = UNSET; | ||
1137 | if (card[core->nr] < cx88_bcount) | ||
1138 | core->board = card[core->nr]; | ||
1139 | for (i = 0; UNSET == core->board && i < cx88_idcount; i++) | ||
1140 | if (pci->subsystem_vendor == cx88_subids[i].subvendor && | ||
1141 | pci->subsystem_device == cx88_subids[i].subdevice) | ||
1142 | core->board = cx88_subids[i].card; | ||
1143 | if (UNSET == core->board) { | ||
1144 | core->board = CX88_BOARD_UNKNOWN; | ||
1145 | cx88_card_list(core,pci); | ||
1146 | } | 1037 | } |
1147 | printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", | ||
1148 | core->name,pci->subsystem_vendor, | ||
1149 | pci->subsystem_device,cx88_boards[core->board].name, | ||
1150 | core->board, card[core->nr] == core->board ? | ||
1151 | "insmod option" : "autodetected"); | ||
1152 | |||
1153 | core->tuner_type = tuner[core->nr]; | ||
1154 | core->radio_type = radio[core->nr]; | ||
1155 | if (UNSET == core->tuner_type) | ||
1156 | core->tuner_type = cx88_boards[core->board].tuner_type; | ||
1157 | if (UNSET == core->radio_type) | ||
1158 | core->radio_type = cx88_boards[core->board].radio_type; | ||
1159 | if (!core->tuner_addr) | ||
1160 | core->tuner_addr = cx88_boards[core->board].tuner_addr; | ||
1161 | if (!core->radio_addr) | ||
1162 | core->radio_addr = cx88_boards[core->board].radio_addr; | ||
1163 | |||
1164 | printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n", | ||
1165 | core->tuner_type, core->tuner_addr<<1, | ||
1166 | core->radio_type, core->radio_addr<<1); | ||
1167 | |||
1168 | core->tda9887_conf = cx88_boards[core->board].tda9887_conf; | ||
1169 | |||
1170 | /* init hardware */ | ||
1171 | cx88_reset(core); | ||
1172 | cx88_card_setup_pre_i2c(core); | ||
1173 | cx88_i2c_init(core,pci); | ||
1174 | cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL); | ||
1175 | cx88_card_setup(core); | ||
1176 | cx88_ir_init(core,pci); | ||
1177 | 1038 | ||
1178 | mutex_unlock(&devlist); | 1039 | mutex_unlock(&devlist); |
1179 | return core; | 1040 | return core; |
1180 | |||
1181 | fail_free: | ||
1182 | kfree(core); | ||
1183 | fail_unlock: | ||
1184 | mutex_unlock(&devlist); | ||
1185 | return NULL; | ||
1186 | } | 1041 | } |
1187 | 1042 | ||
1188 | void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) | 1043 | void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) |
@@ -1229,6 +1084,9 @@ EXPORT_SYMBOL(cx88_vdev_init); | |||
1229 | EXPORT_SYMBOL(cx88_core_get); | 1084 | EXPORT_SYMBOL(cx88_core_get); |
1230 | EXPORT_SYMBOL(cx88_core_put); | 1085 | EXPORT_SYMBOL(cx88_core_put); |
1231 | 1086 | ||
1087 | EXPORT_SYMBOL(cx88_ir_start); | ||
1088 | EXPORT_SYMBOL(cx88_ir_stop); | ||
1089 | |||
1232 | /* | 1090 | /* |
1233 | * Local variables: | 1091 | * Local variables: |
1234 | * c-basic-offset: 8 | 1092 | * c-basic-offset: 8 |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 1773b40467dc..d16e5c6d21c0 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -378,7 +378,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
378 | dev->ts_gen_cntrl = 0x0c; | 378 | dev->ts_gen_cntrl = 0x0c; |
379 | 379 | ||
380 | /* init frontend */ | 380 | /* init frontend */ |
381 | switch (dev->core->board) { | 381 | switch (dev->core->boardnr) { |
382 | case CX88_BOARD_HAUPPAUGE_DVB_T1: | 382 | case CX88_BOARD_HAUPPAUGE_DVB_T1: |
383 | dev->dvb.frontend = dvb_attach(cx22702_attach, | 383 | dev->dvb.frontend = dvb_attach(cx22702_attach, |
384 | &connexant_refboard_config, | 384 | &connexant_refboard_config, |
@@ -482,7 +482,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
482 | &dev->core->i2c_adap, DVB_PLL_FMD1216ME); | 482 | &dev->core->i2c_adap, DVB_PLL_FMD1216ME); |
483 | } | 483 | } |
484 | #else | 484 | #else |
485 | printk("%s: built without vp3054 support\n", dev->core->name); | 485 | printk(KERN_ERR "%s/2: built without vp3054 support\n", dev->core->name); |
486 | #endif | 486 | #endif |
487 | break; | 487 | break; |
488 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: | 488 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: |
@@ -625,12 +625,12 @@ static int dvb_register(struct cx8802_dev *dev) | |||
625 | } | 625 | } |
626 | break; | 626 | break; |
627 | default: | 627 | default: |
628 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", | 628 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", |
629 | dev->core->name); | 629 | dev->core->name); |
630 | break; | 630 | break; |
631 | } | 631 | } |
632 | if (NULL == dev->dvb.frontend) { | 632 | if (NULL == dev->dvb.frontend) { |
633 | printk("%s: frontend initialization failed\n",dev->core->name); | 633 | printk(KERN_ERR "%s/2: frontend initialization failed\n", dev->core->name); |
634 | return -1; | 634 | return -1; |
635 | } | 635 | } |
636 | 636 | ||
@@ -653,7 +653,7 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) | |||
653 | int err = 0; | 653 | int err = 0; |
654 | dprintk( 1, "%s\n", __FUNCTION__); | 654 | dprintk( 1, "%s\n", __FUNCTION__); |
655 | 655 | ||
656 | switch (core->board) { | 656 | switch (core->boardnr) { |
657 | case CX88_BOARD_HAUPPAUGE_HVR1300: | 657 | case CX88_BOARD_HAUPPAUGE_HVR1300: |
658 | /* We arrive here with either the cx23416 or the cx22702 | 658 | /* We arrive here with either the cx23416 or the cx22702 |
659 | * on the bus. Take the bus from the cx23416 and enable the | 659 | * on the bus. Take the bus from the cx23416 and enable the |
@@ -676,7 +676,7 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv) | |||
676 | int err = 0; | 676 | int err = 0; |
677 | dprintk( 1, "%s\n", __FUNCTION__); | 677 | dprintk( 1, "%s\n", __FUNCTION__); |
678 | 678 | ||
679 | switch (core->board) { | 679 | switch (core->boardnr) { |
680 | case CX88_BOARD_HAUPPAUGE_HVR1300: | 680 | case CX88_BOARD_HAUPPAUGE_HVR1300: |
681 | /* Do Nothing, leave the cx22702 on the bus. */ | 681 | /* Do Nothing, leave the cx22702 on the bus. */ |
682 | break; | 682 | break; |
@@ -694,13 +694,13 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) | |||
694 | 694 | ||
695 | dprintk( 1, "%s\n", __FUNCTION__); | 695 | dprintk( 1, "%s\n", __FUNCTION__); |
696 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", | 696 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", |
697 | core->board, | 697 | core->boardnr, |
698 | core->name, | 698 | core->name, |
699 | core->pci_bus, | 699 | core->pci_bus, |
700 | core->pci_slot); | 700 | core->pci_slot); |
701 | 701 | ||
702 | err = -ENODEV; | 702 | err = -ENODEV; |
703 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) | 703 | if (!(core->board.mpeg & CX88_MPEG_DVB)) |
704 | goto fail_core; | 704 | goto fail_core; |
705 | 705 | ||
706 | /* If vp3054 isn't enabled, a stub will just return 0 */ | 706 | /* If vp3054 isn't enabled, a stub will just return 0 */ |
@@ -709,8 +709,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) | |||
709 | goto fail_core; | 709 | goto fail_core; |
710 | 710 | ||
711 | /* dvb stuff */ | 711 | /* dvb stuff */ |
712 | printk("%s/2: cx2388x based dvb card\n", core->name); | 712 | printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); |
713 | videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops, | 713 | videobuf_queue_pci_init(&dev->dvb.dvbq, &dvb_qops, |
714 | dev->pci, &dev->slock, | 714 | dev->pci, &dev->slock, |
715 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 715 | V4L2_BUF_TYPE_VIDEO_CAPTURE, |
716 | V4L2_FIELD_TOP, | 716 | V4L2_FIELD_TOP, |
@@ -718,7 +718,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) | |||
718 | dev); | 718 | dev); |
719 | err = dvb_register(dev); | 719 | err = dvb_register(dev); |
720 | if (err != 0) | 720 | if (err != 0) |
721 | printk("%s dvb_register failed err = %d\n", __FUNCTION__, err); | 721 | printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n", |
722 | core->name, err); | ||
722 | 723 | ||
723 | fail_core: | 724 | fail_core: |
724 | return err; | 725 | return err; |
@@ -747,7 +748,7 @@ static struct cx8802_driver cx8802_dvb_driver = { | |||
747 | 748 | ||
748 | static int dvb_init(void) | 749 | static int dvb_init(void) |
749 | { | 750 | { |
750 | printk(KERN_INFO "cx2388x dvb driver version %d.%d.%d loaded\n", | 751 | printk(KERN_INFO "cx88/2: cx2388x dvb driver version %d.%d.%d loaded\n", |
751 | (CX88_VERSION_CODE >> 16) & 0xff, | 752 | (CX88_VERSION_CODE >> 16) & 0xff, |
752 | (CX88_VERSION_CODE >> 8) & 0xff, | 753 | (CX88_VERSION_CODE >> 8) & 0xff, |
753 | CX88_VERSION_CODE & 0xff); | 754 | CX88_VERSION_CODE & 0xff); |
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 78bbcfab9670..c8b1c50625f4 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c | |||
@@ -28,7 +28,6 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/init.h> | 31 | #include <linux/init.h> |
33 | 32 | ||
34 | #include <asm/io.h> | 33 | #include <asm/io.h> |
@@ -108,28 +107,28 @@ static int attach_inform(struct i2c_client *client) | |||
108 | if (!client->driver->command) | 107 | if (!client->driver->command) |
109 | return 0; | 108 | return 0; |
110 | 109 | ||
111 | if (core->radio_type != UNSET) { | 110 | if (core->board.radio_type != UNSET) { |
112 | if ((core->radio_addr==ADDR_UNSET)||(core->radio_addr==client->addr)) { | 111 | if ((core->board.radio_addr==ADDR_UNSET)||(core->board.radio_addr==client->addr)) { |
113 | tun_setup.mode_mask = T_RADIO; | 112 | tun_setup.mode_mask = T_RADIO; |
114 | tun_setup.type = core->radio_type; | 113 | tun_setup.type = core->board.radio_type; |
115 | tun_setup.addr = core->radio_addr; | 114 | tun_setup.addr = core->board.radio_addr; |
116 | 115 | ||
117 | client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); | 116 | client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); |
118 | } | 117 | } |
119 | } | 118 | } |
120 | if (core->tuner_type != UNSET) { | 119 | if (core->board.tuner_type != UNSET) { |
121 | if ((core->tuner_addr==ADDR_UNSET)||(core->tuner_addr==client->addr)) { | 120 | if ((core->board.tuner_addr==ADDR_UNSET)||(core->board.tuner_addr==client->addr)) { |
122 | 121 | ||
123 | tun_setup.mode_mask = T_ANALOG_TV; | 122 | tun_setup.mode_mask = T_ANALOG_TV; |
124 | tun_setup.type = core->tuner_type; | 123 | tun_setup.type = core->board.tuner_type; |
125 | tun_setup.addr = core->tuner_addr; | 124 | tun_setup.addr = core->board.tuner_addr; |
126 | 125 | ||
127 | client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup); | 126 | client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup); |
128 | } | 127 | } |
129 | } | 128 | } |
130 | 129 | ||
131 | if (core->tda9887_conf) | 130 | if (core->board.tda9887_conf) |
132 | client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf); | 131 | client->driver->command(client, TDA9887_SET_CONFIG, &core->board.tda9887_conf); |
133 | return 0; | 132 | return 0; |
134 | } | 133 | } |
135 | 134 | ||
@@ -146,7 +145,7 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) | |||
146 | if (0 != core->i2c_rc) | 145 | if (0 != core->i2c_rc) |
147 | return; | 146 | return; |
148 | 147 | ||
149 | #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) | 148 | #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) |
150 | if ( (core->dvbdev) && (core->dvbdev->dvb.frontend) ) { | 149 | if ( (core->dvbdev) && (core->dvbdev->dvb.frontend) ) { |
151 | if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) | 150 | if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) |
152 | core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1); | 151 | core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1); |
@@ -204,9 +203,9 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) | |||
204 | memcpy(&core->i2c_algo, &cx8800_i2c_algo_template, | 203 | memcpy(&core->i2c_algo, &cx8800_i2c_algo_template, |
205 | sizeof(core->i2c_algo)); | 204 | sizeof(core->i2c_algo)); |
206 | 205 | ||
207 | if (core->tuner_type != TUNER_ABSENT) | 206 | if (core->board.tuner_type != TUNER_ABSENT) |
208 | core->i2c_adap.class |= I2C_CLASS_TV_ANALOG; | 207 | core->i2c_adap.class |= I2C_CLASS_TV_ANALOG; |
209 | if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) | 208 | if (core->board.mpeg & CX88_MPEG_DVB) |
210 | core->i2c_adap.class |= I2C_CLASS_TV_DIGITAL; | 209 | core->i2c_adap.class |= I2C_CLASS_TV_DIGITAL; |
211 | 210 | ||
212 | core->i2c_adap.dev.parent = &pci->dev; | 211 | core->i2c_adap.dev.parent = &pci->dev; |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index f5d4a565346e..e52de3968c63 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/input.h> | 27 | #include <linux/input.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/moduleparam.h> | ||
31 | 30 | ||
32 | #include "cx88.h" | 31 | #include "cx88.h" |
33 | #include <media/ir-common.h> | 32 | #include <media/ir-common.h> |
@@ -74,7 +73,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) | |||
74 | 73 | ||
75 | /* read gpio value */ | 74 | /* read gpio value */ |
76 | gpio = cx_read(ir->gpio_addr); | 75 | gpio = cx_read(ir->gpio_addr); |
77 | switch (core->board) { | 76 | switch (core->boardnr) { |
78 | case CX88_BOARD_NPGTECH_REALTV_TOP10FM: | 77 | case CX88_BOARD_NPGTECH_REALTV_TOP10FM: |
79 | /* This board apparently uses a combination of 2 GPIO | 78 | /* This board apparently uses a combination of 2 GPIO |
80 | to represent the keys. Additionally, the second GPIO | 79 | to represent the keys. Additionally, the second GPIO |
@@ -113,7 +112,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) | |||
113 | (gpio & ir->mask_keydown) ? " down" : "", | 112 | (gpio & ir->mask_keydown) ? " down" : "", |
114 | (gpio & ir->mask_keyup) ? " up" : ""); | 113 | (gpio & ir->mask_keyup) ? " up" : ""); |
115 | 114 | ||
116 | if (ir->core->board == CX88_BOARD_NORWOOD_MICRO) { | 115 | if (ir->core->boardnr == CX88_BOARD_NORWOOD_MICRO) { |
117 | u32 gpio_key = cx_read(MO_GP0_IO); | 116 | u32 gpio_key = cx_read(MO_GP0_IO); |
118 | 117 | ||
119 | data = (data << 4) | ((gpio_key & 0xf0) >> 4); | 118 | data = (data << 4) | ((gpio_key & 0xf0) >> 4); |
@@ -159,7 +158,7 @@ static void cx88_ir_work(struct work_struct *work) | |||
159 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); | 158 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); |
160 | } | 159 | } |
161 | 160 | ||
162 | static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) | 161 | void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) |
163 | { | 162 | { |
164 | if (ir->polling) { | 163 | if (ir->polling) { |
165 | setup_timer(&ir->timer, ir_timer, (unsigned long)ir); | 164 | setup_timer(&ir->timer, ir_timer, (unsigned long)ir); |
@@ -167,17 +166,17 @@ static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) | |||
167 | schedule_work(&ir->work); | 166 | schedule_work(&ir->work); |
168 | } | 167 | } |
169 | if (ir->sampling) { | 168 | if (ir->sampling) { |
170 | core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */ | 169 | core->pci_irqmask |= PCI_INT_IR_SMPINT; |
171 | cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ | 170 | cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ |
172 | cx_write(MO_DDSCFG_IO, 0x5); /* enable */ | 171 | cx_write(MO_DDSCFG_IO, 0x5); /* enable */ |
173 | } | 172 | } |
174 | } | 173 | } |
175 | 174 | ||
176 | static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) | 175 | void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) |
177 | { | 176 | { |
178 | if (ir->sampling) { | 177 | if (ir->sampling) { |
179 | cx_write(MO_DDSCFG_IO, 0x0); | 178 | cx_write(MO_DDSCFG_IO, 0x0); |
180 | core->pci_irqmask &= ~(1 << 18); | 179 | core->pci_irqmask &= ~PCI_INT_IR_SMPINT; |
181 | } | 180 | } |
182 | 181 | ||
183 | if (ir->polling) { | 182 | if (ir->polling) { |
@@ -204,7 +203,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
204 | ir->input = input_dev; | 203 | ir->input = input_dev; |
205 | 204 | ||
206 | /* detect & configure */ | 205 | /* detect & configure */ |
207 | switch (core->board) { | 206 | switch (core->boardnr) { |
208 | case CX88_BOARD_DNTV_LIVE_DVB_T: | 207 | case CX88_BOARD_DNTV_LIVE_DVB_T: |
209 | case CX88_BOARD_KWORLD_DVB_T: | 208 | case CX88_BOARD_KWORLD_DVB_T: |
210 | case CX88_BOARD_KWORLD_DVB_T_CX22702: | 209 | case CX88_BOARD_KWORLD_DVB_T_CX22702: |
@@ -314,8 +313,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
314 | } | 313 | } |
315 | 314 | ||
316 | /* init input device */ | 315 | /* init input device */ |
317 | snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", | 316 | snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); |
318 | cx88_boards[core->board].name); | ||
319 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); | 317 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); |
320 | 318 | ||
321 | ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); | 319 | ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); |
@@ -406,7 +404,7 @@ void cx88_ir_irq(struct cx88_core *core) | |||
406 | ir_dump_samples(ir->samples, ir->scount); | 404 | ir_dump_samples(ir->samples, ir->scount); |
407 | 405 | ||
408 | /* decode it */ | 406 | /* decode it */ |
409 | switch (core->board) { | 407 | switch (core->boardnr) { |
410 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: | 408 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: |
411 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: | 409 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: |
412 | ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4); | 410 | ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4); |
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index da7a6b591a67..a652f294d23d 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
@@ -23,12 +23,10 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/init.h> | 26 | #include <linux/init.h> |
28 | #include <linux/device.h> | 27 | #include <linux/device.h> |
29 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
30 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
31 | #include <linux/dma-mapping.h> | ||
32 | #include <asm/delay.h> | 30 | #include <asm/delay.h> |
33 | 31 | ||
34 | #include "cx88.h" | 32 | #include "cx88.h" |
@@ -56,9 +54,9 @@ static void request_module_async(struct work_struct *work) | |||
56 | { | 54 | { |
57 | struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk); | 55 | struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk); |
58 | 56 | ||
59 | if (cx88_boards[dev->core->board].mpeg & CX88_MPEG_DVB) | 57 | if (dev->core->board.mpeg & CX88_MPEG_DVB) |
60 | request_module("cx88-dvb"); | 58 | request_module("cx88-dvb"); |
61 | if (cx88_boards[dev->core->board].mpeg & CX88_MPEG_BLACKBIRD) | 59 | if (dev->core->board.mpeg & CX88_MPEG_BLACKBIRD) |
62 | request_module("cx88-blackbird"); | 60 | request_module("cx88-blackbird"); |
63 | } | 61 | } |
64 | 62 | ||
@@ -96,7 +94,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
96 | dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id); | 94 | dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id); |
97 | 95 | ||
98 | if ( (core->active_type_id == CX88_MPEG_DVB) && | 96 | if ( (core->active_type_id == CX88_MPEG_DVB) && |
99 | (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) ) { | 97 | (core->board.mpeg & CX88_MPEG_DVB) ) { |
100 | 98 | ||
101 | dprintk( 1, "cx8802_start_dma doing .dvb\n"); | 99 | dprintk( 1, "cx8802_start_dma doing .dvb\n"); |
102 | /* negedge driven & software reset */ | 100 | /* negedge driven & software reset */ |
@@ -104,7 +102,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
104 | udelay(100); | 102 | udelay(100); |
105 | cx_write(MO_PINMUX_IO, 0x00); | 103 | cx_write(MO_PINMUX_IO, 0x00); |
106 | cx_write(TS_HW_SOP_CNTRL,0x47<<16|188<<4|0x01); | 104 | cx_write(TS_HW_SOP_CNTRL,0x47<<16|188<<4|0x01); |
107 | switch (core->board) { | 105 | switch (core->boardnr) { |
108 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: | 106 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: |
109 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: | 107 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: |
110 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: | 108 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: |
@@ -125,7 +123,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
125 | cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl); | 123 | cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl); |
126 | udelay(100); | 124 | udelay(100); |
127 | } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) && | 125 | } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) && |
128 | (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) ) { | 126 | (core->board.mpeg & CX88_MPEG_BLACKBIRD) ) { |
129 | dprintk( 1, "cx8802_start_dma doing .blackbird\n"); | 127 | dprintk( 1, "cx8802_start_dma doing .blackbird\n"); |
130 | cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */ | 128 | cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */ |
131 | 129 | ||
@@ -139,7 +137,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
139 | udelay(100); | 137 | udelay(100); |
140 | } else { | 138 | } else { |
141 | printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__, | 139 | printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__, |
142 | cx88_boards[core->board].mpeg ); | 140 | core->board.mpeg ); |
143 | return -EINVAL; | 141 | return -EINVAL; |
144 | } | 142 | } |
145 | 143 | ||
@@ -149,7 +147,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
149 | 147 | ||
150 | /* enable irqs */ | 148 | /* enable irqs */ |
151 | dprintk( 1, "setting the interrupt mask\n" ); | 149 | dprintk( 1, "setting the interrupt mask\n" ); |
152 | cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04); | 150 | cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_TSINT); |
153 | cx_set(MO_TS_INTMSK, 0x1f0011); | 151 | cx_set(MO_TS_INTMSK, 0x1f0011); |
154 | 152 | ||
155 | /* start dma */ | 153 | /* start dma */ |
@@ -167,7 +165,7 @@ static int cx8802_stop_dma(struct cx8802_dev *dev) | |||
167 | cx_clear(MO_TS_DMACNTRL, 0x11); | 165 | cx_clear(MO_TS_DMACNTRL, 0x11); |
168 | 166 | ||
169 | /* disable irqs */ | 167 | /* disable irqs */ |
170 | cx_clear(MO_PCI_INTMSK, 0x000004); | 168 | cx_clear(MO_PCI_INTMSK, PCI_INT_TSINT); |
171 | cx_clear(MO_TS_INTMSK, 0x1f0011); | 169 | cx_clear(MO_TS_INTMSK, 0x1f0011); |
172 | 170 | ||
173 | /* Reset the controller */ | 171 | /* Reset the controller */ |
@@ -181,43 +179,43 @@ static int cx8802_restart_queue(struct cx8802_dev *dev, | |||
181 | struct cx88_buffer *buf; | 179 | struct cx88_buffer *buf; |
182 | struct list_head *item; | 180 | struct list_head *item; |
183 | 181 | ||
184 | dprintk( 1, "cx8802_restart_queue\n" ); | 182 | dprintk( 1, "cx8802_restart_queue\n" ); |
185 | if (list_empty(&q->active)) | 183 | if (list_empty(&q->active)) |
186 | { | 184 | { |
187 | struct cx88_buffer *prev; | 185 | struct cx88_buffer *prev; |
188 | prev = NULL; | 186 | prev = NULL; |
189 | 187 | ||
190 | dprintk(1, "cx8802_restart_queue: queue is empty\n" ); | 188 | dprintk(1, "cx8802_restart_queue: queue is empty\n" ); |
191 | 189 | ||
192 | for (;;) { | 190 | for (;;) { |
193 | if (list_empty(&q->queued)) | 191 | if (list_empty(&q->queued)) |
194 | return 0; | 192 | return 0; |
195 | buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); | 193 | buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); |
196 | if (NULL == prev) { | 194 | if (NULL == prev) { |
197 | list_del(&buf->vb.queue); | 195 | list_del(&buf->vb.queue); |
198 | list_add_tail(&buf->vb.queue,&q->active); | 196 | list_add_tail(&buf->vb.queue,&q->active); |
199 | cx8802_start_dma(dev, q, buf); | 197 | cx8802_start_dma(dev, q, buf); |
200 | buf->vb.state = STATE_ACTIVE; | 198 | buf->vb.state = STATE_ACTIVE; |
201 | buf->count = q->count++; | 199 | buf->count = q->count++; |
202 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | 200 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); |
203 | dprintk(1,"[%p/%d] restart_queue - first active\n", | 201 | dprintk(1,"[%p/%d] restart_queue - first active\n", |
204 | buf,buf->vb.i); | 202 | buf,buf->vb.i); |
205 | 203 | ||
206 | } else if (prev->vb.width == buf->vb.width && | 204 | } else if (prev->vb.width == buf->vb.width && |
207 | prev->vb.height == buf->vb.height && | 205 | prev->vb.height == buf->vb.height && |
208 | prev->fmt == buf->fmt) { | 206 | prev->fmt == buf->fmt) { |
209 | list_del(&buf->vb.queue); | 207 | list_del(&buf->vb.queue); |
210 | list_add_tail(&buf->vb.queue,&q->active); | 208 | list_add_tail(&buf->vb.queue,&q->active); |
211 | buf->vb.state = STATE_ACTIVE; | 209 | buf->vb.state = STATE_ACTIVE; |
212 | buf->count = q->count++; | 210 | buf->count = q->count++; |
213 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | 211 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); |
214 | dprintk(1,"[%p/%d] restart_queue - move to active\n", | 212 | dprintk(1,"[%p/%d] restart_queue - move to active\n", |
215 | buf,buf->vb.i); | 213 | buf,buf->vb.i); |
216 | } else { | 214 | } else { |
217 | return 0; | 215 | return 0; |
218 | } | 216 | } |
219 | prev = buf; | 217 | prev = buf; |
220 | } | 218 | } |
221 | return 0; | 219 | return 0; |
222 | } | 220 | } |
223 | 221 | ||
@@ -239,6 +237,7 @@ int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev, | |||
239 | struct cx88_buffer *buf, enum v4l2_field field) | 237 | struct cx88_buffer *buf, enum v4l2_field field) |
240 | { | 238 | { |
241 | int size = dev->ts_packet_size * dev->ts_packet_count; | 239 | int size = dev->ts_packet_size * dev->ts_packet_count; |
240 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
242 | int rc; | 241 | int rc; |
243 | 242 | ||
244 | dprintk(1, "%s: %p\n", __FUNCTION__, buf); | 243 | dprintk(1, "%s: %p\n", __FUNCTION__, buf); |
@@ -254,8 +253,8 @@ int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev, | |||
254 | if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) | 253 | if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) |
255 | goto fail; | 254 | goto fail; |
256 | cx88_risc_databuffer(dev->pci, &buf->risc, | 255 | cx88_risc_databuffer(dev->pci, &buf->risc, |
257 | buf->vb.dma.sglist, | 256 | dma->sglist, |
258 | buf->vb.width, buf->vb.height); | 257 | buf->vb.width, buf->vb.height, 0); |
259 | } | 258 | } |
260 | buf->vb.state = STATE_PREPARED; | 259 | buf->vb.state = STATE_PREPARED; |
261 | return 0; | 260 | return 0; |
@@ -414,7 +413,8 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id) | |||
414 | int loop, handled = 0; | 413 | int loop, handled = 0; |
415 | 414 | ||
416 | for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { | 415 | for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { |
417 | status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04); | 416 | status = cx_read(MO_PCI_INTSTAT) & |
417 | (core->pci_irqmask | PCI_INT_TSINT); | ||
418 | if (0 == status) | 418 | if (0 == status) |
419 | goto out; | 419 | goto out; |
420 | dprintk( 1, "cx8802_irq\n" ); | 420 | dprintk( 1, "cx8802_irq\n" ); |
@@ -425,7 +425,7 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id) | |||
425 | 425 | ||
426 | if (status & core->pci_irqmask) | 426 | if (status & core->pci_irqmask) |
427 | cx88_core_irq(core,status); | 427 | cx88_core_irq(core,status); |
428 | if (status & 0x04) | 428 | if (status & PCI_INT_TSINT) |
429 | cx8802_mpeg_irq(dev); | 429 | cx8802_mpeg_irq(dev); |
430 | }; | 430 | }; |
431 | if (MAX_IRQ_LOOP == loop) { | 431 | if (MAX_IRQ_LOOP == loop) { |
@@ -676,22 +676,24 @@ int cx8802_register_driver(struct cx8802_driver *drv) | |||
676 | struct list_head *list; | 676 | struct list_head *list; |
677 | int err = 0, i = 0; | 677 | int err = 0, i = 0; |
678 | 678 | ||
679 | printk(KERN_INFO "%s() ->registering driver type=%s access=%s\n", __FUNCTION__ , | 679 | printk(KERN_INFO |
680 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", | 680 | "cx88/2: registering cx8802 driver, type: %s access: %s\n", |
681 | drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); | 681 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", |
682 | drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); | ||
682 | 683 | ||
683 | if ((err = cx8802_check_driver(drv)) != 0) { | 684 | if ((err = cx8802_check_driver(drv)) != 0) { |
684 | printk(KERN_INFO "%s() cx8802_driver is invalid\n", __FUNCTION__ ); | 685 | printk(KERN_ERR "cx88/2: cx8802_driver is invalid\n"); |
685 | return err; | 686 | return err; |
686 | } | 687 | } |
687 | 688 | ||
688 | list_for_each(list,&cx8802_devlist) { | 689 | list_for_each(list,&cx8802_devlist) { |
689 | h = list_entry(list, struct cx8802_dev, devlist); | 690 | h = list_entry(list, struct cx8802_dev, devlist); |
690 | 691 | ||
691 | printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n", | 692 | printk(KERN_INFO |
692 | h->core->name,h->pci->subsystem_vendor, | 693 | "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", |
693 | h->pci->subsystem_device,cx88_boards[h->core->board].name, | 694 | h->core->name, h->pci->subsystem_vendor, |
694 | h->core->board); | 695 | h->pci->subsystem_device, h->core->board.name, |
696 | h->core->boardnr); | ||
695 | 697 | ||
696 | /* Bring up a new struct for each driver instance */ | 698 | /* Bring up a new struct for each driver instance */ |
697 | driver = kzalloc(sizeof(*drv),GFP_KERNEL); | 699 | driver = kzalloc(sizeof(*drv),GFP_KERNEL); |
@@ -713,7 +715,9 @@ int cx8802_register_driver(struct cx8802_driver *drv) | |||
713 | list_add_tail(&driver->devlist,&h->drvlist.devlist); | 715 | list_add_tail(&driver->devlist,&h->drvlist.devlist); |
714 | mutex_unlock(&drv->core->lock); | 716 | mutex_unlock(&drv->core->lock); |
715 | } else { | 717 | } else { |
716 | printk(KERN_ERR "%s() ->probe failed err = %d\n", __FUNCTION__, err); | 718 | printk(KERN_ERR |
719 | "%s/2: cx8802 probe failed, err = %d\n", | ||
720 | h->core->name, err); | ||
717 | } | 721 | } |
718 | 722 | ||
719 | } | 723 | } |
@@ -733,17 +737,20 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) | |||
733 | struct list_head *list2, *q; | 737 | struct list_head *list2, *q; |
734 | int err = 0, i = 0; | 738 | int err = 0, i = 0; |
735 | 739 | ||
736 | printk(KERN_INFO "%s() ->unregistering driver type=%s\n", __FUNCTION__ , | 740 | printk(KERN_INFO |
737 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird"); | 741 | "cx88/2: unregistering cx8802 driver, type: %s access: %s\n", |
742 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", | ||
743 | drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); | ||
738 | 744 | ||
739 | list_for_each(list,&cx8802_devlist) { | 745 | list_for_each(list,&cx8802_devlist) { |
740 | i++; | 746 | i++; |
741 | h = list_entry(list, struct cx8802_dev, devlist); | 747 | h = list_entry(list, struct cx8802_dev, devlist); |
742 | 748 | ||
743 | printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n", | 749 | printk(KERN_INFO |
744 | h->core->name,h->pci->subsystem_vendor, | 750 | "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", |
745 | h->pci->subsystem_device,cx88_boards[h->core->board].name, | 751 | h->core->name, h->pci->subsystem_vendor, |
746 | h->core->board); | 752 | h->pci->subsystem_device, h->core->board.name, |
753 | h->core->boardnr); | ||
747 | 754 | ||
748 | list_for_each_safe(list2, q, &h->drvlist.devlist) { | 755 | list_for_each_safe(list2, q, &h->drvlist.devlist) { |
749 | d = list_entry(list2, struct cx8802_driver, devlist); | 756 | d = list_entry(list2, struct cx8802_driver, devlist); |
@@ -758,7 +765,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) | |||
758 | list_del(list2); | 765 | list_del(list2); |
759 | mutex_unlock(&drv->core->lock); | 766 | mutex_unlock(&drv->core->lock); |
760 | } else | 767 | } else |
761 | printk(KERN_ERR "%s() ->remove failed err = %d\n", __FUNCTION__, err); | 768 | printk(KERN_ERR "%s/2: cx8802 driver remove " |
769 | "failed (%d)\n", h->core->name, err); | ||
762 | 770 | ||
763 | } | 771 | } |
764 | 772 | ||
@@ -783,7 +791,7 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, | |||
783 | printk("%s/2: cx2388x 8802 Driver Manager\n", core->name); | 791 | printk("%s/2: cx2388x 8802 Driver Manager\n", core->name); |
784 | 792 | ||
785 | err = -ENODEV; | 793 | err = -ENODEV; |
786 | if (!cx88_boards[core->board].mpeg) | 794 | if (!core->board.mpeg) |
787 | goto fail_core; | 795 | goto fail_core; |
788 | 796 | ||
789 | err = -ENOMEM; | 797 | err = -ENOMEM; |
@@ -866,7 +874,7 @@ static struct pci_driver cx8802_pci_driver = { | |||
866 | 874 | ||
867 | static int cx8802_init(void) | 875 | static int cx8802_init(void) |
868 | { | 876 | { |
869 | printk(KERN_INFO "cx2388x cx88-mpeg Driver Manager version %d.%d.%d loaded\n", | 877 | printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %d.%d.%d loaded\n", |
870 | (CX88_VERSION_CODE >> 16) & 0xff, | 878 | (CX88_VERSION_CODE >> 16) & 0xff, |
871 | (CX88_VERSION_CODE >> 8) & 0xff, | 879 | (CX88_VERSION_CODE >> 8) & 0xff, |
872 | CX88_VERSION_CODE & 0xff); | 880 | CX88_VERSION_CODE & 0xff); |
diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h index d3bf5b17b1d4..2ec52d1cdea0 100644 --- a/drivers/media/video/cx88/cx88-reg.h +++ b/drivers/media/video/cx88/cx88-reg.h | |||
@@ -582,6 +582,28 @@ | |||
582 | /* ---------------------------------------------------------------------- */ | 582 | /* ---------------------------------------------------------------------- */ |
583 | /* various constants */ | 583 | /* various constants */ |
584 | 584 | ||
585 | // DMA | ||
586 | /* Interrupt mask/status */ | ||
587 | #define PCI_INT_VIDINT (1 << 0) | ||
588 | #define PCI_INT_AUDINT (1 << 1) | ||
589 | #define PCI_INT_TSINT (1 << 2) | ||
590 | #define PCI_INT_VIPINT (1 << 3) | ||
591 | #define PCI_INT_HSTINT (1 << 4) | ||
592 | #define PCI_INT_TM1INT (1 << 5) | ||
593 | #define PCI_INT_SRCDMAINT (1 << 6) | ||
594 | #define PCI_INT_DSTDMAINT (1 << 7) | ||
595 | #define PCI_INT_RISC_RD_BERRINT (1 << 10) | ||
596 | #define PCI_INT_RISC_WR_BERRINT (1 << 11) | ||
597 | #define PCI_INT_BRDG_BERRINT (1 << 12) | ||
598 | #define PCI_INT_SRC_DMA_BERRINT (1 << 13) | ||
599 | #define PCI_INT_DST_DMA_BERRINT (1 << 14) | ||
600 | #define PCI_INT_IPB_DMA_BERRINT (1 << 15) | ||
601 | #define PCI_INT_I2CDONE (1 << 16) | ||
602 | #define PCI_INT_I2CRACK (1 << 17) | ||
603 | #define PCI_INT_IR_SMPINT (1 << 18) | ||
604 | #define PCI_INT_GPIO_INT0 (1 << 19) | ||
605 | #define PCI_INT_GPIO_INT1 (1 << 20) | ||
606 | |||
585 | #define SEL_BTSC 0x01 | 607 | #define SEL_BTSC 0x01 |
586 | #define SEL_EIAJ 0x02 | 608 | #define SEL_EIAJ 0x02 |
587 | #define SEL_A2 0x04 | 609 | #define SEL_A2 0x04 |
@@ -590,6 +612,19 @@ | |||
590 | #define SEL_FMRADIO 0x20 | 612 | #define SEL_FMRADIO 0x20 |
591 | 613 | ||
592 | // AUD_CTL | 614 | // AUD_CTL |
615 | #define AUD_INT_DN_RISCI1 (1 << 0) | ||
616 | #define AUD_INT_UP_RISCI1 (1 << 1) | ||
617 | #define AUD_INT_RDS_DN_RISCI1 (1 << 2) | ||
618 | #define AUD_INT_DN_RISCI2 (1 << 4) /* yes, 3 is skipped */ | ||
619 | #define AUD_INT_UP_RISCI2 (1 << 5) | ||
620 | #define AUD_INT_RDS_DN_RISCI2 (1 << 6) | ||
621 | #define AUD_INT_DN_SYNC (1 << 12) | ||
622 | #define AUD_INT_UP_SYNC (1 << 13) | ||
623 | #define AUD_INT_RDS_DN_SYNC (1 << 14) | ||
624 | #define AUD_INT_OPC_ERR (1 << 16) | ||
625 | #define AUD_INT_BER_IRQ (1 << 20) | ||
626 | #define AUD_INT_MCHG_IRQ (1 << 21) | ||
627 | |||
593 | #define EN_BTSC_FORCE_MONO 0 | 628 | #define EN_BTSC_FORCE_MONO 0 |
594 | #define EN_BTSC_FORCE_STEREO 1 | 629 | #define EN_BTSC_FORCE_STEREO 1 |
595 | #define EN_BTSC_FORCE_SAP 2 | 630 | #define EN_BTSC_FORCE_SAP 2 |
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 1cc2d286a1cb..76e5c78d8ae4 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c | |||
@@ -36,7 +36,6 @@ | |||
36 | */ | 36 | */ |
37 | 37 | ||
38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
39 | #include <linux/moduleparam.h> | ||
40 | #include <linux/errno.h> | 39 | #include <linux/errno.h> |
41 | #include <linux/freezer.h> | 40 | #include <linux/freezer.h> |
42 | #include <linux/kernel.h> | 41 | #include <linux/kernel.h> |
@@ -62,6 +61,10 @@ static unsigned int always_analog = 0; | |||
62 | module_param(always_analog,int,0644); | 61 | module_param(always_analog,int,0644); |
63 | MODULE_PARM_DESC(always_analog,"force analog audio out"); | 62 | MODULE_PARM_DESC(always_analog,"force analog audio out"); |
64 | 63 | ||
64 | static unsigned int radio_deemphasis = 0; | ||
65 | module_param(radio_deemphasis,int,0644); | ||
66 | MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, " | ||
67 | "0=None, 1=50us (elsewhere), 2=75us (USA)"); | ||
65 | 68 | ||
66 | #define dprintk(fmt, arg...) if (audio_debug) \ | 69 | #define dprintk(fmt, arg...) if (audio_debug) \ |
67 | printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) | 70 | printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) |
@@ -140,7 +143,7 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) | |||
140 | cx_write(AUD_RATE_THRES_DMD, 0x000000C0); | 143 | cx_write(AUD_RATE_THRES_DMD, 0x000000C0); |
141 | cx88_start_audio_dma(core); | 144 | cx88_start_audio_dma(core); |
142 | 145 | ||
143 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { | 146 | if (core->board.mpeg & CX88_MPEG_BLACKBIRD) { |
144 | cx_write(AUD_I2SINPUTCNTL, 4); | 147 | cx_write(AUD_I2SINPUTCNTL, 4); |
145 | cx_write(AUD_BAUDRATE, 1); | 148 | cx_write(AUD_BAUDRATE, 1); |
146 | /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ | 149 | /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ |
@@ -149,7 +152,7 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) | |||
149 | cx_write(AUD_I2SCNTL, 0); | 152 | cx_write(AUD_I2SCNTL, 0); |
150 | /* cx_write(AUD_APB_IN_RATE_ADJ, 0); */ | 153 | /* cx_write(AUD_APB_IN_RATE_ADJ, 0); */ |
151 | } | 154 | } |
152 | if ((always_analog) || (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))) { | 155 | if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) { |
153 | ctl |= EN_DAC_ENABLE; | 156 | ctl |= EN_DAC_ENABLE; |
154 | cx_write(AUD_CTL, ctl); | 157 | cx_write(AUD_CTL, ctl); |
155 | } | 158 | } |
@@ -678,6 +681,10 @@ static void set_audio_standard_FM(struct cx88_core *core, | |||
678 | }; | 681 | }; |
679 | 682 | ||
680 | /* It is enough to leave default values? */ | 683 | /* It is enough to leave default values? */ |
684 | /* No, it's not! The deemphasis registers are reset to the 75us | ||
685 | * values by default. Analyzing the spectrum of the decoded audio | ||
686 | * reveals that "no deemphasis" is the same as 75 us, while the 50 us | ||
687 | * setting results in less deemphasis. */ | ||
681 | static const struct rlist fm_no_deemph[] = { | 688 | static const struct rlist fm_no_deemph[] = { |
682 | 689 | ||
683 | {AUD_POLYPH80SCALEFAC, 0x0003}, | 690 | {AUD_POLYPH80SCALEFAC, 0x0003}, |
@@ -688,6 +695,7 @@ static void set_audio_standard_FM(struct cx88_core *core, | |||
688 | set_audio_start(core, SEL_FMRADIO); | 695 | set_audio_start(core, SEL_FMRADIO); |
689 | 696 | ||
690 | switch (deemph) { | 697 | switch (deemph) { |
698 | default: | ||
691 | case FM_NO_DEEMPH: | 699 | case FM_NO_DEEMPH: |
692 | set_audio_registers(core, fm_no_deemph); | 700 | set_audio_registers(core, fm_no_deemph); |
693 | break; | 701 | break; |
@@ -757,7 +765,7 @@ void cx88_set_tvaudio(struct cx88_core *core) | |||
757 | set_audio_standard_EIAJ(core); | 765 | set_audio_standard_EIAJ(core); |
758 | break; | 766 | break; |
759 | case WW_FM: | 767 | case WW_FM: |
760 | set_audio_standard_FM(core, FM_NO_DEEMPH); | 768 | set_audio_standard_FM(core, radio_deemphasis); |
761 | break; | 769 | break; |
762 | case WW_NONE: | 770 | case WW_NONE: |
763 | default: | 771 | default: |
@@ -790,9 +798,9 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) | |||
790 | core->astat = reg; | 798 | core->astat = reg; |
791 | 799 | ||
792 | /* TODO | 800 | /* TODO |
793 | Reading from AUD_STATUS is not enough | 801 | Reading from AUD_STATUS is not enough |
794 | for auto-detecting sap/dual-fm/nicam. | 802 | for auto-detecting sap/dual-fm/nicam. |
795 | Add some code here later. | 803 | Add some code here later. |
796 | */ | 804 | */ |
797 | 805 | ||
798 | return; | 806 | return; |
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c index 86c1cf8334bc..babb08556406 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/video/cx88/cx88-vbi.c | |||
@@ -2,7 +2,6 @@ | |||
2 | */ | 2 | */ |
3 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
5 | #include <linux/moduleparam.h> | ||
6 | #include <linux/init.h> | 5 | #include <linux/init.h> |
7 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
8 | 7 | ||
@@ -67,7 +66,7 @@ static int cx8800_start_vbi_dma(struct cx8800_dev *dev, | |||
67 | q->count = 1; | 66 | q->count = 1; |
68 | 67 | ||
69 | /* enable irqs */ | 68 | /* enable irqs */ |
70 | cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01); | 69 | cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT); |
71 | cx_set(MO_VID_INTMSK, 0x0f0088); | 70 | cx_set(MO_VID_INTMSK, 0x0f0088); |
72 | 71 | ||
73 | /* enable capture */ | 72 | /* enable capture */ |
@@ -91,7 +90,7 @@ int cx8800_stop_vbi_dma(struct cx8800_dev *dev) | |||
91 | cx_clear(VID_CAPTURE_CONTROL,0x18); | 90 | cx_clear(VID_CAPTURE_CONTROL,0x18); |
92 | 91 | ||
93 | /* disable irqs */ | 92 | /* disable irqs */ |
94 | cx_clear(MO_PCI_INTMSK, 0x000001); | 93 | cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT); |
95 | cx_clear(MO_VID_INTMSK, 0x0f0088); | 94 | cx_clear(MO_VID_INTMSK, 0x0f0088); |
96 | return 0; | 95 | return 0; |
97 | } | 96 | } |
@@ -100,7 +99,6 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev, | |||
100 | struct cx88_dmaqueue *q) | 99 | struct cx88_dmaqueue *q) |
101 | { | 100 | { |
102 | struct cx88_buffer *buf; | 101 | struct cx88_buffer *buf; |
103 | struct list_head *item; | ||
104 | 102 | ||
105 | if (list_empty(&q->active)) | 103 | if (list_empty(&q->active)) |
106 | return 0; | 104 | return 0; |
@@ -109,10 +107,8 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev, | |||
109 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", | 107 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", |
110 | buf, buf->vb.i); | 108 | buf, buf->vb.i); |
111 | cx8800_start_vbi_dma(dev, q, buf); | 109 | cx8800_start_vbi_dma(dev, q, buf); |
112 | list_for_each(item,&q->active) { | 110 | list_for_each_entry(buf, &q->active, vb.queue) |
113 | buf = list_entry(item, struct cx88_buffer, vb.queue); | ||
114 | buf->count = q->count++; | 111 | buf->count = q->count++; |
115 | } | ||
116 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | 112 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); |
117 | return 0; | 113 | return 0; |
118 | } | 114 | } |
@@ -173,6 +169,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
173 | return -EINVAL; | 169 | return -EINVAL; |
174 | 170 | ||
175 | if (STATE_NEEDS_INIT == buf->vb.state) { | 171 | if (STATE_NEEDS_INIT == buf->vb.state) { |
172 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
176 | buf->vb.width = VBI_LINE_LENGTH; | 173 | buf->vb.width = VBI_LINE_LENGTH; |
177 | buf->vb.height = VBI_LINE_COUNT; | 174 | buf->vb.height = VBI_LINE_COUNT; |
178 | buf->vb.size = size; | 175 | buf->vb.size = size; |
@@ -181,7 +178,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
181 | if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) | 178 | if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) |
182 | goto fail; | 179 | goto fail; |
183 | cx88_risc_buffer(dev->pci, &buf->risc, | 180 | cx88_risc_buffer(dev->pci, &buf->risc, |
184 | buf->vb.dma.sglist, | 181 | dma->sglist, |
185 | 0, buf->vb.width * buf->vb.height, | 182 | 0, buf->vb.width * buf->vb.height, |
186 | buf->vb.width, 0, | 183 | buf->vb.width, 0, |
187 | buf->vb.height); | 184 | buf->vb.height); |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 06b233a7b20b..231ae6c4dd22 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/kmod.h> | 31 | #include <linux/kmod.h> |
33 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
34 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
@@ -36,7 +35,6 @@ | |||
36 | #include <linux/dma-mapping.h> | 35 | #include <linux/dma-mapping.h> |
37 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
38 | #include <linux/kthread.h> | 37 | #include <linux/kthread.h> |
39 | #include <linux/dma-mapping.h> | ||
40 | #include <asm/div64.h> | 38 | #include <asm/div64.h> |
41 | 39 | ||
42 | #include "cx88.h" | 40 | #include "cx88.h" |
@@ -369,17 +367,17 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) | |||
369 | /* struct cx88_core *core = dev->core; */ | 367 | /* struct cx88_core *core = dev->core; */ |
370 | 368 | ||
371 | dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n", | 369 | dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n", |
372 | input, INPUT(input)->vmux, | 370 | input, INPUT(input).vmux, |
373 | INPUT(input)->gpio0,INPUT(input)->gpio1, | 371 | INPUT(input).gpio0,INPUT(input).gpio1, |
374 | INPUT(input)->gpio2,INPUT(input)->gpio3); | 372 | INPUT(input).gpio2,INPUT(input).gpio3); |
375 | core->input = input; | 373 | core->input = input; |
376 | cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input)->vmux << 14); | 374 | cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input).vmux << 14); |
377 | cx_write(MO_GP3_IO, INPUT(input)->gpio3); | 375 | cx_write(MO_GP3_IO, INPUT(input).gpio3); |
378 | cx_write(MO_GP0_IO, INPUT(input)->gpio0); | 376 | cx_write(MO_GP0_IO, INPUT(input).gpio0); |
379 | cx_write(MO_GP1_IO, INPUT(input)->gpio1); | 377 | cx_write(MO_GP1_IO, INPUT(input).gpio1); |
380 | cx_write(MO_GP2_IO, INPUT(input)->gpio2); | 378 | cx_write(MO_GP2_IO, INPUT(input).gpio2); |
381 | 379 | ||
382 | switch (INPUT(input)->type) { | 380 | switch (INPUT(input).type) { |
383 | case CX88_VMUX_SVIDEO: | 381 | case CX88_VMUX_SVIDEO: |
384 | cx_set(MO_AFECFG_IO, 0x00000001); | 382 | cx_set(MO_AFECFG_IO, 0x00000001); |
385 | cx_set(MO_INPUT_FORMAT, 0x00010010); | 383 | cx_set(MO_INPUT_FORMAT, 0x00010010); |
@@ -394,9 +392,9 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) | |||
394 | break; | 392 | break; |
395 | } | 393 | } |
396 | 394 | ||
397 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { | 395 | if (core->board.mpeg & CX88_MPEG_BLACKBIRD) { |
398 | /* sets sound input from external adc */ | 396 | /* sets sound input from external adc */ |
399 | if (INPUT(input)->extadc) | 397 | if (INPUT(input).extadc) |
400 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); | 398 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); |
401 | else | 399 | else |
402 | cx_clear(AUD_CTL, EN_I2SIN_ENABLE); | 400 | cx_clear(AUD_CTL, EN_I2SIN_ENABLE); |
@@ -424,7 +422,7 @@ static int start_video_dma(struct cx8800_dev *dev, | |||
424 | q->count = 1; | 422 | q->count = 1; |
425 | 423 | ||
426 | /* enable irqs */ | 424 | /* enable irqs */ |
427 | cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01); | 425 | cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT); |
428 | 426 | ||
429 | /* Enables corresponding bits at PCI_INT_STAT: | 427 | /* Enables corresponding bits at PCI_INT_STAT: |
430 | bits 0 to 4: video, audio, transport stream, VIP, Host | 428 | bits 0 to 4: video, audio, transport stream, VIP, Host |
@@ -457,7 +455,7 @@ static int stop_video_dma(struct cx8800_dev *dev) | |||
457 | cx_clear(VID_CAPTURE_CONTROL,0x06); | 455 | cx_clear(VID_CAPTURE_CONTROL,0x06); |
458 | 456 | ||
459 | /* disable irqs */ | 457 | /* disable irqs */ |
460 | cx_clear(MO_PCI_INTMSK, 0x000001); | 458 | cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT); |
461 | cx_clear(MO_VID_INTMSK, 0x0f0011); | 459 | cx_clear(MO_VID_INTMSK, 0x0f0011); |
462 | return 0; | 460 | return 0; |
463 | } | 461 | } |
@@ -468,17 +466,14 @@ static int restart_video_queue(struct cx8800_dev *dev, | |||
468 | { | 466 | { |
469 | struct cx88_core *core = dev->core; | 467 | struct cx88_core *core = dev->core; |
470 | struct cx88_buffer *buf, *prev; | 468 | struct cx88_buffer *buf, *prev; |
471 | struct list_head *item; | ||
472 | 469 | ||
473 | if (!list_empty(&q->active)) { | 470 | if (!list_empty(&q->active)) { |
474 | buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); | 471 | buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); |
475 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", | 472 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", |
476 | buf, buf->vb.i); | 473 | buf, buf->vb.i); |
477 | start_video_dma(dev, q, buf); | 474 | start_video_dma(dev, q, buf); |
478 | list_for_each(item,&q->active) { | 475 | list_for_each_entry(buf, &q->active, vb.queue) |
479 | buf = list_entry(item, struct cx88_buffer, vb.queue); | 476 | buf->count = q->count++; |
480 | buf->count = q->count++; | ||
481 | } | ||
482 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | 477 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); |
483 | return 0; | 478 | return 0; |
484 | } | 479 | } |
@@ -536,6 +531,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
536 | struct cx8800_dev *dev = fh->dev; | 531 | struct cx8800_dev *dev = fh->dev; |
537 | struct cx88_core *core = dev->core; | 532 | struct cx88_core *core = dev->core; |
538 | struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); | 533 | struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); |
534 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
539 | int rc, init_buffer = 0; | 535 | int rc, init_buffer = 0; |
540 | 536 | ||
541 | BUG_ON(NULL == fh->fmt); | 537 | BUG_ON(NULL == fh->fmt); |
@@ -568,30 +564,30 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
568 | switch (buf->vb.field) { | 564 | switch (buf->vb.field) { |
569 | case V4L2_FIELD_TOP: | 565 | case V4L2_FIELD_TOP: |
570 | cx88_risc_buffer(dev->pci, &buf->risc, | 566 | cx88_risc_buffer(dev->pci, &buf->risc, |
571 | buf->vb.dma.sglist, 0, UNSET, | 567 | dma->sglist, 0, UNSET, |
572 | buf->bpl, 0, buf->vb.height); | 568 | buf->bpl, 0, buf->vb.height); |
573 | break; | 569 | break; |
574 | case V4L2_FIELD_BOTTOM: | 570 | case V4L2_FIELD_BOTTOM: |
575 | cx88_risc_buffer(dev->pci, &buf->risc, | 571 | cx88_risc_buffer(dev->pci, &buf->risc, |
576 | buf->vb.dma.sglist, UNSET, 0, | 572 | dma->sglist, UNSET, 0, |
577 | buf->bpl, 0, buf->vb.height); | 573 | buf->bpl, 0, buf->vb.height); |
578 | break; | 574 | break; |
579 | case V4L2_FIELD_INTERLACED: | 575 | case V4L2_FIELD_INTERLACED: |
580 | cx88_risc_buffer(dev->pci, &buf->risc, | 576 | cx88_risc_buffer(dev->pci, &buf->risc, |
581 | buf->vb.dma.sglist, 0, buf->bpl, | 577 | dma->sglist, 0, buf->bpl, |
582 | buf->bpl, buf->bpl, | 578 | buf->bpl, buf->bpl, |
583 | buf->vb.height >> 1); | 579 | buf->vb.height >> 1); |
584 | break; | 580 | break; |
585 | case V4L2_FIELD_SEQ_TB: | 581 | case V4L2_FIELD_SEQ_TB: |
586 | cx88_risc_buffer(dev->pci, &buf->risc, | 582 | cx88_risc_buffer(dev->pci, &buf->risc, |
587 | buf->vb.dma.sglist, | 583 | dma->sglist, |
588 | 0, buf->bpl * (buf->vb.height >> 1), | 584 | 0, buf->bpl * (buf->vb.height >> 1), |
589 | buf->bpl, 0, | 585 | buf->bpl, 0, |
590 | buf->vb.height >> 1); | 586 | buf->vb.height >> 1); |
591 | break; | 587 | break; |
592 | case V4L2_FIELD_SEQ_BT: | 588 | case V4L2_FIELD_SEQ_BT: |
593 | cx88_risc_buffer(dev->pci, &buf->risc, | 589 | cx88_risc_buffer(dev->pci, &buf->risc, |
594 | buf->vb.dma.sglist, | 590 | dma->sglist, |
595 | buf->bpl * (buf->vb.height >> 1), 0, | 591 | buf->bpl * (buf->vb.height >> 1), 0, |
596 | buf->bpl, 0, | 592 | buf->bpl, 0, |
597 | buf->vb.height >> 1); | 593 | buf->vb.height >> 1); |
@@ -714,12 +710,10 @@ static int video_open(struct inode *inode, struct file *file) | |||
714 | struct cx8800_dev *h,*dev = NULL; | 710 | struct cx8800_dev *h,*dev = NULL; |
715 | struct cx88_core *core; | 711 | struct cx88_core *core; |
716 | struct cx8800_fh *fh; | 712 | struct cx8800_fh *fh; |
717 | struct list_head *list; | ||
718 | enum v4l2_buf_type type = 0; | 713 | enum v4l2_buf_type type = 0; |
719 | int radio = 0; | 714 | int radio = 0; |
720 | 715 | ||
721 | list_for_each(list,&cx8800_devlist) { | 716 | list_for_each_entry(h, &cx8800_devlist, devlist) { |
722 | h = list_entry(list, struct cx8800_dev, devlist); | ||
723 | if (h->video_dev->minor == minor) { | 717 | if (h->video_dev->minor == minor) { |
724 | dev = h; | 718 | dev = h; |
725 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 719 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
@@ -754,13 +748,13 @@ static int video_open(struct inode *inode, struct file *file) | |||
754 | fh->height = 240; | 748 | fh->height = 240; |
755 | fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); | 749 | fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); |
756 | 750 | ||
757 | videobuf_queue_init(&fh->vidq, &cx8800_video_qops, | 751 | videobuf_queue_pci_init(&fh->vidq, &cx8800_video_qops, |
758 | dev->pci, &dev->slock, | 752 | dev->pci, &dev->slock, |
759 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 753 | V4L2_BUF_TYPE_VIDEO_CAPTURE, |
760 | V4L2_FIELD_INTERLACED, | 754 | V4L2_FIELD_INTERLACED, |
761 | sizeof(struct cx88_buffer), | 755 | sizeof(struct cx88_buffer), |
762 | fh); | 756 | fh); |
763 | videobuf_queue_init(&fh->vbiq, &cx8800_vbi_qops, | 757 | videobuf_queue_pci_init(&fh->vbiq, &cx8800_vbi_qops, |
764 | dev->pci, &dev->slock, | 758 | dev->pci, &dev->slock, |
765 | V4L2_BUF_TYPE_VBI_CAPTURE, | 759 | V4L2_BUF_TYPE_VBI_CAPTURE, |
766 | V4L2_FIELD_SEQ_TB, | 760 | V4L2_FIELD_SEQ_TB, |
@@ -768,12 +762,11 @@ static int video_open(struct inode *inode, struct file *file) | |||
768 | fh); | 762 | fh); |
769 | 763 | ||
770 | if (fh->radio) { | 764 | if (fh->radio) { |
771 | int board = core->board; | ||
772 | dprintk(1,"video_open: setting radio device\n"); | 765 | dprintk(1,"video_open: setting radio device\n"); |
773 | cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3); | 766 | cx_write(MO_GP3_IO, core->board.radio.gpio3); |
774 | cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0); | 767 | cx_write(MO_GP0_IO, core->board.radio.gpio0); |
775 | cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1); | 768 | cx_write(MO_GP1_IO, core->board.radio.gpio1); |
776 | cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2); | 769 | cx_write(MO_GP2_IO, core->board.radio.gpio2); |
777 | core->tvaudio = WW_FM; | 770 | core->tvaudio = WW_FM; |
778 | cx88_set_tvaudio(core); | 771 | cx88_set_tvaudio(core); |
779 | cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); | 772 | cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); |
@@ -1079,8 +1072,7 @@ static int vidioc_querycap (struct file *file, void *priv, | |||
1079 | struct cx88_core *core = dev->core; | 1072 | struct cx88_core *core = dev->core; |
1080 | 1073 | ||
1081 | strcpy(cap->driver, "cx8800"); | 1074 | strcpy(cap->driver, "cx8800"); |
1082 | strlcpy(cap->card, cx88_boards[core->board].name, | 1075 | strlcpy(cap->card, core->board.name, sizeof(cap->card)); |
1083 | sizeof(cap->card)); | ||
1084 | sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); | 1076 | sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); |
1085 | cap->version = CX88_VERSION_CODE; | 1077 | cap->version = CX88_VERSION_CODE; |
1086 | cap->capabilities = | 1078 | cap->capabilities = |
@@ -1088,7 +1080,7 @@ static int vidioc_querycap (struct file *file, void *priv, | |||
1088 | V4L2_CAP_READWRITE | | 1080 | V4L2_CAP_READWRITE | |
1089 | V4L2_CAP_STREAMING | | 1081 | V4L2_CAP_STREAMING | |
1090 | V4L2_CAP_VBI_CAPTURE; | 1082 | V4L2_CAP_VBI_CAPTURE; |
1091 | if (UNSET != core->tuner_type) | 1083 | if (UNSET != core->board.tuner_type) |
1092 | cap->capabilities |= V4L2_CAP_TUNER; | 1084 | cap->capabilities |= V4L2_CAP_TUNER; |
1093 | return 0; | 1085 | return 0; |
1094 | } | 1086 | } |
@@ -1108,28 +1100,9 @@ static int vidioc_enum_fmt_cap (struct file *file, void *priv, | |||
1108 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 1100 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1109 | static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) | 1101 | static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) |
1110 | { | 1102 | { |
1111 | struct cx8800_fh *fh = priv; | 1103 | struct cx8800_fh *fh = priv; |
1112 | struct videobuf_queue *q; | ||
1113 | struct v4l2_requestbuffers req; | ||
1114 | unsigned int i; | ||
1115 | int err; | ||
1116 | 1104 | ||
1117 | q = get_queue(fh); | 1105 | return videobuf_cgmbuf (get_queue(fh), mbuf, 8); |
1118 | memset(&req,0,sizeof(req)); | ||
1119 | req.type = q->type; | ||
1120 | req.count = 8; | ||
1121 | req.memory = V4L2_MEMORY_MMAP; | ||
1122 | err = videobuf_reqbufs(q,&req); | ||
1123 | if (err < 0) | ||
1124 | return err; | ||
1125 | |||
1126 | mbuf->frames = req.count; | ||
1127 | mbuf->size = 0; | ||
1128 | for (i = 0; i < mbuf->frames; i++) { | ||
1129 | mbuf->offsets[i] = q->bufs[i]->boff; | ||
1130 | mbuf->size += q->bufs[i]->bsize; | ||
1131 | } | ||
1132 | return 0; | ||
1133 | } | 1106 | } |
1134 | #endif | 1107 | #endif |
1135 | 1108 | ||
@@ -1222,14 +1195,14 @@ int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i) | |||
1222 | n = i->index; | 1195 | n = i->index; |
1223 | if (n >= 4) | 1196 | if (n >= 4) |
1224 | return -EINVAL; | 1197 | return -EINVAL; |
1225 | if (0 == INPUT(n)->type) | 1198 | if (0 == INPUT(n).type) |
1226 | return -EINVAL; | 1199 | return -EINVAL; |
1227 | memset(i,0,sizeof(*i)); | 1200 | memset(i,0,sizeof(*i)); |
1228 | i->index = n; | 1201 | i->index = n; |
1229 | i->type = V4L2_INPUT_TYPE_CAMERA; | 1202 | i->type = V4L2_INPUT_TYPE_CAMERA; |
1230 | strcpy(i->name,iname[INPUT(n)->type]); | 1203 | strcpy(i->name,iname[INPUT(n).type]); |
1231 | if ((CX88_VMUX_TELEVISION == INPUT(n)->type) || | 1204 | if ((CX88_VMUX_TELEVISION == INPUT(n).type) || |
1232 | (CX88_VMUX_CABLE == INPUT(n)->type)) | 1205 | (CX88_VMUX_CABLE == INPUT(n).type)) |
1233 | i->type = V4L2_INPUT_TYPE_TUNER; | 1206 | i->type = V4L2_INPUT_TYPE_TUNER; |
1234 | i->std = CX88_NORMS; | 1207 | i->std = CX88_NORMS; |
1235 | return 0; | 1208 | return 0; |
@@ -1298,7 +1271,7 @@ static int vidioc_g_tuner (struct file *file, void *priv, | |||
1298 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 1271 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; |
1299 | u32 reg; | 1272 | u32 reg; |
1300 | 1273 | ||
1301 | if (unlikely(UNSET == core->tuner_type)) | 1274 | if (unlikely(UNSET == core->board.tuner_type)) |
1302 | return -EINVAL; | 1275 | return -EINVAL; |
1303 | if (0 != t->index) | 1276 | if (0 != t->index) |
1304 | return -EINVAL; | 1277 | return -EINVAL; |
@@ -1319,7 +1292,7 @@ static int vidioc_s_tuner (struct file *file, void *priv, | |||
1319 | { | 1292 | { |
1320 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 1293 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; |
1321 | 1294 | ||
1322 | if (UNSET == core->tuner_type) | 1295 | if (UNSET == core->board.tuner_type) |
1323 | return -EINVAL; | 1296 | return -EINVAL; |
1324 | if (0 != t->index) | 1297 | if (0 != t->index) |
1325 | return -EINVAL; | 1298 | return -EINVAL; |
@@ -1334,7 +1307,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, | |||
1334 | struct cx8800_fh *fh = priv; | 1307 | struct cx8800_fh *fh = priv; |
1335 | struct cx88_core *core = fh->dev->core; | 1308 | struct cx88_core *core = fh->dev->core; |
1336 | 1309 | ||
1337 | if (unlikely(UNSET == core->tuner_type)) | 1310 | if (unlikely(UNSET == core->board.tuner_type)) |
1338 | return -EINVAL; | 1311 | return -EINVAL; |
1339 | 1312 | ||
1340 | /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */ | 1313 | /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */ |
@@ -1349,7 +1322,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, | |||
1349 | int cx88_set_freq (struct cx88_core *core, | 1322 | int cx88_set_freq (struct cx88_core *core, |
1350 | struct v4l2_frequency *f) | 1323 | struct v4l2_frequency *f) |
1351 | { | 1324 | { |
1352 | if (unlikely(UNSET == core->tuner_type)) | 1325 | if (unlikely(UNSET == core->board.tuner_type)) |
1353 | return -EINVAL; | 1326 | return -EINVAL; |
1354 | if (unlikely(f->tuner != 0)) | 1327 | if (unlikely(f->tuner != 0)) |
1355 | return -EINVAL; | 1328 | return -EINVAL; |
@@ -1420,8 +1393,7 @@ static int radio_querycap (struct file *file, void *priv, | |||
1420 | struct cx88_core *core = dev->core; | 1393 | struct cx88_core *core = dev->core; |
1421 | 1394 | ||
1422 | strcpy(cap->driver, "cx8800"); | 1395 | strcpy(cap->driver, "cx8800"); |
1423 | strlcpy(cap->card, cx88_boards[core->board].name, | 1396 | strlcpy(cap->card, core->board.name, sizeof(cap->card)); |
1424 | sizeof(cap->card)); | ||
1425 | sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci)); | 1397 | sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci)); |
1426 | cap->version = CX88_VERSION_CODE; | 1398 | cap->version = CX88_VERSION_CODE; |
1427 | cap->capabilities = V4L2_CAP_TUNER; | 1399 | cap->capabilities = V4L2_CAP_TUNER; |
@@ -1608,7 +1580,8 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id) | |||
1608 | int loop, handled = 0; | 1580 | int loop, handled = 0; |
1609 | 1581 | ||
1610 | for (loop = 0; loop < 10; loop++) { | 1582 | for (loop = 0; loop < 10; loop++) { |
1611 | status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x01); | 1583 | status = cx_read(MO_PCI_INTSTAT) & |
1584 | (core->pci_irqmask | PCI_INT_VIDINT); | ||
1612 | if (0 == status) | 1585 | if (0 == status) |
1613 | goto out; | 1586 | goto out; |
1614 | cx_write(MO_PCI_INTSTAT, status); | 1587 | cx_write(MO_PCI_INTSTAT, status); |
@@ -1616,7 +1589,7 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id) | |||
1616 | 1589 | ||
1617 | if (status & core->pci_irqmask) | 1590 | if (status & core->pci_irqmask) |
1618 | cx88_core_irq(core,status); | 1591 | cx88_core_irq(core,status); |
1619 | if (status & 0x01) | 1592 | if (status & PCI_INT_VIDINT) |
1620 | cx8800_vid_irq(dev); | 1593 | cx8800_vid_irq(dev); |
1621 | }; | 1594 | }; |
1622 | if (10 == loop) { | 1595 | if (10 == loop) { |
@@ -1717,6 +1690,10 @@ static struct video_device cx8800_radio_template = | |||
1717 | .vidioc_s_ctrl = vidioc_s_ctrl, | 1690 | .vidioc_s_ctrl = vidioc_s_ctrl, |
1718 | .vidioc_g_frequency = vidioc_g_frequency, | 1691 | .vidioc_g_frequency = vidioc_g_frequency, |
1719 | .vidioc_s_frequency = vidioc_s_frequency, | 1692 | .vidioc_s_frequency = vidioc_s_frequency, |
1693 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1694 | .vidioc_g_register = vidioc_g_register, | ||
1695 | .vidioc_s_register = vidioc_s_register, | ||
1696 | #endif | ||
1720 | }; | 1697 | }; |
1721 | 1698 | ||
1722 | /* ----------------------------------------------------------- */ | 1699 | /* ----------------------------------------------------------- */ |
@@ -1818,26 +1795,32 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1818 | err = request_irq(pci_dev->irq, cx8800_irq, | 1795 | err = request_irq(pci_dev->irq, cx8800_irq, |
1819 | IRQF_SHARED | IRQF_DISABLED, core->name, dev); | 1796 | IRQF_SHARED | IRQF_DISABLED, core->name, dev); |
1820 | if (err < 0) { | 1797 | if (err < 0) { |
1821 | printk(KERN_ERR "%s: can't get IRQ %d\n", | 1798 | printk(KERN_ERR "%s/0: can't get IRQ %d\n", |
1822 | core->name,pci_dev->irq); | 1799 | core->name,pci_dev->irq); |
1823 | goto fail_core; | 1800 | goto fail_core; |
1824 | } | 1801 | } |
1825 | cx_set(MO_PCI_INTMSK, core->pci_irqmask); | 1802 | cx_set(MO_PCI_INTMSK, core->pci_irqmask); |
1826 | 1803 | ||
1827 | /* load and configure helper modules */ | 1804 | /* load and configure helper modules */ |
1828 | if (TUNER_ABSENT != core->tuner_type) | 1805 | if (TUNER_ABSENT != core->board.tuner_type) |
1829 | request_module("tuner"); | 1806 | request_module("tuner"); |
1830 | 1807 | ||
1831 | if (cx88_boards[ core->board ].audio_chip == AUDIO_CHIP_WM8775) | 1808 | if (core->board.audio_chip == AUDIO_CHIP_WM8775) |
1832 | request_module("wm8775"); | 1809 | request_module("wm8775"); |
1833 | 1810 | ||
1811 | switch (core->boardnr) { | ||
1812 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: | ||
1813 | request_module("ir-kbd-i2c"); | ||
1814 | request_module("rtc-isl1208"); | ||
1815 | } | ||
1816 | |||
1834 | /* register v4l devices */ | 1817 | /* register v4l devices */ |
1835 | dev->video_dev = cx88_vdev_init(core,dev->pci, | 1818 | dev->video_dev = cx88_vdev_init(core,dev->pci, |
1836 | &cx8800_video_template,"video"); | 1819 | &cx8800_video_template,"video"); |
1837 | err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, | 1820 | err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, |
1838 | video_nr[core->nr]); | 1821 | video_nr[core->nr]); |
1839 | if (err < 0) { | 1822 | if (err < 0) { |
1840 | printk(KERN_INFO "%s: can't register video device\n", | 1823 | printk(KERN_ERR "%s/0: can't register video device\n", |
1841 | core->name); | 1824 | core->name); |
1842 | goto fail_unreg; | 1825 | goto fail_unreg; |
1843 | } | 1826 | } |
@@ -1848,20 +1831,20 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1848 | err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, | 1831 | err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, |
1849 | vbi_nr[core->nr]); | 1832 | vbi_nr[core->nr]); |
1850 | if (err < 0) { | 1833 | if (err < 0) { |
1851 | printk(KERN_INFO "%s/0: can't register vbi device\n", | 1834 | printk(KERN_ERR "%s/0: can't register vbi device\n", |
1852 | core->name); | 1835 | core->name); |
1853 | goto fail_unreg; | 1836 | goto fail_unreg; |
1854 | } | 1837 | } |
1855 | printk(KERN_INFO "%s/0: registered device vbi%d\n", | 1838 | printk(KERN_INFO "%s/0: registered device vbi%d\n", |
1856 | core->name,dev->vbi_dev->minor & 0x1f); | 1839 | core->name,dev->vbi_dev->minor & 0x1f); |
1857 | 1840 | ||
1858 | if (core->has_radio) { | 1841 | if (core->board.radio.type == CX88_RADIO) { |
1859 | dev->radio_dev = cx88_vdev_init(core,dev->pci, | 1842 | dev->radio_dev = cx88_vdev_init(core,dev->pci, |
1860 | &cx8800_radio_template,"radio"); | 1843 | &cx8800_radio_template,"radio"); |
1861 | err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, | 1844 | err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, |
1862 | radio_nr[core->nr]); | 1845 | radio_nr[core->nr]); |
1863 | if (err < 0) { | 1846 | if (err < 0) { |
1864 | printk(KERN_INFO "%s/0: can't register radio device\n", | 1847 | printk(KERN_ERR "%s/0: can't register radio device\n", |
1865 | core->name); | 1848 | core->name); |
1866 | goto fail_unreg; | 1849 | goto fail_unreg; |
1867 | } | 1850 | } |
@@ -1881,12 +1864,12 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1881 | mutex_unlock(&core->lock); | 1864 | mutex_unlock(&core->lock); |
1882 | 1865 | ||
1883 | /* start tvaudio thread */ | 1866 | /* start tvaudio thread */ |
1884 | if (core->tuner_type != TUNER_ABSENT) { | 1867 | if (core->board.tuner_type != TUNER_ABSENT) { |
1885 | core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio"); | 1868 | core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio"); |
1886 | if (IS_ERR(core->kthread)) { | 1869 | if (IS_ERR(core->kthread)) { |
1887 | err = PTR_ERR(core->kthread); | 1870 | err = PTR_ERR(core->kthread); |
1888 | printk(KERN_ERR "Failed to create cx88 audio thread, err=%d\n", | 1871 | printk(KERN_ERR "%s/0: failed to create cx88 audio thread, err=%d\n", |
1889 | err); | 1872 | core->name, err); |
1890 | } | 1873 | } |
1891 | } | 1874 | } |
1892 | return 0; | 1875 | return 0; |
@@ -1937,17 +1920,19 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state) | |||
1937 | /* stop video+vbi capture */ | 1920 | /* stop video+vbi capture */ |
1938 | spin_lock(&dev->slock); | 1921 | spin_lock(&dev->slock); |
1939 | if (!list_empty(&dev->vidq.active)) { | 1922 | if (!list_empty(&dev->vidq.active)) { |
1940 | printk("%s: suspend video\n", core->name); | 1923 | printk("%s/0: suspend video\n", core->name); |
1941 | stop_video_dma(dev); | 1924 | stop_video_dma(dev); |
1942 | del_timer(&dev->vidq.timeout); | 1925 | del_timer(&dev->vidq.timeout); |
1943 | } | 1926 | } |
1944 | if (!list_empty(&dev->vbiq.active)) { | 1927 | if (!list_empty(&dev->vbiq.active)) { |
1945 | printk("%s: suspend vbi\n", core->name); | 1928 | printk("%s/0: suspend vbi\n", core->name); |
1946 | cx8800_stop_vbi_dma(dev); | 1929 | cx8800_stop_vbi_dma(dev); |
1947 | del_timer(&dev->vbiq.timeout); | 1930 | del_timer(&dev->vbiq.timeout); |
1948 | } | 1931 | } |
1949 | spin_unlock(&dev->slock); | 1932 | spin_unlock(&dev->slock); |
1950 | 1933 | ||
1934 | if (core->ir) | ||
1935 | cx88_ir_stop(core, core->ir); | ||
1951 | /* FIXME -- shutdown device */ | 1936 | /* FIXME -- shutdown device */ |
1952 | cx88_shutdown(core); | 1937 | cx88_shutdown(core); |
1953 | 1938 | ||
@@ -1968,8 +1953,8 @@ static int cx8800_resume(struct pci_dev *pci_dev) | |||
1968 | if (dev->state.disabled) { | 1953 | if (dev->state.disabled) { |
1969 | err=pci_enable_device(pci_dev); | 1954 | err=pci_enable_device(pci_dev); |
1970 | if (err) { | 1955 | if (err) { |
1971 | printk(KERN_ERR "%s: can't enable device\n", | 1956 | printk(KERN_ERR "%s/0: can't enable device\n", |
1972 | core->name); | 1957 | core->name); |
1973 | return err; | 1958 | return err; |
1974 | } | 1959 | } |
1975 | 1960 | ||
@@ -1977,9 +1962,7 @@ static int cx8800_resume(struct pci_dev *pci_dev) | |||
1977 | } | 1962 | } |
1978 | err= pci_set_power_state(pci_dev, PCI_D0); | 1963 | err= pci_set_power_state(pci_dev, PCI_D0); |
1979 | if (err) { | 1964 | if (err) { |
1980 | printk(KERN_ERR "%s: can't enable device\n", | 1965 | printk(KERN_ERR "%s/0: can't set power state\n", core->name); |
1981 | core->name); | ||
1982 | |||
1983 | pci_disable_device(pci_dev); | 1966 | pci_disable_device(pci_dev); |
1984 | dev->state.disabled = 1; | 1967 | dev->state.disabled = 1; |
1985 | 1968 | ||
@@ -1989,15 +1972,19 @@ static int cx8800_resume(struct pci_dev *pci_dev) | |||
1989 | 1972 | ||
1990 | /* FIXME: re-initialize hardware */ | 1973 | /* FIXME: re-initialize hardware */ |
1991 | cx88_reset(core); | 1974 | cx88_reset(core); |
1975 | if (core->ir) | ||
1976 | cx88_ir_start(core, core->ir); | ||
1977 | |||
1978 | cx_set(MO_PCI_INTMSK, core->pci_irqmask); | ||
1992 | 1979 | ||
1993 | /* restart video+vbi capture */ | 1980 | /* restart video+vbi capture */ |
1994 | spin_lock(&dev->slock); | 1981 | spin_lock(&dev->slock); |
1995 | if (!list_empty(&dev->vidq.active)) { | 1982 | if (!list_empty(&dev->vidq.active)) { |
1996 | printk("%s: resume video\n", core->name); | 1983 | printk("%s/0: resume video\n", core->name); |
1997 | restart_video_queue(dev,&dev->vidq); | 1984 | restart_video_queue(dev,&dev->vidq); |
1998 | } | 1985 | } |
1999 | if (!list_empty(&dev->vbiq.active)) { | 1986 | if (!list_empty(&dev->vbiq.active)) { |
2000 | printk("%s: resume vbi\n", core->name); | 1987 | printk("%s/0: resume vbi\n", core->name); |
2001 | cx8800_restart_vbi_queue(dev,&dev->vbiq); | 1988 | cx8800_restart_vbi_queue(dev,&dev->vbiq); |
2002 | } | 1989 | } |
2003 | spin_unlock(&dev->slock); | 1990 | spin_unlock(&dev->slock); |
@@ -2033,7 +2020,7 @@ static struct pci_driver cx8800_pci_driver = { | |||
2033 | 2020 | ||
2034 | static int cx8800_init(void) | 2021 | static int cx8800_init(void) |
2035 | { | 2022 | { |
2036 | printk(KERN_INFO "cx2388x v4l2 driver version %d.%d.%d loaded\n", | 2023 | printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %d.%d.%d loaded\n", |
2037 | (CX88_VERSION_CODE >> 16) & 0xff, | 2024 | (CX88_VERSION_CODE >> 16) & 0xff, |
2038 | (CX88_VERSION_CODE >> 8) & 0xff, | 2025 | (CX88_VERSION_CODE >> 8) & 0xff, |
2039 | CX88_VERSION_CODE & 0xff); | 2026 | CX88_VERSION_CODE & 0xff); |
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c index cd0877636a32..77c37889232b 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c | |||
@@ -23,7 +23,6 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/init.h> | 26 | #include <linux/init.h> |
28 | 27 | ||
29 | #include <asm/io.h> | 28 | #include <asm/io.h> |
@@ -111,7 +110,7 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) | |||
111 | struct vp3054_i2c_state *vp3054_i2c; | 110 | struct vp3054_i2c_state *vp3054_i2c; |
112 | int rc; | 111 | int rc; |
113 | 112 | ||
114 | if (core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) | 113 | if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) |
115 | return 0; | 114 | return 0; |
116 | 115 | ||
117 | dev->card_priv = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL); | 116 | dev->card_priv = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL); |
@@ -152,7 +151,7 @@ void vp3054_i2c_remove(struct cx8802_dev *dev) | |||
152 | struct vp3054_i2c_state *vp3054_i2c = dev->card_priv; | 151 | struct vp3054_i2c_state *vp3054_i2c = dev->card_priv; |
153 | 152 | ||
154 | if (vp3054_i2c == NULL || | 153 | if (vp3054_i2c == NULL || |
155 | dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) | 154 | dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) |
156 | return; | 155 | return; |
157 | 156 | ||
158 | i2c_del_adapter(&vp3054_i2c->adap); | 157 | i2c_del_adapter(&vp3054_i2c->adap); |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 809126866a3e..42e0a9b8c550 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -28,11 +28,11 @@ | |||
28 | #include <media/v4l2-common.h> | 28 | #include <media/v4l2-common.h> |
29 | #include <media/tuner.h> | 29 | #include <media/tuner.h> |
30 | #include <media/tveeprom.h> | 30 | #include <media/tveeprom.h> |
31 | #include <media/video-buf.h> | 31 | #include <media/videobuf-dma-sg.h> |
32 | #include <media/cx2341x.h> | 32 | #include <media/cx2341x.h> |
33 | #include <media/audiochip.h> | 33 | #include <media/audiochip.h> |
34 | #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) | 34 | #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) |
35 | #include <media/video-buf-dvb.h> | 35 | #include <media/videobuf-dvb.h> |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | #include "btcx-risc.h" | 38 | #include "btcx-risc.h" |
@@ -226,8 +226,8 @@ enum cx88_itype { | |||
226 | 226 | ||
227 | struct cx88_input { | 227 | struct cx88_input { |
228 | enum cx88_itype type; | 228 | enum cx88_itype type; |
229 | unsigned int vmux; | ||
230 | u32 gpio0, gpio1, gpio2, gpio3; | 229 | u32 gpio0, gpio1, gpio2, gpio3; |
230 | unsigned int vmux:2; | ||
231 | unsigned int extadc:1; | 231 | unsigned int extadc:1; |
232 | }; | 232 | }; |
233 | 233 | ||
@@ -250,7 +250,7 @@ struct cx88_subid { | |||
250 | u32 card; | 250 | u32 card; |
251 | }; | 251 | }; |
252 | 252 | ||
253 | #define INPUT(nr) (&cx88_boards[core->board].input[nr]) | 253 | #define INPUT(nr) (core->board.input[nr]) |
254 | 254 | ||
255 | /* ----------------------------------------------------------- */ | 255 | /* ----------------------------------------------------------- */ |
256 | /* device / file handle status */ | 256 | /* device / file handle status */ |
@@ -304,19 +304,14 @@ struct cx88_core { | |||
304 | u32 i2c_state, i2c_rc; | 304 | u32 i2c_state, i2c_rc; |
305 | 305 | ||
306 | /* config info -- analog */ | 306 | /* config info -- analog */ |
307 | unsigned int board; | 307 | unsigned int boardnr; |
308 | unsigned int tuner_type; | 308 | struct cx88_board board; |
309 | unsigned int radio_type; | ||
310 | unsigned char tuner_addr; | ||
311 | unsigned char radio_addr; | ||
312 | unsigned int tda9887_conf; | ||
313 | unsigned int has_radio; | ||
314 | 309 | ||
315 | /* Supported V4L _STD_ tuner formats */ | 310 | /* Supported V4L _STD_ tuner formats */ |
316 | unsigned int tuner_formats; | 311 | unsigned int tuner_formats; |
317 | 312 | ||
318 | /* config info -- dvb */ | 313 | /* config info -- dvb */ |
319 | #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) | 314 | #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) |
320 | int (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); | 315 | int (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); |
321 | #endif | 316 | #endif |
322 | 317 | ||
@@ -463,7 +458,7 @@ struct cx8802_dev { | |||
463 | int width; | 458 | int width; |
464 | int height; | 459 | int height; |
465 | 460 | ||
466 | #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) | 461 | #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) |
467 | /* for dvb only */ | 462 | /* for dvb only */ |
468 | struct videobuf_dvb dvb; | 463 | struct videobuf_dvb dvb; |
469 | 464 | ||
@@ -524,7 +519,7 @@ cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |||
524 | extern int | 519 | extern int |
525 | cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, | 520 | cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, |
526 | struct scatterlist *sglist, unsigned int bpl, | 521 | struct scatterlist *sglist, unsigned int bpl, |
527 | unsigned int lines); | 522 | unsigned int lines, unsigned int lpi); |
528 | extern int | 523 | extern int |
529 | cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | 524 | cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, |
530 | u32 reg, u32 mask, u32 value); | 525 | u32 reg, u32 mask, u32 value); |
@@ -585,15 +580,9 @@ extern void cx88_call_i2c_clients(struct cx88_core *core, | |||
585 | /* ----------------------------------------------------------- */ | 580 | /* ----------------------------------------------------------- */ |
586 | /* cx88-cards.c */ | 581 | /* cx88-cards.c */ |
587 | 582 | ||
588 | extern struct cx88_board cx88_boards[]; | 583 | extern int cx88_get_resources(const struct cx88_core *core, |
589 | extern const unsigned int cx88_bcount; | 584 | struct pci_dev *pci); |
590 | 585 | extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr); | |
591 | extern struct cx88_subid cx88_subids[]; | ||
592 | extern const unsigned int cx88_idcount; | ||
593 | |||
594 | extern void cx88_card_list(struct cx88_core *core, struct pci_dev *pci); | ||
595 | extern void cx88_card_setup(struct cx88_core *core); | ||
596 | extern void cx88_card_setup_pre_i2c(struct cx88_core *core); | ||
597 | 586 | ||
598 | /* ----------------------------------------------------------- */ | 587 | /* ----------------------------------------------------------- */ |
599 | /* cx88-tvaudio.c */ | 588 | /* cx88-tvaudio.c */ |
@@ -625,6 +614,8 @@ struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board | |||
625 | int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci); | 614 | int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci); |
626 | int cx88_ir_fini(struct cx88_core *core); | 615 | int cx88_ir_fini(struct cx88_core *core); |
627 | void cx88_ir_irq(struct cx88_core *core); | 616 | void cx88_ir_irq(struct cx88_core *core); |
617 | void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir); | ||
618 | void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir); | ||
628 | 619 | ||
629 | /* ----------------------------------------------------------- */ | 620 | /* ----------------------------------------------------------- */ |
630 | /* cx88-mpeg.c */ | 621 | /* cx88-mpeg.c */ |
diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c index 0fcc935828f8..255dae303708 100644 --- a/drivers/media/video/dpc7146.c +++ b/drivers/media/video/dpc7146.c | |||
@@ -92,7 +92,6 @@ static int dpc_probe(struct saa7146_dev* dev) | |||
92 | { | 92 | { |
93 | struct dpc* dpc = NULL; | 93 | struct dpc* dpc = NULL; |
94 | struct i2c_client *client; | 94 | struct i2c_client *client; |
95 | struct list_head *item; | ||
96 | 95 | ||
97 | dpc = kzalloc(sizeof(struct dpc), GFP_KERNEL); | 96 | dpc = kzalloc(sizeof(struct dpc), GFP_KERNEL); |
98 | if( NULL == dpc ) { | 97 | if( NULL == dpc ) { |
@@ -116,11 +115,9 @@ static int dpc_probe(struct saa7146_dev* dev) | |||
116 | } | 115 | } |
117 | 116 | ||
118 | /* loop through all i2c-devices on the bus and look who is there */ | 117 | /* loop through all i2c-devices on the bus and look who is there */ |
119 | list_for_each(item,&dpc->i2c_adapter.clients) { | 118 | list_for_each_entry(client, &dpc->i2c_adapter.clients, list) |
120 | client = list_entry(item, struct i2c_client, list); | ||
121 | if( I2C_SAA7111A == client->addr ) | 119 | if( I2C_SAA7111A == client->addr ) |
122 | dpc->saa7111a = client; | 120 | dpc->saa7111a = client; |
123 | } | ||
124 | 121 | ||
125 | /* check if all devices are present */ | 122 | /* check if all devices are present */ |
126 | if( 0 == dpc->saa7111a ) { | 123 | if( 0 == dpc->saa7111a ) { |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 255a47dfb84f..d3282ec62c5b 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/list.h> | 25 | #include <linux/list.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/moduleparam.h> | ||
28 | #include <linux/usb.h> | 27 | #include <linux/usb.h> |
29 | #include <linux/vmalloc.h> | 28 | #include <linux/vmalloc.h> |
30 | 29 | ||
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 55d45b0032cf..e3894b68c4ee 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -22,7 +22,6 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/init.h> | 25 | #include <linux/init.h> |
27 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 40307f3f6fe3..b8d5327c438d 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -252,10 +252,8 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
252 | int minor = iminor(inode); | 252 | int minor = iminor(inode); |
253 | int errCode = 0; | 253 | int errCode = 0; |
254 | struct em28xx *h,*dev = NULL; | 254 | struct em28xx *h,*dev = NULL; |
255 | struct list_head *list; | ||
256 | 255 | ||
257 | list_for_each(list,&em28xx_devlist) { | 256 | list_for_each_entry(h, &em28xx_devlist, devlist) { |
258 | h = list_entry(list, struct em28xx, devlist); | ||
259 | if (h->vdev->minor == minor) { | 257 | if (h->vdev->minor == minor) { |
260 | dev = h; | 258 | dev = h; |
261 | dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 259 | dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
@@ -268,8 +266,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
268 | if (NULL == dev) | 266 | if (NULL == dev) |
269 | return -ENODEV; | 267 | return -ENODEV; |
270 | 268 | ||
271 | filp->private_data=dev; | ||
272 | |||
273 | em28xx_videodbg("open minor=%d type=%s users=%d\n", | 269 | em28xx_videodbg("open minor=%d type=%s users=%d\n", |
274 | minor,v4l2_type_names[dev->type],dev->users); | 270 | minor,v4l2_type_names[dev->type],dev->users); |
275 | 271 | ||
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 585bd1fe0765..d5fef4c01c87 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/param.h> | 24 | #include <linux/param.h> |
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
27 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
28 | #include <linux/device.h> | 27 | #include <linux/device.h> |
@@ -707,7 +706,8 @@ static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count) | |||
707 | NOTE 2: buffers are PAGE_SIZE long | 706 | NOTE 2: buffers are PAGE_SIZE long |
708 | */ | 707 | */ |
709 | 708 | ||
710 | static ssize_t et61x251_show_reg(struct class_device* cd, char* buf) | 709 | static ssize_t et61x251_show_reg(struct device* cd, |
710 | struct device_attribute *attr, char* buf) | ||
711 | { | 711 | { |
712 | struct et61x251_device* cam; | 712 | struct et61x251_device* cam; |
713 | ssize_t count; | 713 | ssize_t count; |
@@ -730,7 +730,8 @@ static ssize_t et61x251_show_reg(struct class_device* cd, char* buf) | |||
730 | 730 | ||
731 | 731 | ||
732 | static ssize_t | 732 | static ssize_t |
733 | et61x251_store_reg(struct class_device* cd, const char* buf, size_t len) | 733 | et61x251_store_reg(struct device* cd, |
734 | struct device_attribute *attr, const char* buf, size_t len) | ||
734 | { | 735 | { |
735 | struct et61x251_device* cam; | 736 | struct et61x251_device* cam; |
736 | u8 index; | 737 | u8 index; |
@@ -762,7 +763,8 @@ et61x251_store_reg(struct class_device* cd, const char* buf, size_t len) | |||
762 | } | 763 | } |
763 | 764 | ||
764 | 765 | ||
765 | static ssize_t et61x251_show_val(struct class_device* cd, char* buf) | 766 | static ssize_t et61x251_show_val(struct device* cd, |
767 | struct device_attribute *attr, char* buf) | ||
766 | { | 768 | { |
767 | struct et61x251_device* cam; | 769 | struct et61x251_device* cam; |
768 | ssize_t count; | 770 | ssize_t count; |
@@ -793,7 +795,8 @@ static ssize_t et61x251_show_val(struct class_device* cd, char* buf) | |||
793 | 795 | ||
794 | 796 | ||
795 | static ssize_t | 797 | static ssize_t |
796 | et61x251_store_val(struct class_device* cd, const char* buf, size_t len) | 798 | et61x251_store_val(struct device* cd, struct device_attribute *attr, |
799 | const char* buf, size_t len) | ||
797 | { | 800 | { |
798 | struct et61x251_device* cam; | 801 | struct et61x251_device* cam; |
799 | u8 value; | 802 | u8 value; |
@@ -831,7 +834,8 @@ et61x251_store_val(struct class_device* cd, const char* buf, size_t len) | |||
831 | } | 834 | } |
832 | 835 | ||
833 | 836 | ||
834 | static ssize_t et61x251_show_i2c_reg(struct class_device* cd, char* buf) | 837 | static ssize_t et61x251_show_i2c_reg(struct device* cd, |
838 | struct device_attribute *attr, char* buf) | ||
835 | { | 839 | { |
836 | struct et61x251_device* cam; | 840 | struct et61x251_device* cam; |
837 | ssize_t count; | 841 | ssize_t count; |
@@ -856,7 +860,8 @@ static ssize_t et61x251_show_i2c_reg(struct class_device* cd, char* buf) | |||
856 | 860 | ||
857 | 861 | ||
858 | static ssize_t | 862 | static ssize_t |
859 | et61x251_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) | 863 | et61x251_store_i2c_reg(struct device* cd, struct device_attribute *attr, |
864 | const char* buf, size_t len) | ||
860 | { | 865 | { |
861 | struct et61x251_device* cam; | 866 | struct et61x251_device* cam; |
862 | u8 index; | 867 | u8 index; |
@@ -888,7 +893,8 @@ et61x251_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) | |||
888 | } | 893 | } |
889 | 894 | ||
890 | 895 | ||
891 | static ssize_t et61x251_show_i2c_val(struct class_device* cd, char* buf) | 896 | static ssize_t et61x251_show_i2c_val(struct device* cd, |
897 | struct device_attribute *attr, char* buf) | ||
892 | { | 898 | { |
893 | struct et61x251_device* cam; | 899 | struct et61x251_device* cam; |
894 | ssize_t count; | 900 | ssize_t count; |
@@ -924,7 +930,8 @@ static ssize_t et61x251_show_i2c_val(struct class_device* cd, char* buf) | |||
924 | 930 | ||
925 | 931 | ||
926 | static ssize_t | 932 | static ssize_t |
927 | et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len) | 933 | et61x251_store_i2c_val(struct device* cd, struct device_attribute *attr, |
934 | const char* buf, size_t len) | ||
928 | { | 935 | { |
929 | struct et61x251_device* cam; | 936 | struct et61x251_device* cam; |
930 | u8 value; | 937 | u8 value; |
@@ -967,42 +974,40 @@ et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len) | |||
967 | } | 974 | } |
968 | 975 | ||
969 | 976 | ||
970 | static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, | 977 | static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, |
971 | et61x251_show_reg, et61x251_store_reg); | 978 | et61x251_show_reg, et61x251_store_reg); |
972 | static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR, | 979 | static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, |
973 | et61x251_show_val, et61x251_store_val); | 980 | et61x251_show_val, et61x251_store_val); |
974 | static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, | 981 | static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, |
975 | et61x251_show_i2c_reg, et61x251_store_i2c_reg); | 982 | et61x251_show_i2c_reg, et61x251_store_i2c_reg); |
976 | static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, | 983 | static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, |
977 | et61x251_show_i2c_val, et61x251_store_i2c_val); | 984 | et61x251_show_i2c_val, et61x251_store_i2c_val); |
978 | 985 | ||
979 | 986 | ||
980 | static int et61x251_create_sysfs(struct et61x251_device* cam) | 987 | static int et61x251_create_sysfs(struct et61x251_device* cam) |
981 | { | 988 | { |
982 | struct class_device *classdev = &(cam->v4ldev->class_dev); | 989 | struct device *classdev = &(cam->v4ldev->class_dev); |
983 | int err = 0; | 990 | int err = 0; |
984 | 991 | ||
985 | if ((err = class_device_create_file(classdev, &class_device_attr_reg))) | 992 | if ((err = device_create_file(classdev, &dev_attr_reg))) |
986 | goto err_out; | 993 | goto err_out; |
987 | if ((err = class_device_create_file(classdev, &class_device_attr_val))) | 994 | if ((err = device_create_file(classdev, &dev_attr_val))) |
988 | goto err_reg; | 995 | goto err_reg; |
989 | 996 | ||
990 | if (cam->sensor.sysfs_ops) { | 997 | if (cam->sensor.sysfs_ops) { |
991 | if ((err = class_device_create_file(classdev, | 998 | if ((err = device_create_file(classdev, &dev_attr_i2c_reg))) |
992 | &class_device_attr_i2c_reg))) | ||
993 | goto err_val; | 999 | goto err_val; |
994 | if ((err = class_device_create_file(classdev, | 1000 | if ((err = device_create_file(classdev, &dev_attr_i2c_val))) |
995 | &class_device_attr_i2c_val))) | ||
996 | goto err_i2c_reg; | 1001 | goto err_i2c_reg; |
997 | } | 1002 | } |
998 | 1003 | ||
999 | err_i2c_reg: | 1004 | err_i2c_reg: |
1000 | if (cam->sensor.sysfs_ops) | 1005 | if (cam->sensor.sysfs_ops) |
1001 | class_device_remove_file(classdev, &class_device_attr_i2c_reg); | 1006 | device_remove_file(classdev, &dev_attr_i2c_reg); |
1002 | err_val: | 1007 | err_val: |
1003 | class_device_remove_file(classdev, &class_device_attr_val); | 1008 | device_remove_file(classdev, &dev_attr_val); |
1004 | err_reg: | 1009 | err_reg: |
1005 | class_device_remove_file(classdev, &class_device_attr_reg); | 1010 | device_remove_file(classdev, &dev_attr_reg); |
1006 | err_out: | 1011 | err_out: |
1007 | return err; | 1012 | return err; |
1008 | } | 1013 | } |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 2d709e064679..d98dd0d1e373 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -10,6 +10,8 @@ | |||
10 | * Ulrich Mueller <ulrich.mueller42@web.de> | 10 | * Ulrich Mueller <ulrich.mueller42@web.de> |
11 | * modified for em2820 based USB TV tuners by | 11 | * modified for em2820 based USB TV tuners by |
12 | * Markus Rechberger <mrechberger@gmail.com> | 12 | * Markus Rechberger <mrechberger@gmail.com> |
13 | * modified for DViCO Fusion HDTV 5 RT GOLD by | ||
14 | * Chaogui Zhang <czhang1974@gmail.com> | ||
13 | * | 15 | * |
14 | * This program is free software; you can redistribute it and/or modify | 16 | * This program is free software; you can redistribute it and/or modify |
15 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
@@ -28,7 +30,6 @@ | |||
28 | */ | 30 | */ |
29 | 31 | ||
30 | #include <linux/module.h> | 32 | #include <linux/module.h> |
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/init.h> | 33 | #include <linux/init.h> |
33 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
34 | #include <linux/string.h> | 35 | #include <linux/string.h> |
@@ -142,6 +143,30 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
142 | return 1; | 143 | return 1; |
143 | } | 144 | } |
144 | 145 | ||
146 | static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
147 | { | ||
148 | unsigned char buf[4]; | ||
149 | |||
150 | /* poll IR chip */ | ||
151 | if (4 != i2c_master_recv(&ir->c,buf,4)) { | ||
152 | dprintk(1,"read error\n"); | ||
153 | return -EIO; | ||
154 | } | ||
155 | |||
156 | if(buf[0] !=0 || buf[1] !=0 || buf[2] !=0 || buf[3] != 0) | ||
157 | dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __FUNCTION__, | ||
158 | buf[0], buf[1], buf[2], buf[3]); | ||
159 | |||
160 | /* no key pressed or signal from other ir remote */ | ||
161 | if(buf[0] != 0x1 || buf[1] != 0xfe) | ||
162 | return 0; | ||
163 | |||
164 | *ir_key = buf[2]; | ||
165 | *ir_raw = (buf[2] << 8) | buf[3]; | ||
166 | |||
167 | return 1; | ||
168 | } | ||
169 | |||
145 | static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | 170 | static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) |
146 | { | 171 | { |
147 | unsigned char b; | 172 | unsigned char b; |
@@ -364,6 +389,12 @@ static int ir_attach(struct i2c_adapter *adap, int addr, | |||
364 | ir_type = IR_TYPE_OTHER; | 389 | ir_type = IR_TYPE_OTHER; |
365 | ir_codes = ir_codes_empty; | 390 | ir_codes = ir_codes_empty; |
366 | break; | 391 | break; |
392 | case 0x6b: | ||
393 | name = "FusionHDTV"; | ||
394 | ir->get_key = get_key_fusionhdtv; | ||
395 | ir_type = IR_TYPE_RC5; | ||
396 | ir_codes = ir_codes_fusionhdtv_mce; | ||
397 | break; | ||
367 | case 0x7a: | 398 | case 0x7a: |
368 | case 0x47: | 399 | case 0x47: |
369 | case 0x71: | 400 | case 0x71: |
@@ -475,7 +506,8 @@ static int ir_probe(struct i2c_adapter *adap) | |||
475 | static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; | 506 | static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; |
476 | static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, -1 }; | 507 | static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, -1 }; |
477 | static const int probe_em28XX[] = { 0x30, 0x47, -1 }; | 508 | static const int probe_em28XX[] = { 0x30, 0x47, -1 }; |
478 | static const int probe_cx88[] = { 0x18, 0x71, -1 }; | 509 | static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 }; |
510 | static const int probe_cx23885[] = { 0x6b, -1 }; | ||
479 | const int *probe = NULL; | 511 | const int *probe = NULL; |
480 | struct i2c_client c; | 512 | struct i2c_client c; |
481 | unsigned char buf; | 513 | unsigned char buf; |
@@ -496,6 +528,8 @@ static int ir_probe(struct i2c_adapter *adap) | |||
496 | break; | 528 | break; |
497 | case I2C_HW_B_CX2388x: | 529 | case I2C_HW_B_CX2388x: |
498 | probe = probe_cx88; | 530 | probe = probe_cx88; |
531 | case I2C_HW_B_CX23885: | ||
532 | probe = probe_cx23885; | ||
499 | break; | 533 | break; |
500 | } | 534 | } |
501 | if (NULL == probe) | 535 | if (NULL == probe) |
diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index e43beb2c9cbf..854cc9c30ca9 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig | |||
@@ -14,6 +14,7 @@ config VIDEO_IVTV | |||
14 | select VIDEO_CS53L32A | 14 | select VIDEO_CS53L32A |
15 | select VIDEO_WM8775 | 15 | select VIDEO_WM8775 |
16 | select VIDEO_WM8739 | 16 | select VIDEO_WM8739 |
17 | select VIDEO_VP27SMPX | ||
17 | select VIDEO_UPD64031A | 18 | select VIDEO_UPD64031A |
18 | select VIDEO_UPD64083 | 19 | select VIDEO_UPD64083 |
19 | ---help--- | 20 | ---help--- |
@@ -25,3 +26,19 @@ config VIDEO_IVTV | |||
25 | 26 | ||
26 | To compile this driver as a module, choose M here: the | 27 | To compile this driver as a module, choose M here: the |
27 | module will be called ivtv. | 28 | module will be called ivtv. |
29 | |||
30 | config VIDEO_FB_IVTV | ||
31 | tristate "Conexant cx23415 framebuffer support" | ||
32 | depends on VIDEO_IVTV && FB && EXPERIMENTAL | ||
33 | select FB_CFB_FILLRECT | ||
34 | select FB_CFB_COPYAREA | ||
35 | select FB_CFB_IMAGEBLIT | ||
36 | ---help--- | ||
37 | This is a framebuffer driver for the Conexant cx23415 MPEG | ||
38 | encoder/decoder. | ||
39 | |||
40 | This is used in the Hauppauge PVR-350 card. There is a driver | ||
41 | homepage at <http://www.ivtvdriver.org>. | ||
42 | |||
43 | To compile this driver as a module, choose M here: the | ||
44 | module will be called ivtvfb. | ||
diff --git a/drivers/media/video/ivtv/Makefile b/drivers/media/video/ivtv/Makefile index 7e95148fbf4f..e8eefd96d897 100644 --- a/drivers/media/video/ivtv/Makefile +++ b/drivers/media/video/ivtv/Makefile | |||
@@ -1,7 +1,8 @@ | |||
1 | ivtv-objs := ivtv-audio.o ivtv-cards.o ivtv-controls.o \ | 1 | ivtv-objs := ivtv-routing.o ivtv-cards.o ivtv-controls.o \ |
2 | ivtv-driver.o ivtv-fileops.o ivtv-firmware.o \ | 2 | ivtv-driver.o ivtv-fileops.o ivtv-firmware.o \ |
3 | ivtv-gpio.o ivtv-i2c.o ivtv-ioctl.o ivtv-irq.o \ | 3 | ivtv-gpio.o ivtv-i2c.o ivtv-ioctl.o ivtv-irq.o \ |
4 | ivtv-mailbox.o ivtv-queue.o ivtv-streams.o ivtv-udma.o \ | 4 | ivtv-mailbox.o ivtv-queue.o ivtv-streams.o ivtv-udma.o \ |
5 | ivtv-vbi.o ivtv-video.o ivtv-yuv.o | 5 | ivtv-vbi.o ivtv-yuv.o |
6 | 6 | ||
7 | obj-$(CONFIG_VIDEO_IVTV) += ivtv.o | 7 | obj-$(CONFIG_VIDEO_IVTV) += ivtv.o |
8 | obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o | ||
diff --git a/drivers/media/video/ivtv/ivtv-audio.c b/drivers/media/video/ivtv/ivtv-audio.c deleted file mode 100644 index d702b8b539a1..000000000000 --- a/drivers/media/video/ivtv/ivtv-audio.c +++ /dev/null | |||
@@ -1,74 +0,0 @@ | |||
1 | /* | ||
2 | Audio-related ivtv functions. | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include "ivtv-driver.h" | ||
22 | #include "ivtv-mailbox.h" | ||
23 | #include "ivtv-i2c.h" | ||
24 | #include "ivtv-gpio.h" | ||
25 | #include "ivtv-cards.h" | ||
26 | #include "ivtv-audio.h" | ||
27 | #include <media/msp3400.h> | ||
28 | #include <linux/videodev.h> | ||
29 | |||
30 | /* Selects the audio input and output according to the current | ||
31 | settings. */ | ||
32 | int ivtv_audio_set_io(struct ivtv *itv) | ||
33 | { | ||
34 | struct v4l2_routing route; | ||
35 | u32 audio_input; | ||
36 | int mux_input; | ||
37 | |||
38 | /* Determine which input to use */ | ||
39 | if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) { | ||
40 | audio_input = itv->card->radio_input.audio_input; | ||
41 | mux_input = itv->card->radio_input.muxer_input; | ||
42 | } else { | ||
43 | audio_input = itv->card->audio_inputs[itv->audio_input].audio_input; | ||
44 | mux_input = itv->card->audio_inputs[itv->audio_input].muxer_input; | ||
45 | } | ||
46 | |||
47 | /* handle muxer chips */ | ||
48 | route.input = mux_input; | ||
49 | route.output = 0; | ||
50 | ivtv_i2c_hw(itv, itv->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route); | ||
51 | |||
52 | route.input = audio_input; | ||
53 | if (itv->card->hw_audio & IVTV_HW_MSP34XX) { | ||
54 | route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); | ||
55 | } | ||
56 | return ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, &route); | ||
57 | } | ||
58 | |||
59 | void ivtv_audio_set_route(struct ivtv *itv, struct v4l2_routing *route) | ||
60 | { | ||
61 | ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route); | ||
62 | } | ||
63 | |||
64 | void ivtv_audio_set_audio_clock_freq(struct ivtv *itv, u8 freq) | ||
65 | { | ||
66 | static u32 freqs[3] = { 44100, 48000, 32000 }; | ||
67 | |||
68 | /* The audio clock of the digitizer must match the codec sample | ||
69 | rate otherwise you get some very strange effects. */ | ||
70 | if (freq > 2) | ||
71 | return; | ||
72 | ivtv_call_i2c_clients(itv, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[freq]); | ||
73 | } | ||
74 | |||
diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c index 8eab02083887..b6a8be622d3c 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/video/ivtv/ivtv-cards.c | |||
@@ -616,7 +616,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx = { | |||
616 | .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, | 616 | .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, |
617 | .hw_audio = IVTV_HW_GPIO, | 617 | .hw_audio = IVTV_HW_GPIO, |
618 | .hw_audio_ctrl = IVTV_HW_WM8739, | 618 | .hw_audio_ctrl = IVTV_HW_WM8739, |
619 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TVAUDIO | | 619 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_VP27SMPX | |
620 | IVTV_HW_TUNER | IVTV_HW_WM8739 | | 620 | IVTV_HW_TUNER | IVTV_HW_WM8739 | |
621 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, | 621 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, |
622 | .video_inputs = { | 622 | .video_inputs = { |
@@ -654,7 +654,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx2e = { | |||
654 | .hw_audio = IVTV_HW_GPIO, | 654 | .hw_audio = IVTV_HW_GPIO, |
655 | .hw_audio_ctrl = IVTV_HW_WM8739, | 655 | .hw_audio_ctrl = IVTV_HW_WM8739, |
656 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER | | 656 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER | |
657 | IVTV_HW_TVAUDIO | IVTV_HW_WM8739, | 657 | IVTV_HW_VP27SMPX | IVTV_HW_WM8739, |
658 | .video_inputs = { | 658 | .video_inputs = { |
659 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, | 659 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, |
660 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, | 660 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, |
@@ -823,9 +823,7 @@ static const struct ivtv_card ivtv_card_dctmvtvp1 = { | |||
823 | 823 | ||
824 | /* ------------------------------------------------------------------------- */ | 824 | /* ------------------------------------------------------------------------- */ |
825 | 825 | ||
826 | #ifdef HAVE_XC3028 | 826 | /* Yuan PG600-2/GotView PCI DVD Lite cards */ |
827 | |||
828 | /* Yuan PG600-2/GotView PCI DVD Lite/Club3D ZAP-TV1x01 cards */ | ||
829 | 827 | ||
830 | static const struct ivtv_card_pci_info ivtv_pci_pg600v2[] = { | 828 | static const struct ivtv_card_pci_info ivtv_pci_pg600v2[] = { |
831 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3, 0x0600 }, | 829 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3, 0x0600 }, |
@@ -835,29 +833,87 @@ static const struct ivtv_card_pci_info ivtv_pci_pg600v2[] = { | |||
835 | 833 | ||
836 | static const struct ivtv_card ivtv_card_pg600v2 = { | 834 | static const struct ivtv_card ivtv_card_pg600v2 = { |
837 | .type = IVTV_CARD_PG600V2, | 835 | .type = IVTV_CARD_PG600V2, |
838 | .name = "Yuan PG600-2, GotView PCI DVD Lite, Club3D ZAP-TV1x01", | 836 | .name = "Yuan PG600-2, GotView PCI DVD Lite", |
839 | .v4l2_capabilities = IVTV_CAP_ENCODER, | 837 | .v4l2_capabilities = IVTV_CAP_ENCODER, |
840 | .hw_video = IVTV_HW_CX25840, | 838 | .hw_video = IVTV_HW_CX25840, |
841 | .hw_audio = IVTV_HW_CX25840, | 839 | .hw_audio = IVTV_HW_CX25840, |
842 | .hw_audio_ctrl = IVTV_HW_CX25840, | 840 | .hw_audio_ctrl = IVTV_HW_CX25840, |
843 | .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, | 841 | .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, |
844 | .video_inputs = { | 842 | .video_inputs = { |
845 | { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, | 843 | { IVTV_CARD_INPUT_SVIDEO1, 0, |
846 | { IVTV_CARD_INPUT_SVIDEO1, 1, | ||
847 | CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, | 844 | CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, |
845 | { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 }, | ||
848 | }, | 846 | }, |
849 | .audio_inputs = { | 847 | .audio_inputs = { |
850 | { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, | ||
851 | { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL }, | 848 | { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL }, |
852 | }, | 849 | }, |
853 | .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, | ||
854 | .tuners = { | 850 | .tuners = { |
855 | { .std = V4L2_STD_ALL, .tuner = TUNER_XCEIVE_XC3028 }, | 851 | { .std = V4L2_STD_ALL, .tuner = TUNER_XCEIVE_XC3028 }, |
856 | }, | 852 | }, |
857 | .gpio_init = { .direction = 0x1000, .initial_value = 0x1000 }, /* tuner reset */ | ||
858 | .pci_list = ivtv_pci_pg600v2, | 853 | .pci_list = ivtv_pci_pg600v2, |
859 | }; | 854 | }; |
860 | #endif | 855 | |
856 | /* ------------------------------------------------------------------------- */ | ||
857 | |||
858 | /* Club3D ZAP-TV1x01 cards */ | ||
859 | |||
860 | static const struct ivtv_card_pci_info ivtv_pci_club3d[] = { | ||
861 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3, 0x0600 }, | ||
862 | { 0, 0, 0 } | ||
863 | }; | ||
864 | |||
865 | static const struct ivtv_card ivtv_card_club3d = { | ||
866 | .type = IVTV_CARD_CLUB3D, | ||
867 | .name = "Club3D ZAP-TV1x01", | ||
868 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
869 | .hw_video = IVTV_HW_CX25840, | ||
870 | .hw_audio = IVTV_HW_CX25840, | ||
871 | .hw_audio_ctrl = IVTV_HW_CX25840, | ||
872 | .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, | ||
873 | .video_inputs = { | ||
874 | { IVTV_CARD_INPUT_SVIDEO1, 0, | ||
875 | CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, | ||
876 | { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE3 }, | ||
877 | }, | ||
878 | .audio_inputs = { | ||
879 | { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL }, | ||
880 | }, | ||
881 | .tuners = { | ||
882 | { .std = V4L2_STD_ALL, .tuner = TUNER_XCEIVE_XC3028 }, | ||
883 | }, | ||
884 | .pci_list = ivtv_pci_club3d, | ||
885 | }; | ||
886 | |||
887 | /* ------------------------------------------------------------------------- */ | ||
888 | |||
889 | /* AVerTV MCE 116 Plus (M116) card */ | ||
890 | |||
891 | static const struct ivtv_card_pci_info ivtv_pci_avertv_mce116[] = { | ||
892 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc439 }, | ||
893 | { 0, 0, 0 } | ||
894 | }; | ||
895 | |||
896 | static const struct ivtv_card ivtv_card_avertv_mce116 = { | ||
897 | .type = IVTV_CARD_AVERTV_MCE116, | ||
898 | .name = "AVerTV MCE 116 Plus", | ||
899 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
900 | .hw_video = IVTV_HW_CX25840, | ||
901 | .hw_audio = IVTV_HW_CX25840, | ||
902 | .hw_audio_ctrl = IVTV_HW_CX25840, | ||
903 | .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739, | ||
904 | .video_inputs = { | ||
905 | { IVTV_CARD_INPUT_SVIDEO1, 0, CX25840_SVIDEO3 }, | ||
906 | { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 }, | ||
907 | }, | ||
908 | .audio_inputs = { | ||
909 | { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, | ||
910 | }, | ||
911 | .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 }, /* enable line-in */ | ||
912 | .tuners = { | ||
913 | { .std = V4L2_STD_ALL, .tuner = TUNER_XCEIVE_XC3028 }, | ||
914 | }, | ||
915 | .pci_list = ivtv_pci_avertv_mce116, | ||
916 | }; | ||
861 | 917 | ||
862 | static const struct ivtv_card *ivtv_card_list[] = { | 918 | static const struct ivtv_card *ivtv_card_list[] = { |
863 | &ivtv_card_pvr250, | 919 | &ivtv_card_pvr250, |
@@ -878,9 +934,9 @@ static const struct ivtv_card *ivtv_card_list[] = { | |||
878 | &ivtv_card_gotview_pci_dvd2, | 934 | &ivtv_card_gotview_pci_dvd2, |
879 | &ivtv_card_yuan_mpc622, | 935 | &ivtv_card_yuan_mpc622, |
880 | &ivtv_card_dctmvtvp1, | 936 | &ivtv_card_dctmvtvp1, |
881 | #ifdef HAVE_XC3028 | ||
882 | &ivtv_card_pg600v2, | 937 | &ivtv_card_pg600v2, |
883 | #endif | 938 | &ivtv_card_club3d, |
939 | &ivtv_card_avertv_mce116, | ||
884 | 940 | ||
885 | /* Variations of standard cards but with the same PCI IDs. | 941 | /* Variations of standard cards but with the same PCI IDs. |
886 | These cards must come last in this list. */ | 942 | These cards must come last in this list. */ |
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index 91e9e90c14a5..ff46e5ae8653 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h | |||
@@ -18,6 +18,68 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef IVTV_CARDS_H | ||
22 | #define IVTV_CARDS_H | ||
23 | |||
24 | /* Supported cards */ | ||
25 | #define IVTV_CARD_PVR_250 0 /* WinTV PVR 250 */ | ||
26 | #define IVTV_CARD_PVR_350 1 /* encoder, decoder, tv-out */ | ||
27 | #define IVTV_CARD_PVR_150 2 /* WinTV PVR 150 and PVR 500 (really just two | ||
28 | PVR150s on one PCI board) */ | ||
29 | #define IVTV_CARD_M179 3 /* AVerMedia M179 (encoder only) */ | ||
30 | #define IVTV_CARD_MPG600 4 /* Kuroutoshikou ITVC16-STVLP/YUAN MPG600, encoder only */ | ||
31 | #define IVTV_CARD_MPG160 5 /* Kuroutoshikou ITVC15-STVLP/YUAN MPG160 | ||
32 | cx23415 based, but does not have tv-out */ | ||
33 | #define IVTV_CARD_PG600 6 /* YUAN PG600/DIAMONDMM PVR-550 based on the CX Falcon 2 */ | ||
34 | #define IVTV_CARD_AVC2410 7 /* Adaptec AVC-2410 */ | ||
35 | #define IVTV_CARD_AVC2010 8 /* Adaptec AVD-2010 (No Tuner) */ | ||
36 | #define IVTV_CARD_TG5000TV 9 /* NAGASE TRANSGEAR 5000TV, encoder only */ | ||
37 | #define IVTV_CARD_VA2000MAX_SNT6 10 /* VA2000MAX-STN6 */ | ||
38 | #define IVTV_CARD_CX23416GYC 11 /* Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */ | ||
39 | #define IVTV_CARD_GV_MVPRX 12 /* I/O Data GV-MVP/RX, RX2, RX2W */ | ||
40 | #define IVTV_CARD_GV_MVPRX2E 13 /* I/O Data GV-MVP/RX2E */ | ||
41 | #define IVTV_CARD_GOTVIEW_PCI_DVD 14 /* GotView PCI DVD */ | ||
42 | #define IVTV_CARD_GOTVIEW_PCI_DVD2 15 /* GotView PCI DVD2 */ | ||
43 | #define IVTV_CARD_YUAN_MPC622 16 /* Yuan MPC622 miniPCI */ | ||
44 | #define IVTV_CARD_DCTMTVP1 17 /* DIGITAL COWBOY DCT-MTVP1 */ | ||
45 | #define IVTV_CARD_PG600V2 18 /* Yuan PG600V2/GotView PCI DVD Lite */ | ||
46 | #define IVTV_CARD_CLUB3D 19 /* Club3D ZAP-TV1x01 */ | ||
47 | #define IVTV_CARD_AVERTV_MCE116 20 /* AVerTV MCE 116 Plus */ | ||
48 | #define IVTV_CARD_LAST 20 | ||
49 | |||
50 | /* Variants of existing cards but with the same PCI IDs. The driver | ||
51 | detects these based on other device information. | ||
52 | These cards must always come last. | ||
53 | New cards must be inserted above, and the indices of the cards below | ||
54 | must be adjusted accordingly. */ | ||
55 | |||
56 | /* PVR-350 V1 (uses saa7114) */ | ||
57 | #define IVTV_CARD_PVR_350_V1 (IVTV_CARD_LAST+1) | ||
58 | /* 2 variants of Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */ | ||
59 | #define IVTV_CARD_CX23416GYC_NOGR (IVTV_CARD_LAST+2) | ||
60 | #define IVTV_CARD_CX23416GYC_NOGRYCS (IVTV_CARD_LAST+3) | ||
61 | |||
62 | /* system vendor and device IDs */ | ||
63 | #define PCI_VENDOR_ID_ICOMP 0x4444 | ||
64 | #define PCI_DEVICE_ID_IVTV15 0x0803 | ||
65 | #define PCI_DEVICE_ID_IVTV16 0x0016 | ||
66 | |||
67 | /* subsystem vendor ID */ | ||
68 | #define IVTV_PCI_ID_HAUPPAUGE 0x0070 | ||
69 | #define IVTV_PCI_ID_HAUPPAUGE_ALT1 0x0270 | ||
70 | #define IVTV_PCI_ID_HAUPPAUGE_ALT2 0x4070 | ||
71 | #define IVTV_PCI_ID_ADAPTEC 0x9005 | ||
72 | #define IVTV_PCI_ID_AVERMEDIA 0x1461 | ||
73 | #define IVTV_PCI_ID_YUAN1 0x12ab | ||
74 | #define IVTV_PCI_ID_YUAN2 0xff01 | ||
75 | #define IVTV_PCI_ID_YUAN3 0xffab | ||
76 | #define IVTV_PCI_ID_YUAN4 0xfbab | ||
77 | #define IVTV_PCI_ID_DIAMONDMM 0xff92 | ||
78 | #define IVTV_PCI_ID_IODATA 0x10fc | ||
79 | #define IVTV_PCI_ID_MELCO 0x1154 | ||
80 | #define IVTV_PCI_ID_GOTVIEW1 0xffac | ||
81 | #define IVTV_PCI_ID_GOTVIEW2 0xffad | ||
82 | |||
21 | /* hardware flags */ | 83 | /* hardware flags */ |
22 | #define IVTV_HW_CX25840 (1 << 0) | 84 | #define IVTV_HW_CX25840 (1 << 0) |
23 | #define IVTV_HW_SAA7115 (1 << 1) | 85 | #define IVTV_HW_SAA7115 (1 << 1) |
@@ -33,7 +95,8 @@ | |||
33 | #define IVTV_HW_UPD6408X (1 << 11) | 95 | #define IVTV_HW_UPD6408X (1 << 11) |
34 | #define IVTV_HW_SAA717X (1 << 12) | 96 | #define IVTV_HW_SAA717X (1 << 12) |
35 | #define IVTV_HW_WM8739 (1 << 13) | 97 | #define IVTV_HW_WM8739 (1 << 13) |
36 | #define IVTV_HW_GPIO (1 << 14) | 98 | #define IVTV_HW_VP27SMPX (1 << 14) |
99 | #define IVTV_HW_GPIO (1 << 15) | ||
37 | 100 | ||
38 | #define IVTV_HW_SAA711X (IVTV_HW_SAA7115 | IVTV_HW_SAA7114) | 101 | #define IVTV_HW_SAA711X (IVTV_HW_SAA7115 | IVTV_HW_SAA7114) |
39 | 102 | ||
@@ -205,3 +268,5 @@ int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output); | |||
205 | int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *input); | 268 | int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *input); |
206 | int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *output); | 269 | int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *output); |
207 | const struct ivtv_card *ivtv_get_card(u16 index); | 270 | const struct ivtv_card *ivtv_get_card(u16 index); |
271 | |||
272 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c index 7a876c3e5b19..8c02fa661591 100644 --- a/drivers/media/video/ivtv/ivtv-controls.c +++ b/drivers/media/video/ivtv/ivtv-controls.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include "ivtv-driver.h" | 21 | #include "ivtv-driver.h" |
22 | #include "ivtv-cards.h" | 22 | #include "ivtv-cards.h" |
23 | #include "ivtv-ioctl.h" | 23 | #include "ivtv-ioctl.h" |
24 | #include "ivtv-audio.h" | 24 | #include "ivtv-routing.h" |
25 | #include "ivtv-i2c.h" | 25 | #include "ivtv-i2c.h" |
26 | #include "ivtv-mailbox.h" | 26 | #include "ivtv-mailbox.h" |
27 | #include "ivtv-controls.h" | 27 | #include "ivtv-controls.h" |
@@ -231,8 +231,10 @@ int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg) | |||
231 | } | 231 | } |
232 | IVTV_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n"); | 232 | IVTV_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n"); |
233 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { | 233 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { |
234 | static u32 freqs[3] = { 44100, 48000, 32000 }; | ||
234 | struct cx2341x_mpeg_params p = itv->params; | 235 | struct cx2341x_mpeg_params p = itv->params; |
235 | int err = cx2341x_ext_ctrls(&p, arg, cmd); | 236 | int err = cx2341x_ext_ctrls(&p, atomic_read(&itv->capturing), arg, cmd); |
237 | unsigned idx; | ||
236 | 238 | ||
237 | if (err) | 239 | if (err) |
238 | return err; | 240 | return err; |
@@ -254,7 +256,11 @@ int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg) | |||
254 | } | 256 | } |
255 | itv->params = p; | 257 | itv->params = p; |
256 | itv->dualwatch_stereo_mode = p.audio_properties & 0x0300; | 258 | itv->dualwatch_stereo_mode = p.audio_properties & 0x0300; |
257 | ivtv_audio_set_audio_clock_freq(itv, p.audio_properties & 0x03); | 259 | idx = p.audio_properties & 0x03; |
260 | /* The audio clock of the digitizer must match the codec sample | ||
261 | rate otherwise you get some very strange effects. */ | ||
262 | if (idx < sizeof(freqs)) | ||
263 | ivtv_call_i2c_clients(itv, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[idx]); | ||
258 | return err; | 264 | return err; |
259 | } | 265 | } |
260 | return -EINVAL; | 266 | return -EINVAL; |
@@ -282,7 +288,7 @@ int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg) | |||
282 | } | 288 | } |
283 | IVTV_DEBUG_IOCTL("VIDIOC_G_EXT_CTRLS\n"); | 289 | IVTV_DEBUG_IOCTL("VIDIOC_G_EXT_CTRLS\n"); |
284 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) | 290 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) |
285 | return cx2341x_ext_ctrls(&itv->params, arg, cmd); | 291 | return cx2341x_ext_ctrls(&itv->params, 0, arg, cmd); |
286 | return -EINVAL; | 292 | return -EINVAL; |
287 | } | 293 | } |
288 | 294 | ||
@@ -292,7 +298,7 @@ int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg) | |||
292 | 298 | ||
293 | IVTV_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n"); | 299 | IVTV_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n"); |
294 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) | 300 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) |
295 | return cx2341x_ext_ctrls(&itv->params, arg, cmd); | 301 | return cx2341x_ext_ctrls(&itv->params, atomic_read(&itv->capturing), arg, cmd); |
296 | return -EINVAL; | 302 | return -EINVAL; |
297 | } | 303 | } |
298 | 304 | ||
diff --git a/drivers/media/video/ivtv/ivtv-controls.h b/drivers/media/video/ivtv/ivtv-controls.h index 5a11149725ad..bb8a6a5ed2bc 100644 --- a/drivers/media/video/ivtv/ivtv-controls.h +++ b/drivers/media/video/ivtv/ivtv-controls.h | |||
@@ -18,4 +18,9 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef IVTV_CONTROLS_H | ||
22 | #define IVTV_CONTROLS_H | ||
23 | |||
21 | int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg); | 24 | int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg); |
25 | |||
26 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index d73d433a4ff6..511a66252413 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -52,11 +52,12 @@ | |||
52 | #include "ivtv-ioctl.h" | 52 | #include "ivtv-ioctl.h" |
53 | #include "ivtv-cards.h" | 53 | #include "ivtv-cards.h" |
54 | #include "ivtv-vbi.h" | 54 | #include "ivtv-vbi.h" |
55 | #include "ivtv-audio.h" | 55 | #include "ivtv-routing.h" |
56 | #include "ivtv-gpio.h" | 56 | #include "ivtv-gpio.h" |
57 | #include "ivtv-yuv.h" | 57 | #include "ivtv-yuv.h" |
58 | 58 | ||
59 | #include <media/tveeprom.h> | 59 | #include <media/tveeprom.h> |
60 | #include <media/saa7115.h> | ||
60 | #include <media/v4l2-chip-ident.h> | 61 | #include <media/v4l2-chip-ident.h> |
61 | 62 | ||
62 | /* var to keep track of the number of array elements in use */ | 63 | /* var to keep track of the number of array elements in use */ |
@@ -86,17 +87,16 @@ static struct pci_device_id ivtv_pci_tbl[] __devinitdata = { | |||
86 | 87 | ||
87 | MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl); | 88 | MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl); |
88 | 89 | ||
89 | const u32 yuv_offset[4] = { | ||
90 | IVTV_YUV_BUFFER_OFFSET, | ||
91 | IVTV_YUV_BUFFER_OFFSET_1, | ||
92 | IVTV_YUV_BUFFER_OFFSET_2, | ||
93 | IVTV_YUV_BUFFER_OFFSET_3 | ||
94 | }; | ||
95 | |||
96 | /* Parameter declarations */ | 90 | /* Parameter declarations */ |
97 | static int cardtype[IVTV_MAX_CARDS]; | 91 | static int cardtype[IVTV_MAX_CARDS]; |
98 | static int tuner[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; | 92 | static int tuner[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, |
99 | static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; | 93 | -1, -1, -1, -1, -1, -1, -1, -1, |
94 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
95 | -1, -1, -1, -1, -1, -1, -1, -1 }; | ||
96 | static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, | ||
97 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
98 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
99 | -1, -1, -1, -1, -1, -1, -1, -1 }; | ||
100 | 100 | ||
101 | static int cardtype_c = 1; | 101 | static int cardtype_c = 1; |
102 | static int tuner_c = 1; | 102 | static int tuner_c = 1; |
@@ -106,6 +106,18 @@ static char secam[] = "--"; | |||
106 | static char ntsc[] = "-"; | 106 | static char ntsc[] = "-"; |
107 | 107 | ||
108 | /* Buffers */ | 108 | /* Buffers */ |
109 | |||
110 | /* DMA Buffers, Default size in MB allocated */ | ||
111 | #define IVTV_DEFAULT_ENC_MPG_BUFFERS 4 | ||
112 | #define IVTV_DEFAULT_ENC_YUV_BUFFERS 2 | ||
113 | #define IVTV_DEFAULT_ENC_VBI_BUFFERS 1 | ||
114 | /* Exception: size in kB for this stream (MB is overkill) */ | ||
115 | #define IVTV_DEFAULT_ENC_PCM_BUFFERS 320 | ||
116 | #define IVTV_DEFAULT_DEC_MPG_BUFFERS 1 | ||
117 | #define IVTV_DEFAULT_DEC_YUV_BUFFERS 1 | ||
118 | /* Exception: size in kB for this stream (MB is way overkill) */ | ||
119 | #define IVTV_DEFAULT_DEC_VBI_BUFFERS 64 | ||
120 | |||
109 | static int enc_mpg_buffers = IVTV_DEFAULT_ENC_MPG_BUFFERS; | 121 | static int enc_mpg_buffers = IVTV_DEFAULT_ENC_MPG_BUFFERS; |
110 | static int enc_yuv_buffers = IVTV_DEFAULT_ENC_YUV_BUFFERS; | 122 | static int enc_yuv_buffers = IVTV_DEFAULT_ENC_YUV_BUFFERS; |
111 | static int enc_vbi_buffers = IVTV_DEFAULT_ENC_VBI_BUFFERS; | 123 | static int enc_vbi_buffers = IVTV_DEFAULT_ENC_VBI_BUFFERS; |
@@ -170,17 +182,27 @@ MODULE_PARM_DESC(cardtype, | |||
170 | "\t\t\t16 = GOTVIEW PCI DVD2 Deluxe\n" | 182 | "\t\t\t16 = GOTVIEW PCI DVD2 Deluxe\n" |
171 | "\t\t\t17 = Yuan MPC622\n" | 183 | "\t\t\t17 = Yuan MPC622\n" |
172 | "\t\t\t18 = Digital Cowboy DCT-MTVP1\n" | 184 | "\t\t\t18 = Digital Cowboy DCT-MTVP1\n" |
173 | #ifdef HAVE_XC3028 | 185 | "\t\t\t19 = Yuan PG600V2/GotView PCI DVD Lite\n" |
174 | "\t\t\t19 = Yuan PG600V2/GotView PCI DVD Lite/Club3D ZAP-TV1x01\n" | 186 | "\t\t\t20 = Club3D ZAP-TV1x01\n" |
175 | #endif | 187 | "\t\t\t21 = AverTV MCE 116 Plus\n" |
176 | "\t\t\t 0 = Autodetect (default)\n" | 188 | "\t\t\t 0 = Autodetect (default)\n" |
177 | "\t\t\t-1 = Ignore this card\n\t\t"); | 189 | "\t\t\t-1 = Ignore this card\n\t\t"); |
178 | MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); | 190 | MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); |
179 | MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC"); | 191 | MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC"); |
180 | MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K"); | 192 | MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K"); |
181 | MODULE_PARM_DESC(debug, | 193 | MODULE_PARM_DESC(debug, |
182 | "Debug level (bitmask). Default: errors only\n" | 194 | "Debug level (bitmask). Default: 0\n" |
183 | "\t\t\t(debug = 1023 gives full debugging)"); | 195 | "\t\t\t 1/0x0001: warning\n" |
196 | "\t\t\t 2/0x0002: info\n" | ||
197 | "\t\t\t 4/0x0004: mailbox\n" | ||
198 | "\t\t\t 8/0x0008: ioctl\n" | ||
199 | "\t\t\t 16/0x0010: file\n" | ||
200 | "\t\t\t 32/0x0020: dma\n" | ||
201 | "\t\t\t 64/0x0040: irq\n" | ||
202 | "\t\t\t 128/0x0080: decoder\n" | ||
203 | "\t\t\t 256/0x0100: yuv\n" | ||
204 | "\t\t\t 512/0x0200: i2c\n" | ||
205 | "\t\t\t1024/0x0400: high volume\n"); | ||
184 | MODULE_PARM_DESC(ivtv_pci_latency, | 206 | MODULE_PARM_DESC(ivtv_pci_latency, |
185 | "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" | 207 | "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" |
186 | "\t\t\tDefault: Yes"); | 208 | "\t\t\tDefault: Yes"); |
@@ -201,7 +223,7 @@ MODULE_PARM_DESC(enc_vbi_buffers, | |||
201 | "Encoder VBI Buffers (in MB)\n" | 223 | "Encoder VBI Buffers (in MB)\n" |
202 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_VBI_BUFFERS)); | 224 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_VBI_BUFFERS)); |
203 | MODULE_PARM_DESC(enc_pcm_buffers, | 225 | MODULE_PARM_DESC(enc_pcm_buffers, |
204 | "Encoder PCM buffers (in MB)\n" | 226 | "Encoder PCM buffers (in kB)\n" |
205 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_PCM_BUFFERS)); | 227 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_PCM_BUFFERS)); |
206 | MODULE_PARM_DESC(dec_mpg_buffers, | 228 | MODULE_PARM_DESC(dec_mpg_buffers, |
207 | "Decoder MPG buffers (in MB)\n" | 229 | "Decoder MPG buffers (in MB)\n" |
@@ -210,7 +232,7 @@ MODULE_PARM_DESC(dec_yuv_buffers, | |||
210 | "Decoder YUV buffers (in MB)\n" | 232 | "Decoder YUV buffers (in MB)\n" |
211 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_YUV_BUFFERS)); | 233 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_YUV_BUFFERS)); |
212 | MODULE_PARM_DESC(dec_vbi_buffers, | 234 | MODULE_PARM_DESC(dec_vbi_buffers, |
213 | "Decoder VBI buffers (in MB)\n" | 235 | "Decoder VBI buffers (in kB)\n" |
214 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_VBI_BUFFERS)); | 236 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_VBI_BUFFERS)); |
215 | MODULE_PARM_DESC(newi2c, | 237 | MODULE_PARM_DESC(newi2c, |
216 | "Use new I2C implementation\n" | 238 | "Use new I2C implementation\n" |
@@ -540,13 +562,13 @@ static void ivtv_process_options(struct ivtv *itv) | |||
540 | const char *chipname; | 562 | const char *chipname; |
541 | int i, j; | 563 | int i, j; |
542 | 564 | ||
543 | itv->options.megabytes[IVTV_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers; | 565 | itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers * 1024; |
544 | itv->options.megabytes[IVTV_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers; | 566 | itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers * 1024; |
545 | itv->options.megabytes[IVTV_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers; | 567 | itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers * 1024; |
546 | itv->options.megabytes[IVTV_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers; | 568 | itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers; |
547 | itv->options.megabytes[IVTV_DEC_STREAM_TYPE_MPG] = dec_mpg_buffers; | 569 | itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_MPG] = dec_mpg_buffers * 1024; |
548 | itv->options.megabytes[IVTV_DEC_STREAM_TYPE_YUV] = dec_yuv_buffers; | 570 | itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_YUV] = dec_yuv_buffers * 1024; |
549 | itv->options.megabytes[IVTV_DEC_STREAM_TYPE_VBI] = dec_vbi_buffers; | 571 | itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_VBI] = dec_vbi_buffers; |
550 | itv->options.cardtype = cardtype[itv->num]; | 572 | itv->options.cardtype = cardtype[itv->num]; |
551 | itv->options.tuner = tuner[itv->num]; | 573 | itv->options.tuner = tuner[itv->num]; |
552 | itv->options.radio = radio[itv->num]; | 574 | itv->options.radio = radio[itv->num]; |
@@ -645,7 +667,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) | |||
645 | cx2341x_fill_defaults(&itv->params); | 667 | cx2341x_fill_defaults(&itv->params); |
646 | itv->params.port = CX2341X_PORT_MEMORY; | 668 | itv->params.port = CX2341X_PORT_MEMORY; |
647 | itv->params.capabilities = CX2341X_CAP_HAS_SLICED_VBI; | 669 | itv->params.capabilities = CX2341X_CAP_HAS_SLICED_VBI; |
648 | init_waitqueue_head(&itv->cap_w); | 670 | init_waitqueue_head(&itv->eos_waitq); |
649 | init_waitqueue_head(&itv->event_waitq); | 671 | init_waitqueue_head(&itv->event_waitq); |
650 | init_waitqueue_head(&itv->vsync_waitq); | 672 | init_waitqueue_head(&itv->vsync_waitq); |
651 | init_waitqueue_head(&itv->dma_waitq); | 673 | init_waitqueue_head(&itv->dma_waitq); |
@@ -691,14 +713,6 @@ static void __devinit ivtv_init_struct2(struct ivtv *itv) | |||
691 | break; | 713 | break; |
692 | itv->nof_audio_inputs = i; | 714 | itv->nof_audio_inputs = i; |
693 | 715 | ||
694 | /* 0x00EF = saa7114(239) 0x00F0 = saa7115(240) 0x0106 = micro */ | ||
695 | if (itv->card->hw_all & (IVTV_HW_SAA7115 | IVTV_HW_SAA717X)) | ||
696 | itv->digitizer = 0xF1; | ||
697 | else if (itv->card->hw_all & IVTV_HW_SAA7114) | ||
698 | itv->digitizer = 0xEF; | ||
699 | else /* cx25840 */ | ||
700 | itv->digitizer = 0x140; | ||
701 | |||
702 | if (itv->card->hw_all & IVTV_HW_CX25840) { | 716 | if (itv->card->hw_all & IVTV_HW_CX25840) { |
703 | itv->vbi.sliced_size = 288; /* multiple of 16, real size = 284 */ | 717 | itv->vbi.sliced_size = 288; /* multiple of 16, real size = 284 */ |
704 | } else { | 718 | } else { |
@@ -727,6 +741,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, | |||
727 | const struct pci_device_id *pci_id) | 741 | const struct pci_device_id *pci_id) |
728 | { | 742 | { |
729 | u16 cmd; | 743 | u16 cmd; |
744 | u8 card_rev; | ||
730 | unsigned char pci_latency; | 745 | unsigned char pci_latency; |
731 | 746 | ||
732 | IVTV_DEBUG_INFO("Enabling pci device\n"); | 747 | IVTV_DEBUG_INFO("Enabling pci device\n"); |
@@ -773,7 +788,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, | |||
773 | } | 788 | } |
774 | IVTV_DEBUG_INFO("Bus Mastering Enabled.\n"); | 789 | IVTV_DEBUG_INFO("Bus Mastering Enabled.\n"); |
775 | 790 | ||
776 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &itv->card_rev); | 791 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &card_rev); |
777 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); | 792 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); |
778 | 793 | ||
779 | if (pci_latency < 64 && ivtv_pci_latency) { | 794 | if (pci_latency < 64 && ivtv_pci_latency) { |
@@ -790,7 +805,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, | |||
790 | 805 | ||
791 | IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, " | 806 | IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, " |
792 | "irq: %d, latency: %d, memory: 0x%lx\n", | 807 | "irq: %d, latency: %d, memory: 0x%lx\n", |
793 | itv->dev->device, itv->card_rev, dev->bus->number, | 808 | itv->dev->device, card_rev, dev->bus->number, |
794 | PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), | 809 | PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), |
795 | itv->dev->irq, pci_latency, (unsigned long)itv->base_addr); | 810 | itv->dev->irq, pci_latency, (unsigned long)itv->base_addr); |
796 | 811 | ||
@@ -808,18 +823,19 @@ static void ivtv_request_module(struct ivtv *itv, const char *name) | |||
808 | 823 | ||
809 | static void ivtv_load_and_init_modules(struct ivtv *itv) | 824 | static void ivtv_load_and_init_modules(struct ivtv *itv) |
810 | { | 825 | { |
811 | struct v4l2_control ctrl; | ||
812 | u32 hw = itv->card->hw_all; | 826 | u32 hw = itv->card->hw_all; |
813 | int i; | 827 | int i; |
814 | 828 | ||
815 | /* load modules */ | 829 | /* load modules */ |
816 | #ifndef CONFIG_VIDEO_TUNER | 830 | #ifndef CONFIG_VIDEO_TUNER |
817 | if (hw & IVTV_HW_TUNER) { | 831 | if (hw & IVTV_HW_TUNER) { |
818 | ivtv_request_module(itv, "tuner"); | 832 | if (itv->options.tuner == TUNER_XCEIVE_XC3028) { |
819 | #ifdef HAVE_XC3028 | 833 | IVTV_INFO("Xceive tuner not yet supported, only composite and S-Video inputs will be available\n"); |
820 | if (itv->options.tuner == TUNER_XCEIVE_XC3028) | 834 | itv->tunerid = 1; |
821 | ivtv_request_module(itv, "xc3028-tuner"); | 835 | } |
822 | #endif | 836 | else { |
837 | ivtv_request_module(itv, "tuner"); | ||
838 | } | ||
823 | } | 839 | } |
824 | #endif | 840 | #endif |
825 | #ifndef CONFIG_VIDEO_CX25840 | 841 | #ifndef CONFIG_VIDEO_CX25840 |
@@ -848,6 +864,10 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) | |||
848 | if (hw & IVTV_HW_MSP34XX) | 864 | if (hw & IVTV_HW_MSP34XX) |
849 | ivtv_request_module(itv, "msp3400"); | 865 | ivtv_request_module(itv, "msp3400"); |
850 | #endif | 866 | #endif |
867 | #ifndef CONFIG_VIDEO_VP27SMPX | ||
868 | if (hw & IVTV_HW_VP27SMPX) | ||
869 | ivtv_request_module(itv, "vp27smpx"); | ||
870 | #endif | ||
851 | if (hw & IVTV_HW_TVAUDIO) | 871 | if (hw & IVTV_HW_TVAUDIO) |
852 | ivtv_request_module(itv, "tvaudio"); | 872 | ivtv_request_module(itv, "tvaudio"); |
853 | #ifndef CONFIG_VIDEO_WM8775 | 873 | #ifndef CONFIG_VIDEO_WM8775 |
@@ -888,13 +908,17 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) | |||
888 | else if ((hw & IVTV_HW_UPD64031A) == 0) | 908 | else if ((hw & IVTV_HW_UPD64031A) == 0) |
889 | itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGR); | 909 | itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGR); |
890 | } | 910 | } |
911 | else if (itv->card->type == IVTV_CARD_GV_MVPRX || | ||
912 | itv->card->type == IVTV_CARD_GV_MVPRX2E) { | ||
913 | struct v4l2_crystal_freq crystal_freq; | ||
914 | |||
915 | /* The crystal frequency of GVMVPRX is 24.576MHz */ | ||
916 | crystal_freq.freq = SAA7115_FREQ_24_576_MHZ; | ||
917 | crystal_freq.flags = SAA7115_FREQ_FL_UCGC; | ||
918 | itv->video_dec_func(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq); | ||
919 | } | ||
891 | 920 | ||
892 | if (hw & IVTV_HW_CX25840) { | 921 | if (hw & IVTV_HW_CX25840) { |
893 | /* CX25840_CID_ENABLE_PVR150_WORKAROUND */ | ||
894 | ctrl.id = V4L2_CID_PRIVATE_BASE; | ||
895 | ctrl.value = itv->pvr150_workaround; | ||
896 | itv->video_dec_func(itv, VIDIOC_S_CTRL, &ctrl); | ||
897 | |||
898 | itv->vbi.raw_decoder_line_size = 1444; | 922 | itv->vbi.raw_decoder_line_size = 1444; |
899 | itv->vbi.raw_decoder_sav_odd_field = 0x20; | 923 | itv->vbi.raw_decoder_sav_odd_field = 0x20; |
900 | itv->vbi.raw_decoder_sav_even_field = 0x60; | 924 | itv->vbi.raw_decoder_sav_even_field = 0x60; |
@@ -940,12 +964,9 @@ static int __devinit ivtv_probe(struct pci_dev *dev, | |||
940 | const struct pci_device_id *pci_id) | 964 | const struct pci_device_id *pci_id) |
941 | { | 965 | { |
942 | int retval = 0; | 966 | int retval = 0; |
943 | int video_input; | ||
944 | int yuv_buf_size; | 967 | int yuv_buf_size; |
945 | int vbi_buf_size; | 968 | int vbi_buf_size; |
946 | int fw_retry_count = 3; | ||
947 | struct ivtv *itv; | 969 | struct ivtv *itv; |
948 | struct v4l2_frequency vf; | ||
949 | 970 | ||
950 | spin_lock(&ivtv_cards_lock); | 971 | spin_lock(&ivtv_cards_lock); |
951 | 972 | ||
@@ -982,6 +1003,8 @@ static int __devinit ivtv_probe(struct pci_dev *dev, | |||
982 | 1003 | ||
983 | IVTV_DEBUG_INFO("base addr: 0x%08x\n", itv->base_addr); | 1004 | IVTV_DEBUG_INFO("base addr: 0x%08x\n", itv->base_addr); |
984 | 1005 | ||
1006 | mutex_lock(&itv->serialize_lock); | ||
1007 | |||
985 | /* PCI Device Setup */ | 1008 | /* PCI Device Setup */ |
986 | if ((retval = ivtv_setup_pci(itv, dev, pci_id)) != 0) { | 1009 | if ((retval = ivtv_setup_pci(itv, dev, pci_id)) != 0) { |
987 | if (retval == -EIO) | 1010 | if (retval == -EIO) |
@@ -1032,22 +1055,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev, | |||
1032 | goto free_io; | 1055 | goto free_io; |
1033 | } | 1056 | } |
1034 | 1057 | ||
1035 | while (--fw_retry_count > 0) { | ||
1036 | /* load firmware */ | ||
1037 | if (ivtv_firmware_init(itv) == 0) | ||
1038 | break; | ||
1039 | if (fw_retry_count > 1) | ||
1040 | IVTV_WARN("Retry loading firmware\n"); | ||
1041 | } | ||
1042 | if (fw_retry_count == 0) { | ||
1043 | IVTV_ERR("Error initializing firmware\n"); | ||
1044 | goto free_i2c; | ||
1045 | } | ||
1046 | |||
1047 | /* Try and get firmware versions */ | ||
1048 | IVTV_DEBUG_INFO("Getting firmware version..\n"); | ||
1049 | ivtv_firmware_versions(itv); | ||
1050 | |||
1051 | /* Check yuv output filter table */ | 1058 | /* Check yuv output filter table */ |
1052 | if (itv->has_cx23415) ivtv_yuv_filter_check(itv); | 1059 | if (itv->has_cx23415) ivtv_yuv_filter_check(itv); |
1053 | 1060 | ||
@@ -1135,43 +1142,22 @@ static int __devinit ivtv_probe(struct pci_dev *dev, | |||
1135 | if (itv->options.radio > 0) | 1142 | if (itv->options.radio > 0) |
1136 | itv->v4l2_cap |= V4L2_CAP_RADIO; | 1143 | itv->v4l2_cap |= V4L2_CAP_RADIO; |
1137 | 1144 | ||
1138 | if (itv->options.tuner > -1) { | 1145 | if (itv->options.tuner > -1 && itv->tunerid == 0) { |
1139 | struct tuner_setup setup; | 1146 | struct tuner_setup setup; |
1140 | 1147 | ||
1141 | setup.addr = ADDR_UNSET; | 1148 | setup.addr = ADDR_UNSET; |
1142 | setup.type = itv->options.tuner; | 1149 | setup.type = itv->options.tuner; |
1143 | setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */ | 1150 | setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */ |
1144 | #ifdef HAVE_XC3028 | ||
1145 | setup.initmode = V4L2_TUNER_ANALOG_TV; | ||
1146 | if (itv->options.tuner == TUNER_XCEIVE_XC3028) { | ||
1147 | setup.gpio_write = ivtv_reset_tuner_gpio; | ||
1148 | setup.gpio_priv = itv; | ||
1149 | } | ||
1150 | #endif | ||
1151 | ivtv_call_i2c_clients(itv, TUNER_SET_TYPE_ADDR, &setup); | 1151 | ivtv_call_i2c_clients(itv, TUNER_SET_TYPE_ADDR, &setup); |
1152 | } | 1152 | } |
1153 | 1153 | ||
1154 | vf.tuner = 0; | ||
1155 | vf.type = V4L2_TUNER_ANALOG_TV; | ||
1156 | vf.frequency = 6400; /* the tuner 'baseline' frequency */ | ||
1157 | if (itv->std & V4L2_STD_NTSC_M) { | ||
1158 | /* Why on earth? */ | ||
1159 | vf.frequency = 1076; /* ch. 4 67250*16/1000 */ | ||
1160 | } | ||
1161 | |||
1162 | /* The tuner is fixed to the standard. The other inputs (e.g. S-Video) | 1154 | /* The tuner is fixed to the standard. The other inputs (e.g. S-Video) |
1163 | are not. */ | 1155 | are not. */ |
1164 | itv->tuner_std = itv->std; | 1156 | itv->tuner_std = itv->std; |
1165 | 1157 | ||
1166 | video_input = itv->active_input; | 1158 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { |
1167 | itv->active_input++; /* Force update of input */ | 1159 | ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std); |
1168 | ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_INPUT, &video_input); | 1160 | } |
1169 | |||
1170 | /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code | ||
1171 | in one place. */ | ||
1172 | itv->std++; /* Force full standard initialization */ | ||
1173 | itv->std_out = itv->std; | ||
1174 | ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_FREQUENCY, &vf); | ||
1175 | 1161 | ||
1176 | retval = ivtv_streams_setup(itv); | 1162 | retval = ivtv_streams_setup(itv); |
1177 | if (retval) { | 1163 | if (retval) { |
@@ -1179,11 +1165,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev, | |||
1179 | goto free_i2c; | 1165 | goto free_i2c; |
1180 | } | 1166 | } |
1181 | 1167 | ||
1182 | if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) { | ||
1183 | ivtv_init_mpeg_decoder(itv); | ||
1184 | } | ||
1185 | ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_STD, &itv->tuner_std); | ||
1186 | |||
1187 | IVTV_DEBUG_IRQ("Masking interrupts\n"); | 1168 | IVTV_DEBUG_IRQ("Masking interrupts\n"); |
1188 | /* clear interrupt mask, effectively disabling interrupts */ | 1169 | /* clear interrupt mask, effectively disabling interrupts */ |
1189 | ivtv_set_irq_mask(itv, 0xffffffff); | 1170 | ivtv_set_irq_mask(itv, 0xffffffff); |
@@ -1195,26 +1176,8 @@ static int __devinit ivtv_probe(struct pci_dev *dev, | |||
1195 | IVTV_ERR("Failed to register irq %d\n", retval); | 1176 | IVTV_ERR("Failed to register irq %d\n", retval); |
1196 | goto free_streams; | 1177 | goto free_streams; |
1197 | } | 1178 | } |
1198 | 1179 | mutex_unlock(&itv->serialize_lock); | |
1199 | /* On a cx23416 this seems to be able to enable DMA to the chip? */ | ||
1200 | if (!itv->has_cx23415) | ||
1201 | write_reg_sync(0x03, IVTV_REG_DMACONTROL); | ||
1202 | |||
1203 | /* Default interrupts enabled. For the PVR350 this includes the | ||
1204 | decoder VSYNC interrupt, which is always on. It is not only used | ||
1205 | during decoding but also by the OSD. | ||
1206 | Some old PVR250 cards had a cx23415, so testing for that is too | ||
1207 | general. Instead test if the card has video output capability. */ | ||
1208 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) | ||
1209 | ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC); | ||
1210 | else | ||
1211 | ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT); | ||
1212 | |||
1213 | if (itv->has_cx23415) | ||
1214 | ivtv_set_osd_alpha(itv); | ||
1215 | |||
1216 | IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name); | 1180 | IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name); |
1217 | |||
1218 | return 0; | 1181 | return 0; |
1219 | 1182 | ||
1220 | free_irq: | 1183 | free_irq: |
@@ -1232,65 +1195,146 @@ static int __devinit ivtv_probe(struct pci_dev *dev, | |||
1232 | release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); | 1195 | release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); |
1233 | free_workqueue: | 1196 | free_workqueue: |
1234 | destroy_workqueue(itv->irq_work_queues); | 1197 | destroy_workqueue(itv->irq_work_queues); |
1198 | mutex_unlock(&itv->serialize_lock); | ||
1235 | err: | 1199 | err: |
1236 | if (retval == 0) | 1200 | if (retval == 0) |
1237 | retval = -ENODEV; | 1201 | retval = -ENODEV; |
1238 | IVTV_ERR("Error %d on initialization\n", retval); | 1202 | IVTV_ERR("Error %d on initialization\n", retval); |
1239 | 1203 | ||
1204 | spin_lock(&ivtv_cards_lock); | ||
1240 | kfree(ivtv_cards[ivtv_cards_active]); | 1205 | kfree(ivtv_cards[ivtv_cards_active]); |
1241 | ivtv_cards[ivtv_cards_active] = NULL; | 1206 | ivtv_cards[ivtv_cards_active] = NULL; |
1207 | spin_unlock(&ivtv_cards_lock); | ||
1242 | return retval; | 1208 | return retval; |
1243 | } | 1209 | } |
1244 | 1210 | ||
1211 | int ivtv_init_on_first_open(struct ivtv *itv) | ||
1212 | { | ||
1213 | struct v4l2_frequency vf; | ||
1214 | int fw_retry_count = 3; | ||
1215 | int video_input; | ||
1216 | |||
1217 | if (test_bit(IVTV_F_I_FAILED, &itv->i_flags)) | ||
1218 | return -ENXIO; | ||
1219 | |||
1220 | if (test_and_set_bit(IVTV_F_I_INITED, &itv->i_flags)) | ||
1221 | return 0; | ||
1222 | |||
1223 | while (--fw_retry_count > 0) { | ||
1224 | /* load firmware */ | ||
1225 | if (ivtv_firmware_init(itv) == 0) | ||
1226 | break; | ||
1227 | if (fw_retry_count > 1) | ||
1228 | IVTV_WARN("Retry loading firmware\n"); | ||
1229 | } | ||
1230 | |||
1231 | if (fw_retry_count == 0) { | ||
1232 | set_bit(IVTV_F_I_FAILED, &itv->i_flags); | ||
1233 | return -ENXIO; | ||
1234 | } | ||
1235 | |||
1236 | /* Try and get firmware versions */ | ||
1237 | IVTV_DEBUG_INFO("Getting firmware version..\n"); | ||
1238 | ivtv_firmware_versions(itv); | ||
1239 | |||
1240 | if (itv->card->hw_all & IVTV_HW_CX25840) { | ||
1241 | struct v4l2_control ctrl; | ||
1242 | |||
1243 | /* CX25840_CID_ENABLE_PVR150_WORKAROUND */ | ||
1244 | ctrl.id = V4L2_CID_PRIVATE_BASE; | ||
1245 | ctrl.value = itv->pvr150_workaround; | ||
1246 | itv->video_dec_func(itv, VIDIOC_S_CTRL, &ctrl); | ||
1247 | } | ||
1248 | |||
1249 | vf.tuner = 0; | ||
1250 | vf.type = V4L2_TUNER_ANALOG_TV; | ||
1251 | vf.frequency = 6400; /* the tuner 'baseline' frequency */ | ||
1252 | |||
1253 | /* Set initial frequency. For PAL/SECAM broadcasts no | ||
1254 | 'default' channel exists AFAIK. */ | ||
1255 | if (itv->std == V4L2_STD_NTSC_M_JP) { | ||
1256 | vf.frequency = 1460; /* ch. 1 91250*16/1000 */ | ||
1257 | } | ||
1258 | else if (itv->std & V4L2_STD_NTSC_M) { | ||
1259 | vf.frequency = 1076; /* ch. 4 67250*16/1000 */ | ||
1260 | } | ||
1261 | |||
1262 | video_input = itv->active_input; | ||
1263 | itv->active_input++; /* Force update of input */ | ||
1264 | ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_INPUT, &video_input); | ||
1265 | |||
1266 | /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code | ||
1267 | in one place. */ | ||
1268 | itv->std++; /* Force full standard initialization */ | ||
1269 | itv->std_out = itv->std; | ||
1270 | ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_FREQUENCY, &vf); | ||
1271 | |||
1272 | if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) { | ||
1273 | ivtv_init_mpeg_decoder(itv); | ||
1274 | } | ||
1275 | ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_STD, &itv->tuner_std); | ||
1276 | |||
1277 | /* On a cx23416 this seems to be able to enable DMA to the chip? */ | ||
1278 | if (!itv->has_cx23415) | ||
1279 | write_reg_sync(0x03, IVTV_REG_DMACONTROL); | ||
1280 | |||
1281 | /* Default interrupts enabled. For the PVR350 this includes the | ||
1282 | decoder VSYNC interrupt, which is always on. It is not only used | ||
1283 | during decoding but also by the OSD. | ||
1284 | Some old PVR250 cards had a cx23415, so testing for that is too | ||
1285 | general. Instead test if the card has video output capability. */ | ||
1286 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { | ||
1287 | ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC); | ||
1288 | ivtv_set_osd_alpha(itv); | ||
1289 | } | ||
1290 | else | ||
1291 | ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT); | ||
1292 | return 0; | ||
1293 | } | ||
1294 | |||
1245 | static void ivtv_remove(struct pci_dev *pci_dev) | 1295 | static void ivtv_remove(struct pci_dev *pci_dev) |
1246 | { | 1296 | { |
1247 | struct ivtv *itv = pci_get_drvdata(pci_dev); | 1297 | struct ivtv *itv = pci_get_drvdata(pci_dev); |
1248 | 1298 | ||
1249 | IVTV_DEBUG_INFO("Removing Card #%d\n", itv->num); | 1299 | IVTV_DEBUG_INFO("Removing Card #%d\n", itv->num); |
1250 | 1300 | ||
1251 | /* Stop all captures */ | 1301 | if (test_bit(IVTV_F_I_INITED, &itv->i_flags)) { |
1252 | IVTV_DEBUG_INFO("Stopping all streams\n"); | 1302 | /* Stop all captures */ |
1253 | if (atomic_read(&itv->capturing) > 0) | 1303 | IVTV_DEBUG_INFO("Stopping all streams\n"); |
1254 | ivtv_stop_all_captures(itv); | 1304 | if (atomic_read(&itv->capturing) > 0) |
1255 | 1305 | ivtv_stop_all_captures(itv); | |
1256 | /* Stop all decoding */ | 1306 | |
1257 | IVTV_DEBUG_INFO("Stopping decoding\n"); | 1307 | /* Stop all decoding */ |
1258 | if (atomic_read(&itv->decoding) > 0) { | 1308 | IVTV_DEBUG_INFO("Stopping decoding\n"); |
1259 | int type; | 1309 | if (atomic_read(&itv->decoding) > 0) { |
1260 | 1310 | int type; | |
1261 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) | 1311 | |
1262 | type = IVTV_DEC_STREAM_TYPE_YUV; | 1312 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) |
1263 | else | 1313 | type = IVTV_DEC_STREAM_TYPE_YUV; |
1264 | type = IVTV_DEC_STREAM_TYPE_MPG; | 1314 | else |
1265 | ivtv_stop_v4l2_decode_stream(&itv->streams[type], | 1315 | type = IVTV_DEC_STREAM_TYPE_MPG; |
1266 | VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); | 1316 | ivtv_stop_v4l2_decode_stream(&itv->streams[type], |
1317 | VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); | ||
1318 | } | ||
1319 | ivtv_halt_firmware(itv); | ||
1267 | } | 1320 | } |
1268 | 1321 | ||
1269 | /* Interrupts */ | 1322 | /* Interrupts */ |
1270 | IVTV_DEBUG_INFO("Disabling interrupts\n"); | ||
1271 | ivtv_set_irq_mask(itv, 0xffffffff); | 1323 | ivtv_set_irq_mask(itv, 0xffffffff); |
1272 | del_timer_sync(&itv->dma_timer); | 1324 | del_timer_sync(&itv->dma_timer); |
1273 | 1325 | ||
1274 | /* Stop all Work Queues */ | 1326 | /* Stop all Work Queues */ |
1275 | IVTV_DEBUG_INFO("Stop Work Queues\n"); | ||
1276 | flush_workqueue(itv->irq_work_queues); | 1327 | flush_workqueue(itv->irq_work_queues); |
1277 | destroy_workqueue(itv->irq_work_queues); | 1328 | destroy_workqueue(itv->irq_work_queues); |
1278 | 1329 | ||
1279 | IVTV_DEBUG_INFO("Stopping Firmware\n"); | ||
1280 | ivtv_halt_firmware(itv); | ||
1281 | |||
1282 | IVTV_DEBUG_INFO("Unregistering v4l devices\n"); | ||
1283 | ivtv_streams_cleanup(itv); | 1330 | ivtv_streams_cleanup(itv); |
1284 | IVTV_DEBUG_INFO("Freeing dma resources\n"); | ||
1285 | ivtv_udma_free(itv); | 1331 | ivtv_udma_free(itv); |
1286 | 1332 | ||
1287 | exit_ivtv_i2c(itv); | 1333 | exit_ivtv_i2c(itv); |
1288 | 1334 | ||
1289 | IVTV_DEBUG_INFO(" Releasing irq\n"); | ||
1290 | free_irq(itv->dev->irq, (void *)itv); | 1335 | free_irq(itv->dev->irq, (void *)itv); |
1291 | ivtv_iounmap(itv); | 1336 | ivtv_iounmap(itv); |
1292 | 1337 | ||
1293 | IVTV_DEBUG_INFO(" Releasing mem\n"); | ||
1294 | release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); | 1338 | release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); |
1295 | release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); | 1339 | release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); |
1296 | if (itv->has_cx23415) | 1340 | if (itv->has_cx23415) |
@@ -1322,9 +1366,9 @@ static int module_start(void) | |||
1322 | return -1; | 1366 | return -1; |
1323 | } | 1367 | } |
1324 | 1368 | ||
1325 | if (ivtv_debug < 0 || ivtv_debug > 1023) { | 1369 | if (ivtv_debug < 0 || ivtv_debug > 2047) { |
1326 | ivtv_debug = 0; | 1370 | ivtv_debug = 0; |
1327 | printk(KERN_INFO "ivtv: Debug value must be >= 0 and <= 1023\n"); | 1371 | printk(KERN_INFO "ivtv: Debug value must be >= 0 and <= 2047\n"); |
1328 | } | 1372 | } |
1329 | 1373 | ||
1330 | if (pci_register_driver(&ivtv_pci_driver)) { | 1374 | if (pci_register_driver(&ivtv_pci_driver)) { |
@@ -1341,6 +1385,7 @@ static void module_cleanup(void) | |||
1341 | 1385 | ||
1342 | pci_unregister_driver(&ivtv_pci_driver); | 1386 | pci_unregister_driver(&ivtv_pci_driver); |
1343 | 1387 | ||
1388 | spin_lock(&ivtv_cards_lock); | ||
1344 | for (i = 0; i < ivtv_cards_active; i++) { | 1389 | for (i = 0; i < ivtv_cards_active; i++) { |
1345 | if (ivtv_cards[i] == NULL) | 1390 | if (ivtv_cards[i] == NULL) |
1346 | continue; | 1391 | continue; |
@@ -1349,13 +1394,15 @@ static void module_cleanup(void) | |||
1349 | } | 1394 | } |
1350 | kfree(ivtv_cards[i]); | 1395 | kfree(ivtv_cards[i]); |
1351 | } | 1396 | } |
1397 | spin_unlock(&ivtv_cards_lock); | ||
1352 | } | 1398 | } |
1353 | 1399 | ||
1354 | /* Note: These symbols are exported because they are used by the ivtv-fb | 1400 | /* Note: These symbols are exported because they are used by the ivtvfb |
1355 | framebuffer module and an infrared module for the IR-blaster. */ | 1401 | framebuffer module and an infrared module for the IR-blaster. */ |
1356 | EXPORT_SYMBOL(ivtv_set_irq_mask); | 1402 | EXPORT_SYMBOL(ivtv_set_irq_mask); |
1357 | EXPORT_SYMBOL(ivtv_cards_active); | 1403 | EXPORT_SYMBOL(ivtv_cards_active); |
1358 | EXPORT_SYMBOL(ivtv_cards); | 1404 | EXPORT_SYMBOL(ivtv_cards); |
1405 | EXPORT_SYMBOL(ivtv_cards_lock); | ||
1359 | EXPORT_SYMBOL(ivtv_api); | 1406 | EXPORT_SYMBOL(ivtv_api); |
1360 | EXPORT_SYMBOL(ivtv_vapi); | 1407 | EXPORT_SYMBOL(ivtv_vapi); |
1361 | EXPORT_SYMBOL(ivtv_vapi_result); | 1408 | EXPORT_SYMBOL(ivtv_vapi_result); |
@@ -1366,6 +1413,7 @@ EXPORT_SYMBOL(ivtv_udma_setup); | |||
1366 | EXPORT_SYMBOL(ivtv_udma_unmap); | 1413 | EXPORT_SYMBOL(ivtv_udma_unmap); |
1367 | EXPORT_SYMBOL(ivtv_udma_alloc); | 1414 | EXPORT_SYMBOL(ivtv_udma_alloc); |
1368 | EXPORT_SYMBOL(ivtv_udma_prepare); | 1415 | EXPORT_SYMBOL(ivtv_udma_prepare); |
1416 | EXPORT_SYMBOL(ivtv_init_on_first_open); | ||
1369 | 1417 | ||
1370 | module_init(module_start); | 1418 | module_init(module_start); |
1371 | module_exit(module_cleanup); | 1419 | module_exit(module_cleanup); |
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 8abb34a35816..3bda1df63cb6 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
@@ -38,7 +38,6 @@ | |||
38 | 38 | ||
39 | #include <linux/version.h> | 39 | #include <linux/version.h> |
40 | #include <linux/module.h> | 40 | #include <linux/module.h> |
41 | #include <linux/moduleparam.h> | ||
42 | #include <linux/init.h> | 41 | #include <linux/init.h> |
43 | #include <linux/delay.h> | 42 | #include <linux/delay.h> |
44 | #include <linux/sched.h> | 43 | #include <linux/sched.h> |
@@ -63,77 +62,20 @@ | |||
63 | #include <media/tuner.h> | 62 | #include <media/tuner.h> |
64 | #include <media/cx2341x.h> | 63 | #include <media/cx2341x.h> |
65 | 64 | ||
66 | /* #define HAVE_XC3028 1 */ | 65 | #include <linux/ivtv.h> |
67 | 66 | ||
68 | #include <media/ivtv.h> | ||
69 | 67 | ||
68 | /* Memory layout */ | ||
70 | #define IVTV_ENCODER_OFFSET 0x00000000 | 69 | #define IVTV_ENCODER_OFFSET 0x00000000 |
71 | #define IVTV_ENCODER_SIZE 0x00800000 /* Last half isn't needed 0x01000000 */ | 70 | #define IVTV_ENCODER_SIZE 0x00800000 /* Total size is 0x01000000, but only first half is used */ |
72 | |||
73 | #define IVTV_DECODER_OFFSET 0x01000000 | 71 | #define IVTV_DECODER_OFFSET 0x01000000 |
74 | #define IVTV_DECODER_SIZE 0x00800000 /* Last half isn't needed 0x01000000 */ | 72 | #define IVTV_DECODER_SIZE 0x00800000 /* Total size is 0x01000000, but only first half is used */ |
75 | |||
76 | #define IVTV_REG_OFFSET 0x02000000 | 73 | #define IVTV_REG_OFFSET 0x02000000 |
77 | #define IVTV_REG_SIZE 0x00010000 | 74 | #define IVTV_REG_SIZE 0x00010000 |
78 | 75 | ||
79 | /* Buffers on hardware offsets */ | 76 | /* Maximum ivtv driver instances. Some people have a huge number of |
80 | #define IVTV_YUV_BUFFER_OFFSET 0x001a8600 /* First YUV Buffer */ | 77 | capture cards, so set this to a high value. */ |
81 | #define IVTV_YUV_BUFFER_OFFSET_1 0x00240400 /* Second YUV Buffer */ | 78 | #define IVTV_MAX_CARDS 32 |
82 | #define IVTV_YUV_BUFFER_OFFSET_2 0x002d8200 /* Third YUV Buffer */ | ||
83 | #define IVTV_YUV_BUFFER_OFFSET_3 0x00370000 /* Fourth YUV Buffer */ | ||
84 | #define IVTV_YUV_BUFFER_UV_OFFSET 0x65400 /* Offset to UV Buffer */ | ||
85 | |||
86 | /* Offset to filter table in firmware */ | ||
87 | #define IVTV_YUV_HORIZONTAL_FILTER_OFFSET 0x025d8 | ||
88 | #define IVTV_YUV_VERTICAL_FILTER_OFFSET 0x03358 | ||
89 | |||
90 | extern const u32 yuv_offset[4]; | ||
91 | |||
92 | /* Maximum ivtv driver instances. | ||
93 | Based on 6 PVR500s each with two PVR15s... | ||
94 | TODO: make this dynamic. I believe it is only a global in order to support | ||
95 | ivtv-fb. There must be a better way to do that. */ | ||
96 | #define IVTV_MAX_CARDS 12 | ||
97 | |||
98 | /* Supported cards */ | ||
99 | #define IVTV_CARD_PVR_250 0 /* WinTV PVR 250 */ | ||
100 | #define IVTV_CARD_PVR_350 1 /* encoder, decoder, tv-out */ | ||
101 | #define IVTV_CARD_PVR_150 2 /* WinTV PVR 150 and PVR 500 (really just two | ||
102 | PVR150s on one PCI board) */ | ||
103 | #define IVTV_CARD_M179 3 /* AVerMedia M179 (encoder only) */ | ||
104 | #define IVTV_CARD_MPG600 4 /* Kuroutoshikou ITVC16-STVLP/YUAN MPG600, encoder only */ | ||
105 | #define IVTV_CARD_MPG160 5 /* Kuroutoshikou ITVC15-STVLP/YUAN MPG160 | ||
106 | cx23415 based, but does not have tv-out */ | ||
107 | #define IVTV_CARD_PG600 6 /* YUAN PG600/DIAMONDMM PVR-550 based on the CX Falcon 2 */ | ||
108 | #define IVTV_CARD_AVC2410 7 /* Adaptec AVC-2410 */ | ||
109 | #define IVTV_CARD_AVC2010 8 /* Adaptec AVD-2010 (No Tuner) */ | ||
110 | #define IVTV_CARD_TG5000TV 9 /* NAGASE TRANSGEAR 5000TV, encoder only */ | ||
111 | #define IVTV_CARD_VA2000MAX_SNT6 10 /* VA2000MAX-STN6 */ | ||
112 | #define IVTV_CARD_CX23416GYC 11 /* Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */ | ||
113 | #define IVTV_CARD_GV_MVPRX 12 /* I/O Data GV-MVP/RX, RX2, RX2W */ | ||
114 | #define IVTV_CARD_GV_MVPRX2E 13 /* I/O Data GV-MVP/RX2E */ | ||
115 | #define IVTV_CARD_GOTVIEW_PCI_DVD 14 /* GotView PCI DVD */ | ||
116 | #define IVTV_CARD_GOTVIEW_PCI_DVD2 15 /* GotView PCI DVD2 */ | ||
117 | #define IVTV_CARD_YUAN_MPC622 16 /* Yuan MPC622 miniPCI */ | ||
118 | #define IVTV_CARD_DCTMTVP1 17 /* DIGITAL COWBOY DCT-MTVP1 */ | ||
119 | #ifdef HAVE_XC3028 | ||
120 | #define IVTV_CARD_PG600V2 18 /* Yuan PG600V2/GotView PCI DVD Lite/Club3D ZAP-TV1x01 */ | ||
121 | #define IVTV_CARD_LAST 18 | ||
122 | #else | ||
123 | #define IVTV_CARD_LAST 17 | ||
124 | #endif | ||
125 | |||
126 | /* Variants of existing cards but with the same PCI IDs. The driver | ||
127 | detects these based on other device information. | ||
128 | These cards must always come last. | ||
129 | New cards must be inserted above, and the indices of the cards below | ||
130 | must be adjusted accordingly. */ | ||
131 | |||
132 | /* PVR-350 V1 (uses saa7114) */ | ||
133 | #define IVTV_CARD_PVR_350_V1 (IVTV_CARD_LAST+1) | ||
134 | /* 2 variants of Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */ | ||
135 | #define IVTV_CARD_CX23416GYC_NOGR (IVTV_CARD_LAST+2) | ||
136 | #define IVTV_CARD_CX23416GYC_NOGRYCS (IVTV_CARD_LAST+3) | ||
137 | 79 | ||
138 | #define IVTV_ENC_STREAM_TYPE_MPG 0 | 80 | #define IVTV_ENC_STREAM_TYPE_MPG 0 |
139 | #define IVTV_ENC_STREAM_TYPE_YUV 1 | 81 | #define IVTV_ENC_STREAM_TYPE_YUV 1 |
@@ -146,70 +88,8 @@ extern const u32 yuv_offset[4]; | |||
146 | #define IVTV_DEC_STREAM_TYPE_YUV 8 | 88 | #define IVTV_DEC_STREAM_TYPE_YUV 8 |
147 | #define IVTV_MAX_STREAMS 9 | 89 | #define IVTV_MAX_STREAMS 9 |
148 | 90 | ||
149 | #define IVTV_V4L2_DEC_MPG_OFFSET 16 /* offset from 0 to register decoder mpg v4l2 minors on */ | ||
150 | #define IVTV_V4L2_ENC_PCM_OFFSET 24 /* offset from 0 to register pcm v4l2 minors on */ | ||
151 | #define IVTV_V4L2_ENC_YUV_OFFSET 32 /* offset from 0 to register yuv v4l2 minors on */ | ||
152 | #define IVTV_V4L2_DEC_YUV_OFFSET 48 /* offset from 0 to register decoder yuv v4l2 minors on */ | ||
153 | #define IVTV_V4L2_DEC_VBI_OFFSET 8 /* offset from 0 to register decoder vbi input v4l2 minors on */ | ||
154 | #define IVTV_V4L2_DEC_VOUT_OFFSET 16 /* offset from 0 to register vbi output v4l2 minors on */ | ||
155 | |||
156 | #define IVTV_ENC_MEM_START 0x00000000 | ||
157 | #define IVTV_DEC_MEM_START 0x01000000 | ||
158 | |||
159 | /* system vendor and device IDs */ | ||
160 | #define PCI_VENDOR_ID_ICOMP 0x4444 | ||
161 | #define PCI_DEVICE_ID_IVTV15 0x0803 | ||
162 | #define PCI_DEVICE_ID_IVTV16 0x0016 | ||
163 | |||
164 | /* subsystem vendor ID */ | ||
165 | #define IVTV_PCI_ID_HAUPPAUGE 0x0070 | ||
166 | #define IVTV_PCI_ID_HAUPPAUGE_ALT1 0x0270 | ||
167 | #define IVTV_PCI_ID_HAUPPAUGE_ALT2 0x4070 | ||
168 | #define IVTV_PCI_ID_ADAPTEC 0x9005 | ||
169 | #define IVTV_PCI_ID_AVERMEDIA 0x1461 | ||
170 | #define IVTV_PCI_ID_YUAN1 0x12ab | ||
171 | #define IVTV_PCI_ID_YUAN2 0xff01 | ||
172 | #define IVTV_PCI_ID_YUAN3 0xffab | ||
173 | #define IVTV_PCI_ID_YUAN4 0xfbab | ||
174 | #define IVTV_PCI_ID_DIAMONDMM 0xff92 | ||
175 | #define IVTV_PCI_ID_IODATA 0x10fc | ||
176 | #define IVTV_PCI_ID_MELCO 0x1154 | ||
177 | #define IVTV_PCI_ID_GOTVIEW1 0xffac | ||
178 | #define IVTV_PCI_ID_GOTVIEW2 0xffad | ||
179 | |||
180 | /* Decoder Buffer hardware size on Chip */ | ||
181 | #define IVTV_DEC_MAX_BUF 0x00100000 /* max bytes in decoder buffer */ | ||
182 | #define IVTV_DEC_MIN_BUF 0x00010000 /* min bytes in dec buffer */ | ||
183 | |||
184 | /* ======================================================================== */ | ||
185 | /* ========================== START USER SETTABLE DMA VARIABLES =========== */ | ||
186 | /* ======================================================================== */ | ||
187 | |||
188 | #define IVTV_DMA_SG_OSD_ENT (2883584/PAGE_SIZE) /* sg entities */ | 91 | #define IVTV_DMA_SG_OSD_ENT (2883584/PAGE_SIZE) /* sg entities */ |
189 | 92 | ||
190 | /* DMA Buffers, Default size in MB allocated */ | ||
191 | #define IVTV_DEFAULT_ENC_MPG_BUFFERS 4 | ||
192 | #define IVTV_DEFAULT_ENC_YUV_BUFFERS 2 | ||
193 | #define IVTV_DEFAULT_ENC_VBI_BUFFERS 1 | ||
194 | #define IVTV_DEFAULT_ENC_PCM_BUFFERS 1 | ||
195 | #define IVTV_DEFAULT_DEC_MPG_BUFFERS 1 | ||
196 | #define IVTV_DEFAULT_DEC_YUV_BUFFERS 1 | ||
197 | #define IVTV_DEFAULT_DEC_VBI_BUFFERS 1 | ||
198 | |||
199 | /* ======================================================================== */ | ||
200 | /* ========================== END USER SETTABLE DMA VARIABLES ============= */ | ||
201 | /* ======================================================================== */ | ||
202 | |||
203 | /* Decoder Status Register */ | ||
204 | #define IVTV_DMA_ERR_LIST 0x00000010 | ||
205 | #define IVTV_DMA_ERR_WRITE 0x00000008 | ||
206 | #define IVTV_DMA_ERR_READ 0x00000004 | ||
207 | #define IVTV_DMA_SUCCESS_WRITE 0x00000002 | ||
208 | #define IVTV_DMA_SUCCESS_READ 0x00000001 | ||
209 | #define IVTV_DMA_READ_ERR (IVTV_DMA_ERR_LIST | IVTV_DMA_ERR_READ) | ||
210 | #define IVTV_DMA_WRITE_ERR (IVTV_DMA_ERR_LIST | IVTV_DMA_ERR_WRITE) | ||
211 | #define IVTV_DMA_ERR (IVTV_DMA_ERR_LIST | IVTV_DMA_ERR_WRITE | IVTV_DMA_ERR_READ) | ||
212 | |||
213 | /* DMA Registers */ | 93 | /* DMA Registers */ |
214 | #define IVTV_REG_DMAXFER (0x0000) | 94 | #define IVTV_REG_DMAXFER (0x0000) |
215 | #define IVTV_REG_DMASTATUS (0x0004) | 95 | #define IVTV_REG_DMASTATUS (0x0004) |
@@ -232,44 +112,24 @@ extern const u32 yuv_offset[4]; | |||
232 | #define IVTV_REG_VPU (0x9058) | 112 | #define IVTV_REG_VPU (0x9058) |
233 | #define IVTV_REG_APU (0xA064) | 113 | #define IVTV_REG_APU (0xA064) |
234 | 114 | ||
235 | #define IVTV_IRQ_ENC_START_CAP (0x1 << 31) | ||
236 | #define IVTV_IRQ_ENC_EOS (0x1 << 30) | ||
237 | #define IVTV_IRQ_ENC_VBI_CAP (0x1 << 29) | ||
238 | #define IVTV_IRQ_ENC_VIM_RST (0x1 << 28) | ||
239 | #define IVTV_IRQ_ENC_DMA_COMPLETE (0x1 << 27) | ||
240 | #define IVTV_IRQ_ENC_PIO_COMPLETE (0x1 << 25) | ||
241 | #define IVTV_IRQ_DEC_AUD_MODE_CHG (0x1 << 24) | ||
242 | #define IVTV_IRQ_DEC_DATA_REQ (0x1 << 22) | ||
243 | #define IVTV_IRQ_DEC_DMA_COMPLETE (0x1 << 20) | ||
244 | #define IVTV_IRQ_DEC_VBI_RE_INSERT (0x1 << 19) | ||
245 | #define IVTV_IRQ_DMA_ERR (0x1 << 18) | ||
246 | #define IVTV_IRQ_DMA_WRITE (0x1 << 17) | ||
247 | #define IVTV_IRQ_DMA_READ (0x1 << 16) | ||
248 | #define IVTV_IRQ_DEC_VSYNC (0x1 << 10) | ||
249 | |||
250 | /* IRQ Masks */ | ||
251 | #define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|\ | ||
252 | IVTV_IRQ_DMA_READ|IVTV_IRQ_ENC_PIO_COMPLETE) | ||
253 | |||
254 | #define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS) | ||
255 | #define IVTV_IRQ_MASK_DECODE (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG) | ||
256 | |||
257 | /* i2c stuff */ | 115 | /* i2c stuff */ |
258 | #define I2C_CLIENTS_MAX 16 | 116 | #define I2C_CLIENTS_MAX 16 |
259 | 117 | ||
260 | /* debugging */ | 118 | /* debugging */ |
119 | extern int ivtv_debug; | ||
261 | 120 | ||
262 | #define IVTV_DBGFLG_WARN (1 << 0) | 121 | #define IVTV_DBGFLG_WARN (1 << 0) |
263 | #define IVTV_DBGFLG_INFO (1 << 1) | 122 | #define IVTV_DBGFLG_INFO (1 << 1) |
264 | #define IVTV_DBGFLG_API (1 << 2) | 123 | #define IVTV_DBGFLG_MB (1 << 2) |
265 | #define IVTV_DBGFLG_DMA (1 << 3) | 124 | #define IVTV_DBGFLG_IOCTL (1 << 3) |
266 | #define IVTV_DBGFLG_IOCTL (1 << 4) | 125 | #define IVTV_DBGFLG_FILE (1 << 4) |
267 | #define IVTV_DBGFLG_I2C (1 << 5) | 126 | #define IVTV_DBGFLG_DMA (1 << 5) |
268 | #define IVTV_DBGFLG_IRQ (1 << 6) | 127 | #define IVTV_DBGFLG_IRQ (1 << 6) |
269 | #define IVTV_DBGFLG_DEC (1 << 7) | 128 | #define IVTV_DBGFLG_DEC (1 << 7) |
270 | #define IVTV_DBGFLG_YUV (1 << 8) | 129 | #define IVTV_DBGFLG_YUV (1 << 8) |
130 | #define IVTV_DBGFLG_I2C (1 << 9) | ||
271 | /* Flag to turn on high volume debugging */ | 131 | /* Flag to turn on high volume debugging */ |
272 | #define IVTV_DBGFLG_HIGHVOL (1 << 9) | 132 | #define IVTV_DBGFLG_HIGHVOL (1 << 10) |
273 | 133 | ||
274 | /* NOTE: extra space before comma in 'itv->num , ## args' is required for | 134 | /* NOTE: extra space before comma in 'itv->num , ## args' is required for |
275 | gcc-2.95, otherwise it won't compile. */ | 135 | gcc-2.95, otherwise it won't compile. */ |
@@ -278,58 +138,37 @@ extern const u32 yuv_offset[4]; | |||
278 | if ((x) & ivtv_debug) \ | 138 | if ((x) & ivtv_debug) \ |
279 | printk(KERN_INFO "ivtv%d " type ": " fmt, itv->num , ## args); \ | 139 | printk(KERN_INFO "ivtv%d " type ": " fmt, itv->num , ## args); \ |
280 | } while (0) | 140 | } while (0) |
281 | #define IVTV_DEBUG_WARN(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_WARN, "warning", fmt , ## args) | 141 | #define IVTV_DEBUG_WARN(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_WARN, "warn", fmt , ## args) |
282 | #define IVTV_DEBUG_INFO(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_INFO, "info",fmt , ## args) | 142 | #define IVTV_DEBUG_INFO(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_INFO, "info", fmt , ## args) |
283 | #define IVTV_DEBUG_API(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_API, "api", fmt , ## args) | 143 | #define IVTV_DEBUG_MB(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_MB, "mb", fmt , ## args) |
284 | #define IVTV_DEBUG_DMA(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_DMA, "dma", fmt , ## args) | 144 | #define IVTV_DEBUG_DMA(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_DMA, "dma", fmt , ## args) |
285 | #define IVTV_DEBUG_IOCTL(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args) | 145 | #define IVTV_DEBUG_IOCTL(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args) |
286 | #define IVTV_DEBUG_I2C(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_I2C, "i2c", fmt , ## args) | 146 | #define IVTV_DEBUG_FILE(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_FILE, "file", fmt , ## args) |
287 | #define IVTV_DEBUG_IRQ(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_IRQ, "irq", fmt , ## args) | 147 | #define IVTV_DEBUG_I2C(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_I2C, "i2c", fmt , ## args) |
288 | #define IVTV_DEBUG_DEC(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_DEC, "dec", fmt , ## args) | 148 | #define IVTV_DEBUG_IRQ(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_IRQ, "irq", fmt , ## args) |
289 | #define IVTV_DEBUG_YUV(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) | 149 | #define IVTV_DEBUG_DEC(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_DEC, "dec", fmt , ## args) |
150 | #define IVTV_DEBUG_YUV(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) | ||
290 | 151 | ||
291 | #define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \ | 152 | #define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \ |
292 | do { \ | 153 | do { \ |
293 | if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL)) \ | 154 | if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL)) \ |
294 | printk(KERN_INFO "ivtv%d " type ": " fmt, itv->num , ## args); \ | 155 | printk(KERN_INFO "ivtv%d " type ": " fmt, itv->num , ## args); \ |
295 | } while (0) | 156 | } while (0) |
296 | #define IVTV_DEBUG_HI_WARN(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_WARN, "warning", fmt , ## args) | 157 | #define IVTV_DEBUG_HI_WARN(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_WARN, "warn", fmt , ## args) |
297 | #define IVTV_DEBUG_HI_INFO(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_INFO, "info",fmt , ## args) | 158 | #define IVTV_DEBUG_HI_INFO(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_INFO, "info", fmt , ## args) |
298 | #define IVTV_DEBUG_HI_API(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_API, "api", fmt , ## args) | 159 | #define IVTV_DEBUG_HI_MB(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_MB, "mb", fmt , ## args) |
299 | #define IVTV_DEBUG_HI_DMA(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DMA, "dma", fmt , ## args) | 160 | #define IVTV_DEBUG_HI_DMA(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DMA, "dma", fmt , ## args) |
300 | #define IVTV_DEBUG_HI_IOCTL(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args) | 161 | #define IVTV_DEBUG_HI_IOCTL(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args) |
301 | #define IVTV_DEBUG_HI_I2C(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_I2C, "i2c", fmt , ## args) | 162 | #define IVTV_DEBUG_HI_FILE(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_FILE, "file", fmt , ## args) |
302 | #define IVTV_DEBUG_HI_IRQ(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IRQ, "irq", fmt , ## args) | 163 | #define IVTV_DEBUG_HI_I2C(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_I2C, "i2c", fmt , ## args) |
303 | #define IVTV_DEBUG_HI_DEC(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DEC, "dec", fmt , ## args) | 164 | #define IVTV_DEBUG_HI_IRQ(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IRQ, "irq", fmt , ## args) |
304 | #define IVTV_DEBUG_HI_YUV(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) | 165 | #define IVTV_DEBUG_HI_DEC(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DEC, "dec", fmt , ## args) |
305 | 166 | #define IVTV_DEBUG_HI_YUV(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) | |
306 | #define IVTV_FB_DEBUG(x, type, fmt, args...) \ | ||
307 | do { \ | ||
308 | if ((x) & ivtv_debug) \ | ||
309 | printk(KERN_INFO "ivtv%d-fb " type ": " fmt, itv->num , ## args); \ | ||
310 | } while (0) | ||
311 | #define IVTV_FB_DEBUG_WARN(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_WARN, "warning", fmt , ## args) | ||
312 | #define IVTV_FB_DEBUG_INFO(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_INFO, "info", fmt , ## args) | ||
313 | #define IVTV_FB_DEBUG_API(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_API, "api", fmt , ## args) | ||
314 | #define IVTV_FB_DEBUG_DMA(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_DMA, "dma", fmt , ## args) | ||
315 | #define IVTV_FB_DEBUG_IOCTL(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args) | ||
316 | #define IVTV_FB_DEBUG_I2C(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_I2C, "i2c", fmt , ## args) | ||
317 | #define IVTV_FB_DEBUG_IRQ(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_IRQ, "irq", fmt , ## args) | ||
318 | #define IVTV_FB_DEBUG_DEC(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_DEC, "dec", fmt , ## args) | ||
319 | #define IVTV_FB_DEBUG_YUV(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) | ||
320 | 167 | ||
321 | /* Standard kernel messages */ | 168 | /* Standard kernel messages */ |
322 | #define IVTV_ERR(fmt, args...) printk(KERN_ERR "ivtv%d: " fmt, itv->num , ## args) | 169 | #define IVTV_ERR(fmt, args...) printk(KERN_ERR "ivtv%d: " fmt, itv->num , ## args) |
323 | #define IVTV_WARN(fmt, args...) printk(KERN_WARNING "ivtv%d: " fmt, itv->num , ## args) | 170 | #define IVTV_WARN(fmt, args...) printk(KERN_WARNING "ivtv%d: " fmt, itv->num , ## args) |
324 | #define IVTV_INFO(fmt, args...) printk(KERN_INFO "ivtv%d: " fmt, itv->num , ## args) | 171 | #define IVTV_INFO(fmt, args...) printk(KERN_INFO "ivtv%d: " fmt, itv->num , ## args) |
325 | #define IVTV_FB_ERR(fmt, args...) printk(KERN_ERR "ivtv%d-fb: " fmt, itv->num , ## args) | ||
326 | #define IVTV_FB_WARN(fmt, args...) printk(KERN_WARNING "ivtv%d-fb: " fmt, itv->num , ## args) | ||
327 | #define IVTV_FB_INFO(fmt, args...) printk(KERN_INFO "ivtv%d-fb: " fmt, itv->num , ## args) | ||
328 | |||
329 | /* Values for IVTV_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */ | ||
330 | #define MPEG_FRAME_TYPE_IFRAME 1 | ||
331 | #define MPEG_FRAME_TYPE_IFRAME_PFRAME 3 | ||
332 | #define MPEG_FRAME_TYPE_ALL 7 | ||
333 | 172 | ||
334 | /* output modes (cx23415 only) */ | 173 | /* output modes (cx23415 only) */ |
335 | #define OUT_NONE 0 | 174 | #define OUT_NONE 0 |
@@ -340,22 +179,14 @@ extern const u32 yuv_offset[4]; | |||
340 | 179 | ||
341 | #define IVTV_MAX_PGM_INDEX (400) | 180 | #define IVTV_MAX_PGM_INDEX (400) |
342 | 181 | ||
343 | extern int ivtv_debug; | ||
344 | |||
345 | |||
346 | struct ivtv_options { | 182 | struct ivtv_options { |
347 | int megabytes[IVTV_MAX_STREAMS]; /* Size in megabytes of each stream */ | 183 | int kilobytes[IVTV_MAX_STREAMS]; /* size in kilobytes of each stream */ |
348 | int cardtype; /* force card type on load */ | 184 | int cardtype; /* force card type on load */ |
349 | int tuner; /* set tuner on load */ | 185 | int tuner; /* set tuner on load */ |
350 | int radio; /* enable/disable radio */ | 186 | int radio; /* enable/disable radio */ |
351 | int newi2c; /* New I2C algorithm */ | 187 | int newi2c; /* new I2C algorithm */ |
352 | }; | 188 | }; |
353 | 189 | ||
354 | #define IVTV_MBOX_DMA_START 6 | ||
355 | #define IVTV_MBOX_DMA_END 8 | ||
356 | #define IVTV_MBOX_DMA 9 | ||
357 | #define IVTV_MBOX_FIELD_DISPLAYED 8 | ||
358 | |||
359 | /* ivtv-specific mailbox template */ | 190 | /* ivtv-specific mailbox template */ |
360 | struct ivtv_mailbox { | 191 | struct ivtv_mailbox { |
361 | u32 flags; | 192 | u32 flags; |
@@ -379,7 +210,7 @@ struct ivtv_mailbox_data { | |||
379 | }; | 210 | }; |
380 | 211 | ||
381 | /* per-buffer bit flags */ | 212 | /* per-buffer bit flags */ |
382 | #define IVTV_F_B_NEED_BUF_SWAP 0 /* this buffer should be byte swapped */ | 213 | #define IVTV_F_B_NEED_BUF_SWAP (1 << 0) /* this buffer should be byte swapped */ |
383 | 214 | ||
384 | /* per-stream, s_flags */ | 215 | /* per-stream, s_flags */ |
385 | #define IVTV_F_S_DMA_PENDING 0 /* this stream has pending DMA */ | 216 | #define IVTV_F_S_DMA_PENDING 0 /* this stream has pending DMA */ |
@@ -400,24 +231,25 @@ struct ivtv_mailbox_data { | |||
400 | #define IVTV_F_I_DMA 0 /* DMA in progress */ | 231 | #define IVTV_F_I_DMA 0 /* DMA in progress */ |
401 | #define IVTV_F_I_UDMA 1 /* UDMA in progress */ | 232 | #define IVTV_F_I_UDMA 1 /* UDMA in progress */ |
402 | #define IVTV_F_I_UDMA_PENDING 2 /* UDMA pending */ | 233 | #define IVTV_F_I_UDMA_PENDING 2 /* UDMA pending */ |
403 | #define IVTV_F_I_SPEED_CHANGE 3 /* A speed change is in progress */ | 234 | #define IVTV_F_I_SPEED_CHANGE 3 /* a speed change is in progress */ |
404 | #define IVTV_F_I_EOS 4 /* End of encoder stream reached */ | 235 | #define IVTV_F_I_EOS 4 /* end of encoder stream reached */ |
405 | #define IVTV_F_I_RADIO_USER 5 /* The radio tuner is selected */ | 236 | #define IVTV_F_I_RADIO_USER 5 /* the radio tuner is selected */ |
406 | #define IVTV_F_I_DIG_RST 6 /* Reset digitizer */ | 237 | #define IVTV_F_I_DIG_RST 6 /* reset digitizer */ |
407 | #define IVTV_F_I_DEC_YUV 7 /* YUV instead of MPG is being decoded */ | 238 | #define IVTV_F_I_DEC_YUV 7 /* YUV instead of MPG is being decoded */ |
408 | #define IVTV_F_I_ENC_VBI 8 /* VBI DMA */ | ||
409 | #define IVTV_F_I_UPDATE_CC 9 /* CC should be updated */ | 239 | #define IVTV_F_I_UPDATE_CC 9 /* CC should be updated */ |
410 | #define IVTV_F_I_UPDATE_WSS 10 /* WSS should be updated */ | 240 | #define IVTV_F_I_UPDATE_WSS 10 /* WSS should be updated */ |
411 | #define IVTV_F_I_UPDATE_VPS 11 /* VPS should be updated */ | 241 | #define IVTV_F_I_UPDATE_VPS 11 /* VPS should be updated */ |
412 | #define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */ | 242 | #define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */ |
413 | #define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */ | 243 | #define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */ |
414 | #define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */ | 244 | #define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */ |
415 | #define IVTV_F_I_HAVE_WORK 15 /* Used in the interrupt handler: there is work to be done */ | 245 | #define IVTV_F_I_HAVE_WORK 15 /* used in the interrupt handler: there is work to be done */ |
416 | #define IVTV_F_I_WORK_HANDLER_VBI 16 /* there is work to be done for VBI */ | 246 | #define IVTV_F_I_WORK_HANDLER_VBI 16 /* there is work to be done for VBI */ |
417 | #define IVTV_F_I_WORK_HANDLER_YUV 17 /* there is work to be done for YUV */ | 247 | #define IVTV_F_I_WORK_HANDLER_YUV 17 /* there is work to be done for YUV */ |
418 | #define IVTV_F_I_WORK_HANDLER_PIO 18 /* there is work to be done for PIO */ | 248 | #define IVTV_F_I_WORK_HANDLER_PIO 18 /* there is work to be done for PIO */ |
419 | #define IVTV_F_I_PIO 19 /* PIO in progress */ | 249 | #define IVTV_F_I_PIO 19 /* PIO in progress */ |
420 | #define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */ | 250 | #define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */ |
251 | #define IVTV_F_I_INITED 21 /* set after first open */ | ||
252 | #define IVTV_F_I_FAILED 22 /* set if first open failed */ | ||
421 | 253 | ||
422 | /* Event notifications */ | 254 | /* Event notifications */ |
423 | #define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ | 255 | #define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ |
@@ -426,7 +258,7 @@ struct ivtv_mailbox_data { | |||
426 | #define IVTV_F_I_EV_VSYNC_ENABLED 31 /* VSYNC event enabled */ | 258 | #define IVTV_F_I_EV_VSYNC_ENABLED 31 /* VSYNC event enabled */ |
427 | 259 | ||
428 | /* Scatter-Gather array element, used in DMA transfers */ | 260 | /* Scatter-Gather array element, used in DMA transfers */ |
429 | struct ivtv_SG_element { | 261 | struct ivtv_sg_element { |
430 | u32 src; | 262 | u32 src; |
431 | u32 dst; | 263 | u32 dst; |
432 | u32 size; | 264 | u32 size; |
@@ -436,9 +268,11 @@ struct ivtv_user_dma { | |||
436 | struct mutex lock; | 268 | struct mutex lock; |
437 | int page_count; | 269 | int page_count; |
438 | struct page *map[IVTV_DMA_SG_OSD_ENT]; | 270 | struct page *map[IVTV_DMA_SG_OSD_ENT]; |
271 | /* Needed when dealing with highmem userspace buffers */ | ||
272 | struct page *bouncemap[IVTV_DMA_SG_OSD_ENT]; | ||
439 | 273 | ||
440 | /* Base Dev SG Array for cx23415/6 */ | 274 | /* Base Dev SG Array for cx23415/6 */ |
441 | struct ivtv_SG_element SGarray[IVTV_DMA_SG_OSD_ENT]; | 275 | struct ivtv_sg_element SGarray[IVTV_DMA_SG_OSD_ENT]; |
442 | dma_addr_t SG_handle; | 276 | dma_addr_t SG_handle; |
443 | int SG_length; | 277 | int SG_length; |
444 | 278 | ||
@@ -458,21 +292,21 @@ struct ivtv_dma_page_info { | |||
458 | struct ivtv_buffer { | 292 | struct ivtv_buffer { |
459 | struct list_head list; | 293 | struct list_head list; |
460 | dma_addr_t dma_handle; | 294 | dma_addr_t dma_handle; |
461 | unsigned long b_flags; | 295 | unsigned short b_flags; |
296 | unsigned short dma_xfer_cnt; | ||
462 | char *buf; | 297 | char *buf; |
463 | |||
464 | u32 bytesused; | 298 | u32 bytesused; |
465 | u32 readpos; | 299 | u32 readpos; |
466 | }; | 300 | }; |
467 | 301 | ||
468 | struct ivtv_queue { | 302 | struct ivtv_queue { |
469 | struct list_head list; | 303 | struct list_head list; /* the list of buffers in this queue */ |
470 | u32 buffers; | 304 | u32 buffers; /* number of buffers in this queue */ |
471 | u32 length; | 305 | u32 length; /* total number of bytes of available buffer space */ |
472 | u32 bytesused; | 306 | u32 bytesused; /* total number of bytes used in this queue */ |
473 | }; | 307 | }; |
474 | 308 | ||
475 | struct ivtv; /* forward reference */ | 309 | struct ivtv; /* forward reference */ |
476 | 310 | ||
477 | struct ivtv_stream { | 311 | struct ivtv_stream { |
478 | /* These first four fields are always set, even if the stream | 312 | /* These first four fields are always set, even if the stream |
@@ -483,11 +317,13 @@ struct ivtv_stream { | |||
483 | int type; /* stream type */ | 317 | int type; /* stream type */ |
484 | 318 | ||
485 | u32 id; | 319 | u32 id; |
486 | spinlock_t qlock; /* locks access to the queues */ | 320 | spinlock_t qlock; /* locks access to the queues */ |
487 | unsigned long s_flags; /* status flags, see above */ | 321 | unsigned long s_flags; /* status flags, see above */ |
488 | int dma; /* can be PCI_DMA_TODEVICE, | 322 | int dma; /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */ |
489 | PCI_DMA_FROMDEVICE or | 323 | u32 pending_offset; |
490 | PCI_DMA_NONE */ | 324 | u32 pending_backup; |
325 | u64 pending_pts; | ||
326 | |||
491 | u32 dma_offset; | 327 | u32 dma_offset; |
492 | u32 dma_backup; | 328 | u32 dma_backup; |
493 | u64 dma_pts; | 329 | u64 dma_pts; |
@@ -508,47 +344,53 @@ struct ivtv_stream { | |||
508 | struct ivtv_queue q_dma; /* waiting for DMA */ | 344 | struct ivtv_queue q_dma; /* waiting for DMA */ |
509 | struct ivtv_queue q_predma; /* waiting for DMA */ | 345 | struct ivtv_queue q_predma; /* waiting for DMA */ |
510 | 346 | ||
347 | /* DMA xfer counter, buffers belonging to the same DMA | ||
348 | xfer will have the same dma_xfer_cnt. */ | ||
349 | u16 dma_xfer_cnt; | ||
350 | |||
511 | /* Base Dev SG Array for cx23415/6 */ | 351 | /* Base Dev SG Array for cx23415/6 */ |
512 | struct ivtv_SG_element *SGarray; | 352 | struct ivtv_sg_element *sg_pending; |
513 | struct ivtv_SG_element *PIOarray; | 353 | struct ivtv_sg_element *sg_processing; |
514 | dma_addr_t SG_handle; | 354 | struct ivtv_sg_element *sg_dma; |
515 | int SG_length; | 355 | dma_addr_t sg_handle; |
356 | int sg_pending_size; | ||
357 | int sg_processing_size; | ||
358 | int sg_processed; | ||
516 | 359 | ||
517 | /* SG List of Buffers */ | 360 | /* SG List of Buffers */ |
518 | struct scatterlist *SGlist; | 361 | struct scatterlist *SGlist; |
519 | }; | 362 | }; |
520 | 363 | ||
521 | struct ivtv_open_id { | 364 | struct ivtv_open_id { |
522 | u32 open_id; | 365 | u32 open_id; /* unique ID for this file descriptor */ |
523 | int type; | 366 | int type; /* stream type */ |
524 | enum v4l2_priority prio; | 367 | int yuv_frames; /* 1: started OUT_UDMA_YUV output mode */ |
368 | enum v4l2_priority prio; /* priority */ | ||
525 | struct ivtv *itv; | 369 | struct ivtv *itv; |
526 | }; | 370 | }; |
527 | 371 | ||
528 | #define IVTV_YUV_UPDATE_HORIZONTAL 0x01 | ||
529 | #define IVTV_YUV_UPDATE_VERTICAL 0x02 | ||
530 | |||
531 | struct yuv_frame_info | 372 | struct yuv_frame_info |
532 | { | 373 | { |
533 | u32 update; | 374 | u32 update; |
534 | int src_x; | 375 | s32 src_x; |
535 | int src_y; | 376 | s32 src_y; |
536 | unsigned int src_w; | 377 | u32 src_w; |
537 | unsigned int src_h; | 378 | u32 src_h; |
538 | int dst_x; | 379 | s32 dst_x; |
539 | int dst_y; | 380 | s32 dst_y; |
540 | unsigned int dst_w; | 381 | u32 dst_w; |
541 | unsigned int dst_h; | 382 | u32 dst_h; |
542 | int pan_x; | 383 | s32 pan_x; |
543 | int pan_y; | 384 | s32 pan_y; |
544 | u32 vis_w; | 385 | u32 vis_w; |
545 | u32 vis_h; | 386 | u32 vis_h; |
546 | u32 interlaced_y; | 387 | u32 interlaced_y; |
547 | u32 interlaced_uv; | 388 | u32 interlaced_uv; |
548 | int tru_x; | 389 | s32 tru_x; |
549 | u32 tru_w; | 390 | u32 tru_w; |
550 | u32 tru_h; | 391 | u32 tru_h; |
551 | u32 offset_y; | 392 | u32 offset_y; |
393 | s32 lace_mode; | ||
552 | }; | 394 | }; |
553 | 395 | ||
554 | #define IVTV_YUV_MODE_INTERLACED 0x00 | 396 | #define IVTV_YUV_MODE_INTERLACED 0x00 |
@@ -621,7 +463,6 @@ struct yuv_playback_info | |||
621 | int decode_height; | 463 | int decode_height; |
622 | 464 | ||
623 | int frame_interlaced; | 465 | int frame_interlaced; |
624 | int frame_interlaced_last; | ||
625 | 466 | ||
626 | int lace_mode; | 467 | int lace_mode; |
627 | int lace_threshold; | 468 | int lace_threshold; |
@@ -632,6 +473,11 @@ struct yuv_playback_info | |||
632 | 473 | ||
633 | u32 yuv_forced_update; | 474 | u32 yuv_forced_update; |
634 | int update_frame; | 475 | int update_frame; |
476 | |||
477 | int sync_field[4]; /* Field to sync on */ | ||
478 | int field_delay[4]; /* Flag to extend duration of previous frame */ | ||
479 | u8 fields_lapsed; /* Counter used when delaying a frame */ | ||
480 | |||
635 | struct yuv_frame_info new_frame_info[4]; | 481 | struct yuv_frame_info new_frame_info[4]; |
636 | struct yuv_frame_info old_frame_info; | 482 | struct yuv_frame_info old_frame_info; |
637 | struct yuv_frame_info old_frame_info_args; | 483 | struct yuv_frame_info old_frame_info_args; |
@@ -643,37 +489,61 @@ struct yuv_playback_info | |||
643 | #define IVTV_VBI_FRAMES 32 | 489 | #define IVTV_VBI_FRAMES 32 |
644 | 490 | ||
645 | /* VBI data */ | 491 | /* VBI data */ |
492 | struct vbi_cc { | ||
493 | u8 odd[2]; /* two-byte payload of odd field */ | ||
494 | u8 even[2]; /* two-byte payload of even field */; | ||
495 | }; | ||
496 | |||
497 | struct vbi_vps { | ||
498 | u8 data[5]; /* five-byte VPS payload */ | ||
499 | }; | ||
500 | |||
646 | struct vbi_info { | 501 | struct vbi_info { |
647 | u32 dec_start; | 502 | /* VBI general data, does not change during streaming */ |
648 | u32 enc_start, enc_size; | 503 | |
649 | int fpi; | 504 | u32 raw_decoder_line_size; /* raw VBI line size from digitizer */ |
650 | u32 frame; | 505 | u8 raw_decoder_sav_odd_field; /* raw VBI Start Active Video digitizer code of odd field */ |
651 | u32 dma_offset; | 506 | u8 raw_decoder_sav_even_field; /* raw VBI Start Active Video digitizer code of even field */ |
652 | u8 cc_data_odd[256]; | 507 | u32 sliced_decoder_line_size; /* sliced VBI line size from digitizer */ |
653 | u8 cc_data_even[256]; | 508 | u8 sliced_decoder_sav_odd_field; /* sliced VBI Start Active Video digitizer code of odd field */ |
654 | int cc_pos; | 509 | u8 sliced_decoder_sav_even_field; /* sliced VBI Start Active Video digitizer code of even field */ |
655 | u8 cc_no_update; | 510 | |
656 | u8 vps[5]; | 511 | u32 start[2]; /* start of first VBI line in the odd/even fields */ |
657 | u8 vps_found; | 512 | u32 count; /* number of VBI lines per field */ |
658 | int wss; | 513 | u32 raw_size; /* size of raw VBI line from the digitizer */ |
659 | u8 wss_found; | 514 | u32 sliced_size; /* size of sliced VBI line from the digitizer */ |
660 | u8 wss_no_update; | 515 | |
661 | u32 raw_decoder_line_size; | 516 | u32 dec_start; /* start in decoder memory of VBI re-insertion buffers */ |
662 | u8 raw_decoder_sav_odd_field; | 517 | u32 enc_start; /* start in encoder memory of VBI capture buffers */ |
663 | u8 raw_decoder_sav_even_field; | 518 | u32 enc_size; /* size of VBI capture area */ |
664 | u32 sliced_decoder_line_size; | 519 | int fpi; /* number of VBI frames per interrupt */ |
665 | u8 sliced_decoder_sav_odd_field; | 520 | |
666 | u8 sliced_decoder_sav_even_field; | 521 | struct v4l2_format in; /* current VBI capture format */ |
667 | struct v4l2_format in; | 522 | struct v4l2_sliced_vbi_format *sliced_in; /* convenience pointer to sliced struct in vbi.in union */ |
668 | /* convenience pointer to sliced struct in vbi_in union */ | 523 | int insert_mpeg; /* if non-zero, then embed VBI data in MPEG stream */ |
669 | struct v4l2_sliced_vbi_format *sliced_in; | 524 | |
670 | u32 service_set_in; | 525 | /* Raw VBI compatibility hack */ |
671 | int insert_mpeg; | 526 | |
672 | 527 | u32 frame; /* frame counter hack needed for backwards compatibility | |
673 | /* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines. | 528 | of old VBI software */ |
674 | One for /dev/vbi0 and one for /dev/vbi8 */ | 529 | |
675 | struct v4l2_sliced_vbi_data sliced_data[36]; | 530 | /* Sliced VBI output data */ |
676 | struct v4l2_sliced_vbi_data sliced_dec_data[36]; | 531 | |
532 | struct vbi_cc cc_payload[256]; /* sliced VBI CC payload array: it is an array to | ||
533 | prevent dropping CC data if they couldn't be | ||
534 | processed fast enough */ | ||
535 | int cc_payload_idx; /* index in cc_payload */ | ||
536 | u8 cc_missing_cnt; /* counts number of frames without CC for passthrough mode */ | ||
537 | int wss_payload; /* sliced VBI WSS payload */ | ||
538 | u8 wss_missing_cnt; /* counts number of frames without WSS for passthrough mode */ | ||
539 | struct vbi_vps vps_payload; /* sliced VBI VPS payload */ | ||
540 | |||
541 | /* Sliced VBI capture data */ | ||
542 | |||
543 | struct v4l2_sliced_vbi_data sliced_data[36]; /* sliced VBI storage for VBI encoder stream */ | ||
544 | struct v4l2_sliced_vbi_data sliced_dec_data[36];/* sliced VBI storage for VBI decoder stream */ | ||
545 | |||
546 | /* VBI Embedding data */ | ||
677 | 547 | ||
678 | /* Buffer for VBI data inserted into MPEG stream. | 548 | /* Buffer for VBI data inserted into MPEG stream. |
679 | The first byte is a dummy byte that's never used. | 549 | The first byte is a dummy byte that's never used. |
@@ -690,12 +560,9 @@ struct vbi_info { | |||
690 | This pointer array will allocate 2049 bytes to store each VBI frame. */ | 560 | This pointer array will allocate 2049 bytes to store each VBI frame. */ |
691 | u8 *sliced_mpeg_data[IVTV_VBI_FRAMES]; | 561 | u8 *sliced_mpeg_data[IVTV_VBI_FRAMES]; |
692 | u32 sliced_mpeg_size[IVTV_VBI_FRAMES]; | 562 | u32 sliced_mpeg_size[IVTV_VBI_FRAMES]; |
693 | struct ivtv_buffer sliced_mpeg_buf; | 563 | struct ivtv_buffer sliced_mpeg_buf; /* temporary buffer holding data from sliced_mpeg_data */ |
694 | u32 inserted_frame; | 564 | u32 inserted_frame; /* index in sliced_mpeg_size of next sliced data |
695 | 565 | to be inserted in the MPEG stream */ | |
696 | u32 start[2], count; | ||
697 | u32 raw_size; | ||
698 | u32 sliced_size; | ||
699 | }; | 566 | }; |
700 | 567 | ||
701 | /* forward declaration of struct defined in ivtv-cards.h */ | 568 | /* forward declaration of struct defined in ivtv-cards.h */ |
@@ -703,131 +570,132 @@ struct ivtv_card; | |||
703 | 570 | ||
704 | /* Struct to hold info about ivtv cards */ | 571 | /* Struct to hold info about ivtv cards */ |
705 | struct ivtv { | 572 | struct ivtv { |
706 | int num; /* board number, -1 during init! */ | 573 | /* General fixed card data */ |
707 | char name[8]; /* board name for printk and interrupts (e.g. 'ivtv0') */ | 574 | int num; /* board number, -1 during init! */ |
708 | struct pci_dev *dev; /* PCI device */ | 575 | char name[8]; /* board name for printk and interrupts (e.g. 'ivtv0') */ |
576 | struct pci_dev *dev; /* PCI device */ | ||
709 | const struct ivtv_card *card; /* card information */ | 577 | const struct ivtv_card *card; /* card information */ |
710 | const char *card_name; /* full name of the card */ | 578 | const char *card_name; /* full name of the card */ |
711 | u8 has_cx23415; /* 1 if it is a cx23415 based card, 0 for cx23416 */ | 579 | u8 has_cx23415; /* 1 if it is a cx23415 based card, 0 for cx23416 */ |
712 | u8 is_50hz; | 580 | u8 pvr150_workaround; /* 1 if the cx25840 needs to workaround a PVR150 bug */ |
713 | u8 is_60hz; | 581 | u8 nof_inputs; /* number of video inputs */ |
714 | u8 is_out_50hz; | 582 | u8 nof_audio_inputs; /* number of audio inputs */ |
715 | u8 is_out_60hz; | 583 | u32 v4l2_cap; /* V4L2 capabilities of card */ |
716 | u8 pvr150_workaround; /* 1 if the cx25840 needs to workaround a PVR150 bug */ | 584 | u32 hw_flags; /* hardware description of the board */ |
717 | u8 nof_inputs; /* number of video inputs */ | 585 | int tunerid; /* userspace tuner ID for experimental Xceive tuner support */ |
718 | u8 nof_audio_inputs; /* number of audio inputs */ | 586 | v4l2_std_id tuner_std; /* the norm of the card's tuner (fixed) */ |
719 | u32 v4l2_cap; /* V4L2 capabilities of card */ | 587 | /* controlling video decoder function */ |
720 | u32 hw_flags; /* Hardware description of the board */ | ||
721 | |||
722 | /* controlling Video decoder function */ | ||
723 | int (*video_dec_func)(struct ivtv *, unsigned int, void *); | 588 | int (*video_dec_func)(struct ivtv *, unsigned int, void *); |
589 | u32 base_addr; /* PCI resource base address */ | ||
590 | volatile void __iomem *enc_mem; /* pointer to mapped encoder memory */ | ||
591 | volatile void __iomem *dec_mem; /* pointer to mapped decoder memory */ | ||
592 | volatile void __iomem *reg_mem; /* pointer to mapped registers */ | ||
593 | struct ivtv_options options; /* user options */ | ||
594 | |||
595 | |||
596 | /* High-level state info */ | ||
597 | unsigned long i_flags; /* global ivtv flags */ | ||
598 | u8 is_50hz; /* 1 if the current capture standard is 50 Hz */ | ||
599 | u8 is_60hz /* 1 if the current capture standard is 60 Hz */; | ||
600 | u8 is_out_50hz /* 1 if the current TV output standard is 50 Hz */; | ||
601 | u8 is_out_60hz /* 1 if the current TV output standard is 60 Hz */; | ||
602 | int output_mode; /* decoder output mode: NONE, MPG, YUV, UDMA YUV, passthrough */ | ||
603 | u32 audio_input; /* current audio input */ | ||
604 | u32 active_input; /* current video input */ | ||
605 | u32 active_output; /* current video output */ | ||
606 | v4l2_std_id std; /* current capture TV standard */ | ||
607 | v4l2_std_id std_out; /* current TV output standard */ | ||
608 | u8 audio_stereo_mode; /* decoder setting how to handle stereo MPEG audio */ | ||
609 | u8 audio_bilingual_mode; /* decoder setting how to handle bilingual MPEG audio */ | ||
610 | struct cx2341x_mpeg_params params; /* current encoder parameters */ | ||
611 | |||
612 | |||
613 | /* Locking */ | ||
614 | spinlock_t lock; /* lock access to this struct */ | ||
615 | struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ | ||
616 | |||
617 | |||
618 | /* Streams */ | ||
619 | int stream_buf_size[IVTV_MAX_STREAMS]; /* stream buffer size */ | ||
620 | struct ivtv_stream streams[IVTV_MAX_STREAMS]; /* stream data */ | ||
621 | atomic_t capturing; /* count number of active capture streams */ | ||
622 | atomic_t decoding; /* count number of active decoding streams */ | ||
623 | |||
624 | |||
625 | /* Interrupts & DMA */ | ||
626 | u32 irqmask; /* active interrupts */ | ||
627 | u32 irq_rr_idx; /* round-robin stream index */ | ||
628 | struct workqueue_struct *irq_work_queues; /* workqueue for PIO/YUV/VBI actions */ | ||
629 | struct work_struct irq_work_queue; /* work entry */ | ||
630 | spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ | ||
631 | int cur_dma_stream; /* index of current stream doing DMA (-1 if none) */ | ||
632 | int cur_pio_stream; /* index of current stream doing PIO (-1 if none) */ | ||
633 | u32 dma_data_req_offset; /* store offset in decoder memory of current DMA request */ | ||
634 | u32 dma_data_req_size; /* store size of current DMA request */ | ||
635 | int dma_retries; /* current DMA retry attempt */ | ||
636 | struct ivtv_user_dma udma; /* user based DMA for OSD */ | ||
637 | struct timer_list dma_timer; /* timer used to catch unfinished DMAs */ | ||
638 | u32 last_vsync_field; /* last seen vsync field */ | ||
639 | wait_queue_head_t dma_waitq; /* wake up when the current DMA is finished */ | ||
640 | wait_queue_head_t eos_waitq; /* wake up when EOS arrives */ | ||
641 | wait_queue_head_t event_waitq; /* wake up when the next decoder event arrives */ | ||
642 | wait_queue_head_t vsync_waitq; /* wake up when the next decoder vsync arrives */ | ||
643 | |||
644 | |||
645 | /* Mailbox */ | ||
646 | struct ivtv_mailbox_data enc_mbox; /* encoder mailboxes */ | ||
647 | struct ivtv_mailbox_data dec_mbox; /* decoder mailboxes */ | ||
648 | struct ivtv_api_cache api_cache[256]; /* cached API commands */ | ||
649 | |||
650 | |||
651 | /* I2C */ | ||
652 | struct i2c_adapter i2c_adap; | ||
653 | struct i2c_algo_bit_data i2c_algo; | ||
654 | struct i2c_client i2c_client; | ||
655 | struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];/* pointers to all I2C clients */ | ||
656 | int i2c_state; /* i2c bit state */ | ||
657 | struct mutex i2c_bus_lock; /* lock i2c bus */ | ||
658 | |||
659 | |||
660 | /* Program Index information */ | ||
661 | u32 pgm_info_offset; /* start of pgm info in encoder memory */ | ||
662 | u32 pgm_info_num; /* number of elements in the pgm cyclic buffer in encoder memory */ | ||
663 | u32 pgm_info_write_idx; /* last index written by the card that was transferred to pgm_info[] */ | ||
664 | u32 pgm_info_read_idx; /* last index in pgm_info read by the application */ | ||
665 | struct v4l2_enc_idx_entry pgm_info[IVTV_MAX_PGM_INDEX]; /* filled from the pgm cyclic buffer on the card */ | ||
666 | |||
667 | |||
668 | /* Miscellaneous */ | ||
669 | u32 open_id; /* incremented each time an open occurs, is >= 1 */ | ||
670 | struct v4l2_prio_state prio; /* priority state */ | ||
671 | int search_pack_header; /* 1 if ivtv_copy_buf_to_user() is scanning for a pack header (0xba) */ | ||
672 | int speed; /* current playback speed setting */ | ||
673 | u8 speed_mute_audio; /* 1 if audio should be muted when fast forward */ | ||
674 | u64 mpg_data_received; /* number of bytes received from the MPEG stream */ | ||
675 | u64 vbi_data_inserted; /* number of VBI bytes inserted into the MPEG stream */ | ||
676 | u32 last_dec_timing[3]; /* cache last retrieved pts/scr/frame values */ | ||
677 | unsigned long dualwatch_jiffies;/* jiffies value of the previous dualwatch check */ | ||
678 | u16 dualwatch_stereo_mode; /* current detected dualwatch stereo mode */ | ||
679 | |||
680 | |||
681 | /* VBI state info */ | ||
682 | struct vbi_info vbi; /* VBI-specific data */ | ||
683 | |||
684 | |||
685 | /* YUV playback */ | ||
686 | struct yuv_playback_info yuv_info; /* YUV playback data */ | ||
724 | 687 | ||
725 | struct ivtv_options options; /* User options */ | ||
726 | int stream_buf_size[IVTV_MAX_STREAMS]; /* Stream buffer size */ | ||
727 | struct ivtv_stream streams[IVTV_MAX_STREAMS]; /* Stream data */ | ||
728 | int speed; | ||
729 | u8 speed_mute_audio; | ||
730 | unsigned long i_flags; /* global ivtv flags */ | ||
731 | atomic_t capturing; /* count number of active capture streams */ | ||
732 | atomic_t decoding; /* count number of active decoding streams */ | ||
733 | u32 irq_rr_idx; /* Round-robin stream index */ | ||
734 | int cur_dma_stream; /* index of stream doing DMA */ | ||
735 | int cur_pio_stream; /* index of stream doing PIO */ | ||
736 | u32 dma_data_req_offset; | ||
737 | u32 dma_data_req_size; | ||
738 | int output_mode; /* NONE, MPG, YUV, UDMA YUV, passthrough */ | ||
739 | spinlock_t lock; /* lock access to this struct */ | ||
740 | int search_pack_header; | ||
741 | |||
742 | spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ | ||
743 | struct mutex serialize_lock; /* lock used to serialize starting streams */ | ||
744 | |||
745 | /* User based DMA for OSD */ | ||
746 | struct ivtv_user_dma udma; | ||
747 | |||
748 | int open_id; /* incremented each time an open occurs, used as unique ID. | ||
749 | starts at 1, so 0 can be used as uninitialized value | ||
750 | in the stream->id. */ | ||
751 | |||
752 | u32 base_addr; | ||
753 | u32 irqmask; | ||
754 | |||
755 | struct v4l2_prio_state prio; | ||
756 | struct workqueue_struct *irq_work_queues; | ||
757 | struct work_struct irq_work_queue; | ||
758 | struct timer_list dma_timer; /* Timer used to catch unfinished DMAs */ | ||
759 | |||
760 | struct vbi_info vbi; | ||
761 | |||
762 | struct ivtv_mailbox_data enc_mbox; | ||
763 | struct ivtv_mailbox_data dec_mbox; | ||
764 | struct ivtv_api_cache api_cache[256]; /* Cached API Commands */ | ||
765 | |||
766 | u8 card_rev; | ||
767 | volatile void __iomem *enc_mem, *dec_mem, *reg_mem; | ||
768 | |||
769 | u32 pgm_info_offset; | ||
770 | u32 pgm_info_num; | ||
771 | u32 pgm_info_write_idx; | ||
772 | u32 pgm_info_read_idx; | ||
773 | struct v4l2_enc_idx_entry pgm_info[IVTV_MAX_PGM_INDEX]; | ||
774 | |||
775 | u64 mpg_data_received; | ||
776 | u64 vbi_data_inserted; | ||
777 | |||
778 | wait_queue_head_t cap_w; | ||
779 | /* when the next decoder event arrives this queue is woken up */ | ||
780 | wait_queue_head_t event_waitq; | ||
781 | /* when the next decoder vsync arrives this queue is woken up */ | ||
782 | wait_queue_head_t vsync_waitq; | ||
783 | /* when the current DMA is finished this queue is woken up */ | ||
784 | wait_queue_head_t dma_waitq; | ||
785 | 688 | ||
786 | /* OSD support */ | 689 | /* OSD support */ |
787 | unsigned long osd_video_pbase; | 690 | unsigned long osd_video_pbase; |
788 | int osd_global_alpha_state; /* 0=off : 1=on */ | 691 | int osd_global_alpha_state; /* 1 = global alpha is on */ |
789 | int osd_local_alpha_state; /* 0=off : 1=on */ | 692 | int osd_local_alpha_state; /* 1 = local alpha is on */ |
790 | int osd_color_key_state; /* 0=off : 1=on */ | 693 | int osd_chroma_key_state; /* 1 = chroma-keying is on */ |
791 | u8 osd_global_alpha; /* Current global alpha */ | 694 | u8 osd_global_alpha; /* current global alpha */ |
792 | u32 osd_color_key; /* Current color key */ | 695 | u32 osd_chroma_key; /* current chroma key */ |
793 | u32 osd_pixelformat; /* Current pixel format */ | 696 | struct v4l2_rect osd_rect; /* current OSD position and size */ |
794 | struct v4l2_rect osd_rect; /* Current OSD position and size */ | 697 | struct v4l2_rect main_rect; /* current Main window position and size */ |
795 | struct v4l2_rect main_rect; /* Current Main window position and size */ | 698 | struct osd_info *osd_info; /* ivtvfb private OSD info */ |
796 | |||
797 | u32 last_dec_timing[3]; /* Store last retrieved pts/scr/frame values */ | ||
798 | |||
799 | /* i2c */ | ||
800 | struct i2c_adapter i2c_adap; | ||
801 | struct i2c_algo_bit_data i2c_algo; | ||
802 | struct i2c_client i2c_client; | ||
803 | struct mutex i2c_bus_lock; | ||
804 | int i2c_state; | ||
805 | struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; | ||
806 | |||
807 | /* v4l2 and User settings */ | ||
808 | |||
809 | /* codec settings */ | ||
810 | struct cx2341x_mpeg_params params; | ||
811 | u32 audio_input; | ||
812 | u32 active_input; | ||
813 | u32 active_output; | ||
814 | v4l2_std_id std; | ||
815 | v4l2_std_id std_out; | ||
816 | v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */ | ||
817 | u8 audio_stereo_mode; | ||
818 | u8 audio_bilingual_mode; | ||
819 | |||
820 | /* dualwatch */ | ||
821 | unsigned long dualwatch_jiffies; | ||
822 | u16 dualwatch_stereo_mode; | ||
823 | |||
824 | /* Digitizer type */ | ||
825 | int digitizer; /* 0x00EF = saa7114 0x00FO = saa7115 0x0106 = mic */ | ||
826 | |||
827 | u32 lastVsyncFrame; | ||
828 | |||
829 | struct yuv_playback_info yuv_info; | ||
830 | struct osd_info *osd_info; | ||
831 | }; | 699 | }; |
832 | 700 | ||
833 | /* Globals */ | 701 | /* Globals */ |
@@ -858,6 +726,9 @@ int ivtv_waitq(wait_queue_head_t *waitq); | |||
858 | struct tveeprom; /* forward reference */ | 726 | struct tveeprom; /* forward reference */ |
859 | void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv); | 727 | void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv); |
860 | 728 | ||
729 | /* First-open initialization: load firmware, init cx25840, etc. */ | ||
730 | int ivtv_init_on_first_open(struct ivtv *itv); | ||
731 | |||
861 | /* This is a PCI post thing, where if the pci register is not read, then | 732 | /* This is a PCI post thing, where if the pci register is not read, then |
862 | the write doesn't always take effect right away. By reading back the | 733 | the write doesn't always take effect right away. By reading back the |
863 | register any pending PCI writes will be performed (in order), and so | 734 | register any pending PCI writes will be performed (in order), and so |
@@ -885,4 +756,4 @@ void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv); | |||
885 | #define write_dec_sync(val, addr) \ | 756 | #define write_dec_sync(val, addr) \ |
886 | do { write_dec(val, addr); read_dec(addr); } while (0) | 757 | do { write_dec(val, addr); read_dec(addr); } while (0) |
887 | 758 | ||
888 | #endif /* IVTV_DRIVER_H */ | 759 | #endif |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 66ea3cbc369c..da50fa4a72a5 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -27,10 +27,9 @@ | |||
27 | #include "ivtv-irq.h" | 27 | #include "ivtv-irq.h" |
28 | #include "ivtv-vbi.h" | 28 | #include "ivtv-vbi.h" |
29 | #include "ivtv-mailbox.h" | 29 | #include "ivtv-mailbox.h" |
30 | #include "ivtv-audio.h" | 30 | #include "ivtv-routing.h" |
31 | #include "ivtv-streams.h" | 31 | #include "ivtv-streams.h" |
32 | #include "ivtv-yuv.h" | 32 | #include "ivtv-yuv.h" |
33 | #include "ivtv-controls.h" | ||
34 | #include "ivtv-ioctl.h" | 33 | #include "ivtv-ioctl.h" |
35 | #include "ivtv-cards.h" | 34 | #include "ivtv-cards.h" |
36 | #include <media/saa7115.h> | 35 | #include <media/saa7115.h> |
@@ -247,8 +246,9 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, | |||
247 | /* do we have new data? */ | 246 | /* do we have new data? */ |
248 | buf = ivtv_dequeue(s, &s->q_full); | 247 | buf = ivtv_dequeue(s, &s->q_full); |
249 | if (buf) { | 248 | if (buf) { |
250 | if (!test_and_clear_bit(IVTV_F_B_NEED_BUF_SWAP, &buf->b_flags)) | 249 | if ((buf->b_flags & IVTV_F_B_NEED_BUF_SWAP) == 0) |
251 | return buf; | 250 | return buf; |
251 | buf->b_flags &= ~IVTV_F_B_NEED_BUF_SWAP; | ||
252 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG) | 252 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG) |
253 | /* byteswap MPG data */ | 253 | /* byteswap MPG data */ |
254 | ivtv_buf_swap(buf); | 254 | ivtv_buf_swap(buf); |
@@ -258,19 +258,19 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, | |||
258 | } | 258 | } |
259 | return buf; | 259 | return buf; |
260 | } | 260 | } |
261 | /* return if file was opened with O_NONBLOCK */ | ||
262 | if (non_block) { | ||
263 | *err = -EAGAIN; | ||
264 | return NULL; | ||
265 | } | ||
266 | 261 | ||
267 | /* return if end of stream */ | 262 | /* return if end of stream */ |
268 | if (s->type != IVTV_DEC_STREAM_TYPE_VBI && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { | 263 | if (s->type != IVTV_DEC_STREAM_TYPE_VBI && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { |
269 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | ||
270 | IVTV_DEBUG_INFO("EOS %s\n", s->name); | 264 | IVTV_DEBUG_INFO("EOS %s\n", s->name); |
271 | return NULL; | 265 | return NULL; |
272 | } | 266 | } |
273 | 267 | ||
268 | /* return if file was opened with O_NONBLOCK */ | ||
269 | if (non_block) { | ||
270 | *err = -EAGAIN; | ||
271 | return NULL; | ||
272 | } | ||
273 | |||
274 | /* wait for more data to arrive */ | 274 | /* wait for more data to arrive */ |
275 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); | 275 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); |
276 | /* New buffers might have become available before we were added to the waitqueue */ | 276 | /* New buffers might have become available before we were added to the waitqueue */ |
@@ -378,10 +378,20 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co | |||
378 | int rc; | 378 | int rc; |
379 | 379 | ||
380 | buf = ivtv_get_buffer(s, non_block, &rc); | 380 | buf = ivtv_get_buffer(s, non_block, &rc); |
381 | if (buf == NULL && rc == -EAGAIN && tot_written) | 381 | /* if there is no data available... */ |
382 | break; | 382 | if (buf == NULL) { |
383 | if (buf == NULL) | 383 | /* if we got data, then return that regardless */ |
384 | if (tot_written) | ||
385 | break; | ||
386 | /* EOS condition */ | ||
387 | if (rc == 0) { | ||
388 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | ||
389 | clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); | ||
390 | ivtv_release_stream(s); | ||
391 | } | ||
392 | /* set errno */ | ||
384 | return rc; | 393 | return rc; |
394 | } | ||
385 | rc = ivtv_copy_buf_to_user(s, buf, ubuf + tot_written, tot_count - tot_written); | 395 | rc = ivtv_copy_buf_to_user(s, buf, ubuf + tot_written, tot_count - tot_written); |
386 | if (buf != &itv->vbi.sliced_mpeg_buf) { | 396 | if (buf != &itv->vbi.sliced_mpeg_buf) { |
387 | ivtv_enqueue(s, buf, (buf->readpos == buf->bytesused) ? &s->q_free : &s->q_io); | 397 | ivtv_enqueue(s, buf, (buf->readpos == buf->bytesused) ? &s->q_free : &s->q_io); |
@@ -408,7 +418,7 @@ static ssize_t ivtv_read_pos(struct ivtv_stream *s, char __user *ubuf, size_t co | |||
408 | ssize_t rc = count ? ivtv_read(s, ubuf, count, non_block) : 0; | 418 | ssize_t rc = count ? ivtv_read(s, ubuf, count, non_block) : 0; |
409 | struct ivtv *itv = s->itv; | 419 | struct ivtv *itv = s->itv; |
410 | 420 | ||
411 | IVTV_DEBUG_HI_INFO("read %zd from %s, got %zd\n", count, s->name, rc); | 421 | IVTV_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc); |
412 | if (rc > 0) | 422 | if (rc > 0) |
413 | pos += rc; | 423 | pos += rc; |
414 | return rc; | 424 | return rc; |
@@ -499,9 +509,11 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_ | |||
499 | struct ivtv_stream *s = &itv->streams[id->type]; | 509 | struct ivtv_stream *s = &itv->streams[id->type]; |
500 | int rc; | 510 | int rc; |
501 | 511 | ||
502 | IVTV_DEBUG_HI_IOCTL("read %zd bytes from %s\n", count, s->name); | 512 | IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name); |
503 | 513 | ||
514 | mutex_lock(&itv->serialize_lock); | ||
504 | rc = ivtv_start_capture(id); | 515 | rc = ivtv_start_capture(id); |
516 | mutex_unlock(&itv->serialize_lock); | ||
505 | if (rc) | 517 | if (rc) |
506 | return rc; | 518 | return rc; |
507 | return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); | 519 | return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); |
@@ -537,7 +549,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c | |||
537 | int rc; | 549 | int rc; |
538 | DEFINE_WAIT(wait); | 550 | DEFINE_WAIT(wait); |
539 | 551 | ||
540 | IVTV_DEBUG_HI_IOCTL("write %zd bytes to %s\n", count, s->name); | 552 | IVTV_DEBUG_HI_FILE("write %zd bytes to %s\n", count, s->name); |
541 | 553 | ||
542 | if (s->type != IVTV_DEC_STREAM_TYPE_MPG && | 554 | if (s->type != IVTV_DEC_STREAM_TYPE_MPG && |
543 | s->type != IVTV_DEC_STREAM_TYPE_YUV && | 555 | s->type != IVTV_DEC_STREAM_TYPE_YUV && |
@@ -551,8 +563,11 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c | |||
551 | 563 | ||
552 | /* This stream does not need to start any decoding */ | 564 | /* This stream does not need to start any decoding */ |
553 | if (s->type == IVTV_DEC_STREAM_TYPE_VOUT) { | 565 | if (s->type == IVTV_DEC_STREAM_TYPE_VOUT) { |
566 | int elems = count / sizeof(struct v4l2_sliced_vbi_data); | ||
567 | |||
554 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); | 568 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); |
555 | return ivtv_write_vbi(itv, user_buf, count); | 569 | ivtv_write_vbi(itv, (const struct v4l2_sliced_vbi_data *)user_buf, elems); |
570 | return elems * sizeof(struct v4l2_sliced_vbi_data); | ||
556 | } | 571 | } |
557 | 572 | ||
558 | mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV; | 573 | mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV; |
@@ -612,7 +627,9 @@ retry: | |||
612 | } | 627 | } |
613 | 628 | ||
614 | /* Start decoder (returns 0 if already started) */ | 629 | /* Start decoder (returns 0 if already started) */ |
630 | mutex_lock(&itv->serialize_lock); | ||
615 | rc = ivtv_start_decoding(id, itv->speed); | 631 | rc = ivtv_start_decoding(id, itv->speed); |
632 | mutex_unlock(&itv->serialize_lock); | ||
616 | if (rc) { | 633 | if (rc) { |
617 | IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name); | 634 | IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name); |
618 | 635 | ||
@@ -645,7 +662,7 @@ retry: | |||
645 | to transfer the rest. */ | 662 | to transfer the rest. */ |
646 | if (count && !(filp->f_flags & O_NONBLOCK)) | 663 | if (count && !(filp->f_flags & O_NONBLOCK)) |
647 | goto retry; | 664 | goto retry; |
648 | IVTV_DEBUG_HI_INFO("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused); | 665 | IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused); |
649 | return bytes_written; | 666 | return bytes_written; |
650 | } | 667 | } |
651 | 668 | ||
@@ -657,6 +674,7 @@ unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) | |||
657 | int res = 0; | 674 | int res = 0; |
658 | 675 | ||
659 | /* add stream's waitq to the poll list */ | 676 | /* add stream's waitq to the poll list */ |
677 | IVTV_DEBUG_HI_FILE("Decoder poll\n"); | ||
660 | poll_wait(filp, &s->waitq, wait); | 678 | poll_wait(filp, &s->waitq, wait); |
661 | 679 | ||
662 | set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); | 680 | set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); |
@@ -679,16 +697,21 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) | |||
679 | 697 | ||
680 | /* Start a capture if there is none */ | 698 | /* Start a capture if there is none */ |
681 | if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { | 699 | if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { |
682 | int rc = ivtv_start_capture(id); | 700 | int rc; |
683 | 701 | ||
702 | mutex_lock(&itv->serialize_lock); | ||
703 | rc = ivtv_start_capture(id); | ||
704 | mutex_unlock(&itv->serialize_lock); | ||
684 | if (rc) { | 705 | if (rc) { |
685 | IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", | 706 | IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", |
686 | s->name, rc); | 707 | s->name, rc); |
687 | return POLLERR; | 708 | return POLLERR; |
688 | } | 709 | } |
710 | IVTV_DEBUG_FILE("Encoder poll started capture\n"); | ||
689 | } | 711 | } |
690 | 712 | ||
691 | /* add stream's waitq to the poll list */ | 713 | /* add stream's waitq to the poll list */ |
714 | IVTV_DEBUG_HI_FILE("Encoder poll\n"); | ||
692 | poll_wait(filp, &s->waitq, wait); | 715 | poll_wait(filp, &s->waitq, wait); |
693 | 716 | ||
694 | if (eof || s->q_full.length) | 717 | if (eof || s->q_full.length) |
@@ -701,7 +724,7 @@ void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end) | |||
701 | struct ivtv *itv = id->itv; | 724 | struct ivtv *itv = id->itv; |
702 | struct ivtv_stream *s = &itv->streams[id->type]; | 725 | struct ivtv_stream *s = &itv->streams[id->type]; |
703 | 726 | ||
704 | IVTV_DEBUG_IOCTL("close() of %s\n", s->name); | 727 | IVTV_DEBUG_FILE("close() of %s\n", s->name); |
705 | 728 | ||
706 | /* 'Unclaim' this stream */ | 729 | /* 'Unclaim' this stream */ |
707 | 730 | ||
@@ -728,10 +751,11 @@ void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end) | |||
728 | ivtv_stop_v4l2_encode_stream(s, gop_end); | 751 | ivtv_stop_v4l2_encode_stream(s, gop_end); |
729 | } | 752 | } |
730 | } | 753 | } |
731 | clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); | 754 | if (!gop_end) { |
732 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | 755 | clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); |
733 | 756 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | |
734 | ivtv_release_stream(s); | 757 | ivtv_release_stream(s); |
758 | } | ||
735 | } | 759 | } |
736 | 760 | ||
737 | static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) | 761 | static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) |
@@ -739,13 +763,14 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) | |||
739 | struct ivtv *itv = id->itv; | 763 | struct ivtv *itv = id->itv; |
740 | struct ivtv_stream *s = &itv->streams[id->type]; | 764 | struct ivtv_stream *s = &itv->streams[id->type]; |
741 | 765 | ||
742 | IVTV_DEBUG_IOCTL("close() of %s\n", s->name); | 766 | IVTV_DEBUG_FILE("close() of %s\n", s->name); |
743 | 767 | ||
744 | /* Stop decoding */ | 768 | /* Stop decoding */ |
745 | if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { | 769 | if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { |
746 | IVTV_DEBUG_INFO("close stopping decode\n"); | 770 | IVTV_DEBUG_INFO("close stopping decode\n"); |
747 | 771 | ||
748 | ivtv_stop_v4l2_decode_stream(s, flags, pts); | 772 | ivtv_stop_v4l2_decode_stream(s, flags, pts); |
773 | itv->output_mode = OUT_NONE; | ||
749 | } | 774 | } |
750 | clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); | 775 | clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); |
751 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | 776 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); |
@@ -753,11 +778,7 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) | |||
753 | /* Restore registers we've changed & clean up any mess we've made */ | 778 | /* Restore registers we've changed & clean up any mess we've made */ |
754 | ivtv_yuv_close(itv); | 779 | ivtv_yuv_close(itv); |
755 | } | 780 | } |
756 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_YUV) | 781 | if (itv->output_mode == OUT_UDMA_YUV && id->yuv_frames) |
757 | itv->output_mode = OUT_NONE; | ||
758 | else if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_UDMA_YUV) | ||
759 | itv->output_mode = OUT_NONE; | ||
760 | else if (s->type == IVTV_DEC_STREAM_TYPE_MPG && itv->output_mode == OUT_MPG) | ||
761 | itv->output_mode = OUT_NONE; | 782 | itv->output_mode = OUT_NONE; |
762 | 783 | ||
763 | itv->speed = 0; | 784 | itv->speed = 0; |
@@ -771,7 +792,7 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) | |||
771 | struct ivtv *itv = id->itv; | 792 | struct ivtv *itv = id->itv; |
772 | struct ivtv_stream *s = &itv->streams[id->type]; | 793 | struct ivtv_stream *s = &itv->streams[id->type]; |
773 | 794 | ||
774 | IVTV_DEBUG_IOCTL("close() of %s\n", s->name); | 795 | IVTV_DEBUG_FILE("close %s\n", s->name); |
775 | 796 | ||
776 | v4l2_prio_close(&itv->prio, &id->prio); | 797 | v4l2_prio_close(&itv->prio, &id->prio); |
777 | 798 | ||
@@ -784,6 +805,7 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) | |||
784 | /* 'Unclaim' this stream */ | 805 | /* 'Unclaim' this stream */ |
785 | 806 | ||
786 | /* Stop radio */ | 807 | /* Stop radio */ |
808 | mutex_lock(&itv->serialize_lock); | ||
787 | if (id->type == IVTV_ENC_STREAM_TYPE_RAD) { | 809 | if (id->type == IVTV_ENC_STREAM_TYPE_RAD) { |
788 | /* Closing radio device, return to TV mode */ | 810 | /* Closing radio device, return to TV mode */ |
789 | ivtv_mute(itv); | 811 | ivtv_mute(itv); |
@@ -809,56 +831,35 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) | |||
809 | ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); | 831 | ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); |
810 | 832 | ||
811 | /* If all output streams are closed, and if the user doesn't have | 833 | /* If all output streams are closed, and if the user doesn't have |
812 | IVTV_DEC_STREAM_TYPE_VOUT open, then disable VBI on TV-out. */ | 834 | IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */ |
813 | if (itv->output_mode == OUT_NONE && !test_bit(IVTV_F_S_APPL_IO, &s_vout->s_flags)) { | 835 | if (itv->output_mode == OUT_NONE && !test_bit(IVTV_F_S_APPL_IO, &s_vout->s_flags)) { |
814 | /* disable VBI on TV-out */ | 836 | /* disable CC on TV-out */ |
815 | ivtv_disable_vbi(itv); | 837 | ivtv_disable_cc(itv); |
816 | } | 838 | } |
817 | } else { | 839 | } else { |
818 | ivtv_stop_capture(id, 0); | 840 | ivtv_stop_capture(id, 0); |
819 | } | 841 | } |
820 | kfree(id); | 842 | kfree(id); |
843 | mutex_unlock(&itv->serialize_lock); | ||
821 | return 0; | 844 | return 0; |
822 | } | 845 | } |
823 | 846 | ||
824 | int ivtv_v4l2_open(struct inode *inode, struct file *filp) | 847 | static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) |
825 | { | 848 | { |
826 | int x, y = 0; | 849 | struct ivtv *itv = s->itv; |
827 | struct ivtv_open_id *item; | 850 | struct ivtv_open_id *item; |
828 | struct ivtv *itv = NULL; | ||
829 | struct ivtv_stream *s = NULL; | ||
830 | int minor = iminor(inode); | ||
831 | |||
832 | /* Find which card this open was on */ | ||
833 | spin_lock(&ivtv_cards_lock); | ||
834 | for (x = 0; itv == NULL && x < ivtv_cards_active; x++) { | ||
835 | /* find out which stream this open was on */ | ||
836 | for (y = 0; y < IVTV_MAX_STREAMS; y++) { | ||
837 | s = &ivtv_cards[x]->streams[y]; | ||
838 | if (s->v4l2dev && s->v4l2dev->minor == minor) { | ||
839 | itv = ivtv_cards[x]; | ||
840 | break; | ||
841 | } | ||
842 | } | ||
843 | } | ||
844 | spin_unlock(&ivtv_cards_lock); | ||
845 | 851 | ||
846 | if (itv == NULL) { | 852 | IVTV_DEBUG_FILE("open %s\n", s->name); |
847 | /* Couldn't find a device registered | ||
848 | on that minor, shouldn't happen! */ | ||
849 | printk(KERN_WARNING "ivtv: No ivtv device found on minor %d\n", minor); | ||
850 | return -ENXIO; | ||
851 | } | ||
852 | 853 | ||
853 | if (y == IVTV_DEC_STREAM_TYPE_MPG && | 854 | if (s->type == IVTV_DEC_STREAM_TYPE_MPG && |
854 | test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags)) | 855 | test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags)) |
855 | return -EBUSY; | 856 | return -EBUSY; |
856 | 857 | ||
857 | if (y == IVTV_DEC_STREAM_TYPE_YUV && | 858 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && |
858 | test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_MPG].s_flags)) | 859 | test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_MPG].s_flags)) |
859 | return -EBUSY; | 860 | return -EBUSY; |
860 | 861 | ||
861 | if (y == IVTV_DEC_STREAM_TYPE_YUV) { | 862 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV) { |
862 | if (read_reg(0x82c) == 0) { | 863 | if (read_reg(0x82c) == 0) { |
863 | IVTV_ERR("Tried to open YUV output device but need to send data to mpeg decoder before it can be used\n"); | 864 | IVTV_ERR("Tried to open YUV output device but need to send data to mpeg decoder before it can be used\n"); |
864 | /* return -ENODEV; */ | 865 | /* return -ENODEV; */ |
@@ -873,7 +874,7 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) | |||
873 | return -ENOMEM; | 874 | return -ENOMEM; |
874 | } | 875 | } |
875 | item->itv = itv; | 876 | item->itv = itv; |
876 | item->type = y; | 877 | item->type = s->type; |
877 | v4l2_prio_open(&itv->prio, &item->prio); | 878 | v4l2_prio_open(&itv->prio, &item->prio); |
878 | 879 | ||
879 | item->open_id = itv->open_id++; | 880 | item->open_id = itv->open_id++; |
@@ -887,12 +888,20 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) | |||
887 | return -EBUSY; | 888 | return -EBUSY; |
888 | } | 889 | } |
889 | 890 | ||
891 | if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) { | ||
892 | if (atomic_read(&itv->capturing) > 0) { | ||
893 | /* switching to radio while capture is | ||
894 | in progress is not polite */ | ||
895 | kfree(item); | ||
896 | return -EBUSY; | ||
897 | } | ||
898 | } | ||
899 | /* Mark that the radio is being used. */ | ||
900 | set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); | ||
890 | /* We have the radio */ | 901 | /* We have the radio */ |
891 | ivtv_mute(itv); | 902 | ivtv_mute(itv); |
892 | /* Switch tuner to radio */ | 903 | /* Switch tuner to radio */ |
893 | ivtv_call_i2c_clients(itv, AUDC_SET_RADIO, NULL); | 904 | ivtv_call_i2c_clients(itv, AUDC_SET_RADIO, NULL); |
894 | /* Mark that the radio is being used. */ | ||
895 | set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); | ||
896 | /* Select the correct audio input (i.e. radio tuner) */ | 905 | /* Select the correct audio input (i.e. radio tuner) */ |
897 | ivtv_audio_set_io(itv); | 906 | ivtv_audio_set_io(itv); |
898 | if (itv->hw_flags & IVTV_HW_SAA711X) | 907 | if (itv->hw_flags & IVTV_HW_SAA711X) |
@@ -907,45 +916,65 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) | |||
907 | } | 916 | } |
908 | 917 | ||
909 | /* YUV or MPG Decoding Mode? */ | 918 | /* YUV or MPG Decoding Mode? */ |
910 | if (y == IVTV_DEC_STREAM_TYPE_MPG) | 919 | if (s->type == IVTV_DEC_STREAM_TYPE_MPG) |
911 | clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); | 920 | clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); |
912 | else if (y == IVTV_DEC_STREAM_TYPE_YUV) | 921 | else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) |
913 | { | ||
914 | set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); | 922 | set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); |
915 | } | ||
916 | |||
917 | return 0; | 923 | return 0; |
918 | } | 924 | } |
919 | 925 | ||
920 | void ivtv_mute(struct ivtv *itv) | 926 | int ivtv_v4l2_open(struct inode *inode, struct file *filp) |
921 | { | 927 | { |
922 | struct v4l2_control ctrl = { V4L2_CID_AUDIO_MUTE, 1 }; | 928 | int res, x, y = 0; |
929 | struct ivtv *itv = NULL; | ||
930 | struct ivtv_stream *s = NULL; | ||
931 | int minor = iminor(inode); | ||
932 | |||
933 | /* Find which card this open was on */ | ||
934 | spin_lock(&ivtv_cards_lock); | ||
935 | for (x = 0; itv == NULL && x < ivtv_cards_active; x++) { | ||
936 | /* find out which stream this open was on */ | ||
937 | for (y = 0; y < IVTV_MAX_STREAMS; y++) { | ||
938 | s = &ivtv_cards[x]->streams[y]; | ||
939 | if (s->v4l2dev && s->v4l2dev->minor == minor) { | ||
940 | itv = ivtv_cards[x]; | ||
941 | break; | ||
942 | } | ||
943 | } | ||
944 | } | ||
945 | spin_unlock(&ivtv_cards_lock); | ||
946 | |||
947 | if (itv == NULL) { | ||
948 | /* Couldn't find a device registered | ||
949 | on that minor, shouldn't happen! */ | ||
950 | IVTV_WARN("No ivtv device found on minor %d\n", minor); | ||
951 | return -ENXIO; | ||
952 | } | ||
923 | 953 | ||
924 | /* Mute sound to avoid pop */ | 954 | mutex_lock(&itv->serialize_lock); |
925 | ivtv_control_ioctls(itv, VIDIOC_S_CTRL, &ctrl); | 955 | if (ivtv_init_on_first_open(itv)) { |
956 | IVTV_ERR("Failed to initialize on minor %d\n", minor); | ||
957 | mutex_unlock(&itv->serialize_lock); | ||
958 | return -ENXIO; | ||
959 | } | ||
960 | res = ivtv_serialized_open(s, filp); | ||
961 | mutex_unlock(&itv->serialize_lock); | ||
962 | return res; | ||
963 | } | ||
926 | 964 | ||
965 | void ivtv_mute(struct ivtv *itv) | ||
966 | { | ||
927 | if (atomic_read(&itv->capturing)) | 967 | if (atomic_read(&itv->capturing)) |
928 | ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 1); | 968 | ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 1); |
929 | |||
930 | IVTV_DEBUG_INFO("Mute\n"); | 969 | IVTV_DEBUG_INFO("Mute\n"); |
931 | } | 970 | } |
932 | 971 | ||
933 | void ivtv_unmute(struct ivtv *itv) | 972 | void ivtv_unmute(struct ivtv *itv) |
934 | { | 973 | { |
935 | struct v4l2_control ctrl = { V4L2_CID_AUDIO_MUTE, 0 }; | ||
936 | |||
937 | /* initialize or refresh input */ | ||
938 | if (atomic_read(&itv->capturing) == 0) | ||
939 | ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); | ||
940 | |||
941 | ivtv_msleep_timeout(100, 0); | ||
942 | |||
943 | if (atomic_read(&itv->capturing)) { | 974 | if (atomic_read(&itv->capturing)) { |
975 | ivtv_msleep_timeout(100, 0); | ||
944 | ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12); | 976 | ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12); |
945 | ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 0); | 977 | ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 0); |
946 | } | 978 | } |
947 | |||
948 | /* Unmute */ | ||
949 | ivtv_control_ioctls(itv, VIDIOC_S_CTRL, &ctrl); | ||
950 | IVTV_DEBUG_INFO("Unmute\n"); | 979 | IVTV_DEBUG_INFO("Unmute\n"); |
951 | } | 980 | } |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.h b/drivers/media/video/ivtv/ivtv-fileops.h index 74a1745fabbc..2c8d5186c9c3 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.h +++ b/drivers/media/video/ivtv/ivtv-fileops.h | |||
@@ -18,6 +18,9 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef IVTV_FILEOPS_H | ||
22 | #define IVTV_FILEOPS_H | ||
23 | |||
21 | /* Testing/Debugging */ | 24 | /* Testing/Debugging */ |
22 | int ivtv_v4l2_open(struct inode *inode, struct file *filp); | 25 | int ivtv_v4l2_open(struct inode *inode, struct file *filp); |
23 | ssize_t ivtv_v4l2_read(struct file *filp, char __user *buf, size_t count, | 26 | ssize_t ivtv_v4l2_read(struct file *filp, char __user *buf, size_t count, |
@@ -42,3 +45,5 @@ int ivtv_claim_stream(struct ivtv_open_id *id, int type); | |||
42 | 45 | ||
43 | /* Release a previously claimed stream. */ | 46 | /* Release a previously claimed stream. */ |
44 | void ivtv_release_stream(struct ivtv_stream *s); | 47 | void ivtv_release_stream(struct ivtv_stream *s); |
48 | |||
49 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-firmware.h b/drivers/media/video/ivtv/ivtv-firmware.h index 8b2ffe658905..041ba94e65bc 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.h +++ b/drivers/media/video/ivtv/ivtv-firmware.h | |||
@@ -19,7 +19,12 @@ | |||
19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #ifndef IVTV_FIRMWARE_H | ||
23 | #define IVTV_FIRMWARE_H | ||
24 | |||
22 | int ivtv_firmware_init(struct ivtv *itv); | 25 | int ivtv_firmware_init(struct ivtv *itv); |
23 | void ivtv_firmware_versions(struct ivtv *itv); | 26 | void ivtv_firmware_versions(struct ivtv *itv); |
24 | void ivtv_halt_firmware(struct ivtv *itv); | 27 | void ivtv_halt_firmware(struct ivtv *itv); |
25 | void ivtv_init_mpeg_decoder(struct ivtv *itv); | 28 | void ivtv_init_mpeg_decoder(struct ivtv *itv); |
29 | |||
30 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c index 6a5a7aa66976..132fb5f71366 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.c +++ b/drivers/media/video/ivtv/ivtv-gpio.c | |||
@@ -122,30 +122,6 @@ void ivtv_reset_ir_gpio(struct ivtv *itv) | |||
122 | write_reg(curdir, IVTV_REG_GPIO_DIR); | 122 | write_reg(curdir, IVTV_REG_GPIO_DIR); |
123 | } | 123 | } |
124 | 124 | ||
125 | #ifdef HAVE_XC3028 | ||
126 | int ivtv_reset_tuner_gpio(enum v4l2_tuner_type mode, void *priv, int ptr) | ||
127 | { | ||
128 | int curdir, curout; | ||
129 | struct ivtv *itv = (struct ivtv *) priv; | ||
130 | |||
131 | if (itv->card->type != IVTV_CARD_PG600V2 || itv->options.tuner != TUNER_XCEIVE_XC3028) | ||
132 | return -EINVAL; | ||
133 | IVTV_INFO("Resetting tuner\n"); | ||
134 | curout = read_reg(IVTV_REG_GPIO_OUT); | ||
135 | curdir = read_reg(IVTV_REG_GPIO_DIR); | ||
136 | curdir |= (1 << 12); /* GPIO bit 12 */ | ||
137 | |||
138 | curout &= ~(1 << 12); | ||
139 | write_reg(curout, IVTV_REG_GPIO_OUT); | ||
140 | schedule_timeout_interruptible(msecs_to_jiffies(1)); | ||
141 | |||
142 | curout |= (1 << 12); | ||
143 | write_reg(curout, IVTV_REG_GPIO_OUT); | ||
144 | schedule_timeout_interruptible(msecs_to_jiffies(1)); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | #endif | ||
149 | 125 | ||
150 | void ivtv_gpio_init(struct ivtv *itv) | 126 | void ivtv_gpio_init(struct ivtv *itv) |
151 | { | 127 | { |
diff --git a/drivers/media/video/ivtv/ivtv-gpio.h b/drivers/media/video/ivtv/ivtv-gpio.h index c301d2a39346..964a265d91a9 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.h +++ b/drivers/media/video/ivtv/ivtv-gpio.h | |||
@@ -18,8 +18,13 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef IVTV_GPIO_H | ||
22 | #define IVTV_GPIO_H | ||
23 | |||
21 | /* GPIO stuff */ | 24 | /* GPIO stuff */ |
22 | void ivtv_gpio_init(struct ivtv *itv); | 25 | void ivtv_gpio_init(struct ivtv *itv); |
23 | void ivtv_reset_ir_gpio(struct ivtv *itv); | 26 | void ivtv_reset_ir_gpio(struct ivtv *itv); |
24 | int ivtv_reset_tuner_gpio(enum v4l2_tuner_type mode, void *priv, int ptr); | 27 | int ivtv_reset_tuner_gpio(void *dev, int cmd, int value); |
25 | int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg); | 28 | int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg); |
29 | |||
30 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index b3557435456d..285fca676a69 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c | |||
@@ -109,6 +109,7 @@ static const u8 hw_driverids[] = { | |||
109 | I2C_DRIVERID_UPD64083, | 109 | I2C_DRIVERID_UPD64083, |
110 | I2C_DRIVERID_SAA717X, | 110 | I2C_DRIVERID_SAA717X, |
111 | I2C_DRIVERID_WM8739, | 111 | I2C_DRIVERID_WM8739, |
112 | I2C_DRIVERID_VP27SMPX, | ||
112 | 0 /* IVTV_HW_GPIO dummy driver ID */ | 113 | 0 /* IVTV_HW_GPIO dummy driver ID */ |
113 | }; | 114 | }; |
114 | 115 | ||
@@ -128,6 +129,7 @@ static const char * const hw_drivernames[] = { | |||
128 | "upd64083", | 129 | "upd64083", |
129 | "saa717x", | 130 | "saa717x", |
130 | "wm8739", | 131 | "wm8739", |
132 | "vp27smpx", | ||
131 | "gpio", | 133 | "gpio", |
132 | }; | 134 | }; |
133 | 135 | ||
@@ -534,14 +536,13 @@ static struct i2c_adapter ivtv_i2c_adap_template = { | |||
534 | #endif | 536 | #endif |
535 | }; | 537 | }; |
536 | 538 | ||
537 | static struct i2c_algo_bit_data ivtv_i2c_algo_template = { | 539 | static const struct i2c_algo_bit_data ivtv_i2c_algo_template = { |
538 | NULL, /* ?? */ | 540 | .setsda = ivtv_setsda_old, |
539 | ivtv_setsda_old, /* setsda function */ | 541 | .setscl = ivtv_setscl_old, |
540 | ivtv_setscl_old, /* " */ | 542 | .getsda = ivtv_getsda_old, |
541 | ivtv_getsda_old, /* " */ | 543 | .getscl = ivtv_getscl_old, |
542 | ivtv_getscl_old, /* " */ | 544 | .udelay = 5, |
543 | 10, /* udelay */ | 545 | .timeout = 200, |
544 | 200 /* timeout */ | ||
545 | }; | 546 | }; |
546 | 547 | ||
547 | static struct i2c_client ivtv_i2c_client_template = { | 548 | static struct i2c_client ivtv_i2c_client_template = { |
diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/video/ivtv/ivtv-i2c.h index 5d210adb5c52..677c3292855e 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.h +++ b/drivers/media/video/ivtv/ivtv-i2c.h | |||
@@ -18,6 +18,9 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef IVTV_I2C_H | ||
22 | #define IVTV_I2C_H | ||
23 | |||
21 | int ivtv_cx25840(struct ivtv *itv, unsigned int cmd, void *arg); | 24 | int ivtv_cx25840(struct ivtv *itv, unsigned int cmd, void *arg); |
22 | int ivtv_saa7115(struct ivtv *itv, unsigned int cmd, void *arg); | 25 | int ivtv_saa7115(struct ivtv *itv, unsigned int cmd, void *arg); |
23 | int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg); | 26 | int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg); |
@@ -34,3 +37,5 @@ void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg); | |||
34 | /* init + register i2c algo-bit adapter */ | 37 | /* init + register i2c algo-bit adapter */ |
35 | int __devinit init_ivtv_i2c(struct ivtv *itv); | 38 | int __devinit init_ivtv_i2c(struct ivtv *itv); |
36 | void __devexit exit_ivtv_i2c(struct ivtv *itv); | 39 | void __devexit exit_ivtv_i2c(struct ivtv *itv); |
40 | |||
41 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index dfe0aedc60fd..206eee7542db 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -25,8 +25,7 @@ | |||
25 | #include "ivtv-queue.h" | 25 | #include "ivtv-queue.h" |
26 | #include "ivtv-fileops.h" | 26 | #include "ivtv-fileops.h" |
27 | #include "ivtv-vbi.h" | 27 | #include "ivtv-vbi.h" |
28 | #include "ivtv-audio.h" | 28 | #include "ivtv-routing.h" |
29 | #include "ivtv-video.h" | ||
30 | #include "ivtv-streams.h" | 29 | #include "ivtv-streams.h" |
31 | #include "ivtv-yuv.h" | 30 | #include "ivtv-yuv.h" |
32 | #include "ivtv-ioctl.h" | 31 | #include "ivtv-ioctl.h" |
@@ -164,7 +163,7 @@ void ivtv_set_osd_alpha(struct ivtv *itv) | |||
164 | { | 163 | { |
165 | ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3, | 164 | ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3, |
166 | itv->osd_global_alpha_state, itv->osd_global_alpha, !itv->osd_local_alpha_state); | 165 | itv->osd_global_alpha_state, itv->osd_global_alpha, !itv->osd_local_alpha_state); |
167 | ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, 2, itv->osd_color_key_state, itv->osd_color_key); | 166 | ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, 2, itv->osd_chroma_key_state, itv->osd_chroma_key); |
168 | } | 167 | } |
169 | 168 | ||
170 | int ivtv_set_speed(struct ivtv *itv, int speed) | 169 | int ivtv_set_speed(struct ivtv *itv, int speed) |
@@ -427,7 +426,7 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm | |||
427 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: | 426 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: |
428 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | 427 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
429 | return -EINVAL; | 428 | return -EINVAL; |
430 | fmt->fmt.win.chromakey = itv->osd_color_key; | 429 | fmt->fmt.win.chromakey = itv->osd_chroma_key; |
431 | fmt->fmt.win.global_alpha = itv->osd_global_alpha; | 430 | fmt->fmt.win.global_alpha = itv->osd_global_alpha; |
432 | break; | 431 | break; |
433 | 432 | ||
@@ -547,7 +546,7 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, | |||
547 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | 546 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
548 | return -EINVAL; | 547 | return -EINVAL; |
549 | if (set_fmt) { | 548 | if (set_fmt) { |
550 | itv->osd_color_key = fmt->fmt.win.chromakey; | 549 | itv->osd_chroma_key = fmt->fmt.win.chromakey; |
551 | itv->osd_global_alpha = fmt->fmt.win.global_alpha; | 550 | itv->osd_global_alpha = fmt->fmt.win.global_alpha; |
552 | ivtv_set_osd_alpha(itv); | 551 | ivtv_set_osd_alpha(itv); |
553 | } | 552 | } |
@@ -584,9 +583,7 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, | |||
584 | 583 | ||
585 | /* set raw VBI format */ | 584 | /* set raw VBI format */ |
586 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | 585 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { |
587 | if (set_fmt && streamtype == IVTV_ENC_STREAM_TYPE_VBI && | 586 | if (set_fmt && atomic_read(&itv->capturing) > 0) { |
588 | itv->vbi.sliced_in->service_set && | ||
589 | atomic_read(&itv->capturing) > 0) { | ||
590 | return -EBUSY; | 587 | return -EBUSY; |
591 | } | 588 | } |
592 | if (set_fmt) { | 589 | if (set_fmt) { |
@@ -624,7 +621,7 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, | |||
624 | return 0; | 621 | return 0; |
625 | if (set == 0) | 622 | if (set == 0) |
626 | return -EINVAL; | 623 | return -EINVAL; |
627 | if (atomic_read(&itv->capturing) > 0 && itv->vbi.sliced_in->service_set == 0) { | 624 | if (atomic_read(&itv->capturing) > 0) { |
628 | return -EBUSY; | 625 | return -EBUSY; |
629 | } | 626 | } |
630 | itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); | 627 | itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); |
@@ -677,13 +674,21 @@ static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
677 | case VIDIOC_INT_S_AUDIO_ROUTING: { | 674 | case VIDIOC_INT_S_AUDIO_ROUTING: { |
678 | struct v4l2_routing *route = arg; | 675 | struct v4l2_routing *route = arg; |
679 | 676 | ||
680 | ivtv_audio_set_route(itv, route); | 677 | ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route); |
681 | break; | 678 | break; |
682 | } | 679 | } |
683 | 680 | ||
684 | case VIDIOC_INT_RESET: | 681 | case VIDIOC_INT_RESET: { |
685 | ivtv_reset_ir_gpio(itv); | 682 | u32 val = *(u32 *)arg; |
683 | |||
684 | if ((val == 0 && itv->options.newi2c) || (val & 0x01)) { | ||
685 | ivtv_reset_ir_gpio(itv); | ||
686 | } | ||
687 | if (val & 0x02) { | ||
688 | itv->video_dec_func(itv, cmd, 0); | ||
689 | } | ||
686 | break; | 690 | break; |
691 | } | ||
687 | 692 | ||
688 | default: | 693 | default: |
689 | return -EINVAL; | 694 | return -EINVAL; |
@@ -694,6 +699,7 @@ static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
694 | int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg) | 699 | int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg) |
695 | { | 700 | { |
696 | struct ivtv_open_id *id = NULL; | 701 | struct ivtv_open_id *id = NULL; |
702 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
697 | 703 | ||
698 | if (filp) id = (struct ivtv_open_id *)filp->private_data; | 704 | if (filp) id = (struct ivtv_open_id *)filp->private_data; |
699 | 705 | ||
@@ -898,6 +904,9 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
898 | IVTV_DEBUG_INFO("Input unchanged\n"); | 904 | IVTV_DEBUG_INFO("Input unchanged\n"); |
899 | break; | 905 | break; |
900 | } | 906 | } |
907 | if (atomic_read(&itv->capturing) > 0) { | ||
908 | return -EBUSY; | ||
909 | } | ||
901 | IVTV_DEBUG_INFO("Changing input from %d to %d\n", | 910 | IVTV_DEBUG_INFO("Changing input from %d to %d\n", |
902 | itv->active_input, inp); | 911 | itv->active_input, inp); |
903 | 912 | ||
@@ -1127,12 +1136,14 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
1127 | memset(&enc->raw, 0, sizeof(enc->raw)); | 1136 | memset(&enc->raw, 0, sizeof(enc->raw)); |
1128 | switch (enc->cmd) { | 1137 | switch (enc->cmd) { |
1129 | case V4L2_ENC_CMD_START: | 1138 | case V4L2_ENC_CMD_START: |
1139 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n"); | ||
1130 | enc->flags = 0; | 1140 | enc->flags = 0; |
1131 | if (try) | 1141 | if (try) |
1132 | return 0; | 1142 | return 0; |
1133 | return ivtv_start_capture(id); | 1143 | return ivtv_start_capture(id); |
1134 | 1144 | ||
1135 | case V4L2_ENC_CMD_STOP: | 1145 | case V4L2_ENC_CMD_STOP: |
1146 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n"); | ||
1136 | enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END; | 1147 | enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END; |
1137 | if (try) | 1148 | if (try) |
1138 | return 0; | 1149 | return 0; |
@@ -1140,6 +1151,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
1140 | return 0; | 1151 | return 0; |
1141 | 1152 | ||
1142 | case V4L2_ENC_CMD_PAUSE: | 1153 | case V4L2_ENC_CMD_PAUSE: |
1154 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n"); | ||
1143 | enc->flags = 0; | 1155 | enc->flags = 0; |
1144 | if (try) | 1156 | if (try) |
1145 | return 0; | 1157 | return 0; |
@@ -1152,6 +1164,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
1152 | break; | 1164 | break; |
1153 | 1165 | ||
1154 | case V4L2_ENC_CMD_RESUME: | 1166 | case V4L2_ENC_CMD_RESUME: |
1167 | IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n"); | ||
1155 | enc->flags = 0; | 1168 | enc->flags = 0; |
1156 | if (try) | 1169 | if (try) |
1157 | return 0; | 1170 | return 0; |
@@ -1163,6 +1176,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
1163 | ivtv_unmute(itv); | 1176 | ivtv_unmute(itv); |
1164 | break; | 1177 | break; |
1165 | default: | 1178 | default: |
1179 | IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd); | ||
1166 | return -EINVAL; | 1180 | return -EINVAL; |
1167 | } | 1181 | } |
1168 | break; | 1182 | break; |
@@ -1170,22 +1184,58 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
1170 | 1184 | ||
1171 | case VIDIOC_G_FBUF: { | 1185 | case VIDIOC_G_FBUF: { |
1172 | struct v4l2_framebuffer *fb = arg; | 1186 | struct v4l2_framebuffer *fb = arg; |
1187 | int pixfmt; | ||
1188 | static u32 pixel_format[16] = { | ||
1189 | V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */ | ||
1190 | V4L2_PIX_FMT_RGB565, | ||
1191 | V4L2_PIX_FMT_RGB555, | ||
1192 | V4L2_PIX_FMT_RGB444, | ||
1193 | V4L2_PIX_FMT_RGB32, | ||
1194 | 0, | ||
1195 | 0, | ||
1196 | 0, | ||
1197 | V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */ | ||
1198 | V4L2_PIX_FMT_YUV565, | ||
1199 | V4L2_PIX_FMT_YUV555, | ||
1200 | V4L2_PIX_FMT_YUV444, | ||
1201 | V4L2_PIX_FMT_YUV32, | ||
1202 | 0, | ||
1203 | 0, | ||
1204 | 0, | ||
1205 | }; | ||
1173 | 1206 | ||
1174 | memset(fb, 0, sizeof(*fb)); | 1207 | memset(fb, 0, sizeof(*fb)); |
1175 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) | 1208 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) |
1176 | return -EINVAL; | 1209 | return -EINVAL; |
1177 | fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY | | 1210 | fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY | |
1178 | V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_GLOBAL_ALPHA; | 1211 | V4L2_FBUF_CAP_GLOBAL_ALPHA; |
1179 | fb->fmt.pixelformat = itv->osd_pixelformat; | 1212 | ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0); |
1213 | data[0] |= (read_reg(0x2a00) >> 7) & 0x40; | ||
1214 | pixfmt = (data[0] >> 3) & 0xf; | ||
1215 | fb->fmt.pixelformat = pixel_format[pixfmt]; | ||
1180 | fb->fmt.width = itv->osd_rect.width; | 1216 | fb->fmt.width = itv->osd_rect.width; |
1181 | fb->fmt.height = itv->osd_rect.height; | 1217 | fb->fmt.height = itv->osd_rect.height; |
1182 | fb->base = (void *)itv->osd_video_pbase; | 1218 | fb->base = (void *)itv->osd_video_pbase; |
1219 | if (itv->osd_chroma_key_state) | ||
1220 | fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY; | ||
1183 | if (itv->osd_global_alpha_state) | 1221 | if (itv->osd_global_alpha_state) |
1184 | fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; | 1222 | fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; |
1185 | if (itv->osd_local_alpha_state) | 1223 | pixfmt &= 7; |
1186 | fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; | 1224 | /* no local alpha for RGB565 or unknown formats */ |
1187 | if (itv->osd_color_key_state) | 1225 | if (pixfmt == 1 || pixfmt > 4) |
1188 | fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY; | 1226 | break; |
1227 | /* 16-bit formats have inverted local alpha */ | ||
1228 | if (pixfmt == 2 || pixfmt == 3) | ||
1229 | fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA; | ||
1230 | else | ||
1231 | fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA; | ||
1232 | if (itv->osd_local_alpha_state) { | ||
1233 | /* 16-bit formats have inverted local alpha */ | ||
1234 | if (pixfmt == 2 || pixfmt == 3) | ||
1235 | fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA; | ||
1236 | else | ||
1237 | fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; | ||
1238 | } | ||
1189 | break; | 1239 | break; |
1190 | } | 1240 | } |
1191 | 1241 | ||
@@ -1195,12 +1245,22 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
1195 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) | 1245 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) |
1196 | return -EINVAL; | 1246 | return -EINVAL; |
1197 | itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0; | 1247 | itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0; |
1198 | itv->osd_local_alpha_state = (fb->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) != 0; | 1248 | itv->osd_local_alpha_state = |
1199 | itv->osd_color_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; | 1249 | (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0; |
1250 | itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; | ||
1200 | ivtv_set_osd_alpha(itv); | 1251 | ivtv_set_osd_alpha(itv); |
1201 | break; | 1252 | break; |
1202 | } | 1253 | } |
1203 | 1254 | ||
1255 | case VIDIOC_OVERLAY: { | ||
1256 | int *on = arg; | ||
1257 | |||
1258 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) | ||
1259 | return -EINVAL; | ||
1260 | ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, *on != 0); | ||
1261 | break; | ||
1262 | } | ||
1263 | |||
1204 | case VIDIOC_LOG_STATUS: | 1264 | case VIDIOC_LOG_STATUS: |
1205 | { | 1265 | { |
1206 | int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT; | 1266 | int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT; |
@@ -1209,6 +1269,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
1209 | int i; | 1269 | int i; |
1210 | 1270 | ||
1211 | IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num); | 1271 | IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num); |
1272 | IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name); | ||
1212 | if (itv->hw_flags & IVTV_HW_TVEEPROM) { | 1273 | if (itv->hw_flags & IVTV_HW_TVEEPROM) { |
1213 | struct tveeprom tv; | 1274 | struct tveeprom tv; |
1214 | 1275 | ||
@@ -1217,32 +1278,72 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
1217 | ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL); | 1278 | ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL); |
1218 | ivtv_get_input(itv, itv->active_input, &vidin); | 1279 | ivtv_get_input(itv, itv->active_input, &vidin); |
1219 | ivtv_get_audio_input(itv, itv->audio_input, &audin); | 1280 | ivtv_get_audio_input(itv, itv->audio_input, &audin); |
1220 | IVTV_INFO("Video Input: %s\n", vidin.name); | 1281 | IVTV_INFO("Video Input: %s\n", vidin.name); |
1221 | IVTV_INFO("Audio Input: %s\n", audin.name); | 1282 | IVTV_INFO("Audio Input: %s%s\n", audin.name, |
1283 | (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : ""); | ||
1222 | if (has_output) { | 1284 | if (has_output) { |
1223 | struct v4l2_output vidout; | 1285 | struct v4l2_output vidout; |
1224 | struct v4l2_audioout audout; | 1286 | struct v4l2_audioout audout; |
1225 | int mode = itv->output_mode; | 1287 | int mode = itv->output_mode; |
1226 | static const char * const output_modes[] = { | 1288 | static const char * const output_modes[5] = { |
1227 | "None", | 1289 | "None", |
1228 | "MPEG Streaming", | 1290 | "MPEG Streaming", |
1229 | "YUV Streaming", | 1291 | "YUV Streaming", |
1230 | "YUV Frames", | 1292 | "YUV Frames", |
1231 | "Passthrough", | 1293 | "Passthrough", |
1232 | }; | 1294 | }; |
1295 | static const char * const audio_modes[5] = { | ||
1296 | "Stereo", | ||
1297 | "Left", | ||
1298 | "Right", | ||
1299 | "Mono", | ||
1300 | "Swapped" | ||
1301 | }; | ||
1302 | static const char * const alpha_mode[4] = { | ||
1303 | "None", | ||
1304 | "Global", | ||
1305 | "Local", | ||
1306 | "Global and Local" | ||
1307 | }; | ||
1308 | static const char * const pixel_format[16] = { | ||
1309 | "ARGB Indexed", | ||
1310 | "RGB 5:6:5", | ||
1311 | "ARGB 1:5:5:5", | ||
1312 | "ARGB 1:4:4:4", | ||
1313 | "ARGB 8:8:8:8", | ||
1314 | "5", | ||
1315 | "6", | ||
1316 | "7", | ||
1317 | "AYUV Indexed", | ||
1318 | "YUV 5:6:5", | ||
1319 | "AYUV 1:5:5:5", | ||
1320 | "AYUV 1:4:4:4", | ||
1321 | "AYUV 8:8:8:8", | ||
1322 | "13", | ||
1323 | "14", | ||
1324 | "15", | ||
1325 | }; | ||
1233 | 1326 | ||
1234 | ivtv_get_output(itv, itv->active_output, &vidout); | 1327 | ivtv_get_output(itv, itv->active_output, &vidout); |
1235 | ivtv_get_audio_output(itv, 0, &audout); | 1328 | ivtv_get_audio_output(itv, 0, &audout); |
1236 | IVTV_INFO("Video Output: %s\n", vidout.name); | 1329 | IVTV_INFO("Video Output: %s\n", vidout.name); |
1237 | IVTV_INFO("Audio Output: %s\n", audout.name); | 1330 | IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name, |
1331 | audio_modes[itv->audio_stereo_mode], | ||
1332 | audio_modes[itv->audio_bilingual_mode]); | ||
1238 | if (mode < 0 || mode > OUT_PASSTHROUGH) | 1333 | if (mode < 0 || mode > OUT_PASSTHROUGH) |
1239 | mode = OUT_NONE; | 1334 | mode = OUT_NONE; |
1240 | IVTV_INFO("Output Mode: %s\n", output_modes[mode]); | 1335 | IVTV_INFO("Output Mode: %s\n", output_modes[mode]); |
1336 | ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0); | ||
1337 | data[0] |= (read_reg(0x2a00) >> 7) & 0x40; | ||
1338 | IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n", | ||
1339 | data[0] & 1 ? "On" : "Off", | ||
1340 | alpha_mode[(data[0] >> 1) & 0x3], | ||
1341 | pixel_format[(data[0] >> 3) & 0xf]); | ||
1241 | } | 1342 | } |
1242 | IVTV_INFO("Tuner: %s\n", | 1343 | IVTV_INFO("Tuner: %s\n", |
1243 | test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); | 1344 | test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); |
1244 | cx2341x_log_status(&itv->params, itv->name); | 1345 | cx2341x_log_status(&itv->params, itv->name); |
1245 | IVTV_INFO("Version: %s Status flags: 0x%08lx\n", IVTV_VERSION, itv->i_flags); | 1346 | IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); |
1246 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { | 1347 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { |
1247 | struct ivtv_stream *s = &itv->streams[i]; | 1348 | struct ivtv_stream *s = &itv->streams[i]; |
1248 | 1349 | ||
@@ -1252,7 +1353,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
1252 | (s->buffers - s->q_free.buffers) * 100 / s->buffers, | 1353 | (s->buffers - s->q_free.buffers) * 100 / s->buffers, |
1253 | (s->buffers * s->buf_size) / 1024, s->buffers); | 1354 | (s->buffers * s->buf_size) / 1024, s->buffers); |
1254 | } | 1355 | } |
1255 | IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted); | 1356 | IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted); |
1256 | IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num); | 1357 | IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num); |
1257 | break; | 1358 | break; |
1258 | } | 1359 | } |
@@ -1288,6 +1389,8 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
1288 | ivtv_release_stream(s); | 1389 | ivtv_release_stream(s); |
1289 | return -EBUSY; | 1390 | return -EBUSY; |
1290 | } | 1391 | } |
1392 | /* Mark that this file handle started the UDMA_YUV mode */ | ||
1393 | id->yuv_frames = 1; | ||
1291 | if (args->y_source == NULL) | 1394 | if (args->y_source == NULL) |
1292 | return 0; | 1395 | return 0; |
1293 | return ivtv_yuv_prep_frame(itv, args); | 1396 | return ivtv_yuv_prep_frame(itv, args); |
@@ -1396,9 +1499,9 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
1396 | int try = (cmd == VIDEO_TRY_COMMAND); | 1499 | int try = (cmd == VIDEO_TRY_COMMAND); |
1397 | 1500 | ||
1398 | if (try) | 1501 | if (try) |
1399 | IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND\n"); | 1502 | IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd); |
1400 | else | 1503 | else |
1401 | IVTV_DEBUG_IOCTL("VIDEO_COMMAND\n"); | 1504 | IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd); |
1402 | return ivtv_video_command(itv, id, vc, try); | 1505 | return ivtv_video_command(itv, id, vc, try); |
1403 | } | 1506 | } |
1404 | 1507 | ||
@@ -1429,11 +1532,15 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
1429 | return 0; | 1532 | return 0; |
1430 | if (nonblocking) | 1533 | if (nonblocking) |
1431 | return -EAGAIN; | 1534 | return -EAGAIN; |
1432 | /* wait for event */ | 1535 | /* Wait for event. Note that serialize_lock is locked, |
1536 | so to allow other processes to access the driver while | ||
1537 | we are waiting unlock first and later lock again. */ | ||
1538 | mutex_unlock(&itv->serialize_lock); | ||
1433 | prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE); | 1539 | prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE); |
1434 | if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0) | 1540 | if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0) |
1435 | schedule(); | 1541 | schedule(); |
1436 | finish_wait(&itv->event_waitq, &wait); | 1542 | finish_wait(&itv->event_waitq, &wait); |
1543 | mutex_lock(&itv->serialize_lock); | ||
1437 | if (signal_pending(current)) { | 1544 | if (signal_pending(current)) { |
1438 | /* return if a signal was received */ | 1545 | /* return if a signal was received */ |
1439 | IVTV_DEBUG_INFO("User stopped wait for event\n"); | 1546 | IVTV_DEBUG_INFO("User stopped wait for event\n"); |
@@ -1470,6 +1577,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp, | |||
1470 | case VIDIOC_S_AUDOUT: | 1577 | case VIDIOC_S_AUDOUT: |
1471 | case VIDIOC_S_EXT_CTRLS: | 1578 | case VIDIOC_S_EXT_CTRLS: |
1472 | case VIDIOC_S_FBUF: | 1579 | case VIDIOC_S_FBUF: |
1580 | case VIDIOC_OVERLAY: | ||
1473 | ret = v4l2_prio_check(&itv->prio, &id->prio); | 1581 | ret = v4l2_prio_check(&itv->prio, &id->prio); |
1474 | if (ret) | 1582 | if (ret) |
1475 | return ret; | 1583 | return ret; |
@@ -1523,6 +1631,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp, | |||
1523 | case VIDIOC_TRY_ENCODER_CMD: | 1631 | case VIDIOC_TRY_ENCODER_CMD: |
1524 | case VIDIOC_G_FBUF: | 1632 | case VIDIOC_G_FBUF: |
1525 | case VIDIOC_S_FBUF: | 1633 | case VIDIOC_S_FBUF: |
1634 | case VIDIOC_OVERLAY: | ||
1526 | if (ivtv_debug & IVTV_DBGFLG_IOCTL) { | 1635 | if (ivtv_debug & IVTV_DBGFLG_IOCTL) { |
1527 | printk(KERN_INFO "ivtv%d ioctl: ", itv->num); | 1636 | printk(KERN_INFO "ivtv%d ioctl: ", itv->num); |
1528 | v4l_printk_ioctl(cmd); | 1637 | v4l_printk_ioctl(cmd); |
@@ -1563,12 +1672,9 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp, | |||
1563 | return 0; | 1672 | return 0; |
1564 | } | 1673 | } |
1565 | 1674 | ||
1566 | int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | 1675 | static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp, |
1567 | unsigned long arg) | 1676 | unsigned int cmd, unsigned long arg) |
1568 | { | 1677 | { |
1569 | struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; | ||
1570 | struct ivtv *itv = id->itv; | ||
1571 | |||
1572 | /* Filter dvb ioctls that cannot be handled by video_usercopy */ | 1678 | /* Filter dvb ioctls that cannot be handled by video_usercopy */ |
1573 | switch (cmd) { | 1679 | switch (cmd) { |
1574 | case VIDEO_SELECT_SOURCE: | 1680 | case VIDEO_SELECT_SOURCE: |
@@ -1603,3 +1709,16 @@ int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
1603 | } | 1709 | } |
1604 | return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl); | 1710 | return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl); |
1605 | } | 1711 | } |
1712 | |||
1713 | int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | ||
1714 | unsigned long arg) | ||
1715 | { | ||
1716 | struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; | ||
1717 | struct ivtv *itv = id->itv; | ||
1718 | int res; | ||
1719 | |||
1720 | mutex_lock(&itv->serialize_lock); | ||
1721 | res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg); | ||
1722 | mutex_unlock(&itv->serialize_lock); | ||
1723 | return res; | ||
1724 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/video/ivtv/ivtv-ioctl.h index cbccf7a9f65c..a03351b6853d 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.h +++ b/drivers/media/video/ivtv/ivtv-ioctl.h | |||
@@ -18,6 +18,9 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef IVTV_IOCTL_H | ||
22 | #define IVTV_IOCTL_H | ||
23 | |||
21 | u16 service2vbi(int type); | 24 | u16 service2vbi(int type); |
22 | void expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal); | 25 | void expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal); |
23 | u16 get_service_set(struct v4l2_sliced_vbi_format *fmt); | 26 | u16 get_service_set(struct v4l2_sliced_vbi_format *fmt); |
@@ -26,3 +29,5 @@ int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
26 | int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg); | 29 | int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg); |
27 | void ivtv_set_osd_alpha(struct ivtv *itv); | 30 | void ivtv_set_osd_alpha(struct ivtv *itv); |
28 | int ivtv_set_speed(struct ivtv *itv, int speed); | 31 | int ivtv_set_speed(struct ivtv *itv, int speed); |
32 | |||
33 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index fcd6e7f5f121..fd1688e4757d 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c | |||
@@ -19,12 +19,9 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include "ivtv-driver.h" | 21 | #include "ivtv-driver.h" |
22 | #include "ivtv-firmware.h" | ||
23 | #include "ivtv-fileops.h" | ||
24 | #include "ivtv-queue.h" | 22 | #include "ivtv-queue.h" |
25 | #include "ivtv-udma.h" | 23 | #include "ivtv-udma.h" |
26 | #include "ivtv-irq.h" | 24 | #include "ivtv-irq.h" |
27 | #include "ivtv-ioctl.h" | ||
28 | #include "ivtv-mailbox.h" | 25 | #include "ivtv-mailbox.h" |
29 | #include "ivtv-vbi.h" | 26 | #include "ivtv-vbi.h" |
30 | #include "ivtv-yuv.h" | 27 | #include "ivtv-yuv.h" |
@@ -45,7 +42,6 @@ static void ivtv_pio_work_handler(struct ivtv *itv) | |||
45 | { | 42 | { |
46 | struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream]; | 43 | struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream]; |
47 | struct ivtv_buffer *buf; | 44 | struct ivtv_buffer *buf; |
48 | struct list_head *p; | ||
49 | int i = 0; | 45 | int i = 0; |
50 | 46 | ||
51 | IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n"); | 47 | IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n"); |
@@ -57,21 +53,19 @@ static void ivtv_pio_work_handler(struct ivtv *itv) | |||
57 | return; | 53 | return; |
58 | } | 54 | } |
59 | IVTV_DEBUG_HI_DMA("Process PIO %s\n", s->name); | 55 | IVTV_DEBUG_HI_DMA("Process PIO %s\n", s->name); |
60 | buf = list_entry(s->q_dma.list.next, struct ivtv_buffer, list); | 56 | list_for_each_entry(buf, &s->q_dma.list, list) { |
61 | list_for_each(p, &s->q_dma.list) { | 57 | u32 size = s->sg_processing[i].size & 0x3ffff; |
62 | struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list); | ||
63 | u32 size = s->PIOarray[i].size & 0x3ffff; | ||
64 | 58 | ||
65 | /* Copy the data from the card to the buffer */ | 59 | /* Copy the data from the card to the buffer */ |
66 | if (s->type == IVTV_DEC_STREAM_TYPE_VBI) { | 60 | if (s->type == IVTV_DEC_STREAM_TYPE_VBI) { |
67 | memcpy_fromio(buf->buf, itv->dec_mem + s->PIOarray[i].src - IVTV_DECODER_OFFSET, size); | 61 | memcpy_fromio(buf->buf, itv->dec_mem + s->sg_processing[i].src - IVTV_DECODER_OFFSET, size); |
68 | } | 62 | } |
69 | else { | 63 | else { |
70 | memcpy_fromio(buf->buf, itv->enc_mem + s->PIOarray[i].src, size); | 64 | memcpy_fromio(buf->buf, itv->enc_mem + s->sg_processing[i].src, size); |
71 | } | 65 | } |
72 | if (s->PIOarray[i].size & 0x80000000) | ||
73 | break; | ||
74 | i++; | 66 | i++; |
67 | if (i == s->sg_processing_size) | ||
68 | break; | ||
75 | } | 69 | } |
76 | write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); | 70 | write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); |
77 | } | 71 | } |
@@ -100,12 +94,11 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA | |||
100 | { | 94 | { |
101 | struct ivtv *itv = s->itv; | 95 | struct ivtv *itv = s->itv; |
102 | struct ivtv_buffer *buf; | 96 | struct ivtv_buffer *buf; |
103 | struct list_head *p; | ||
104 | u32 bytes_needed = 0; | 97 | u32 bytes_needed = 0; |
105 | u32 offset, size; | 98 | u32 offset, size; |
106 | u32 UVoffset = 0, UVsize = 0; | 99 | u32 UVoffset = 0, UVsize = 0; |
107 | int skip_bufs = s->q_predma.buffers; | 100 | int skip_bufs = s->q_predma.buffers; |
108 | int idx = s->SG_length; | 101 | int idx = s->sg_pending_size; |
109 | int rc; | 102 | int rc; |
110 | 103 | ||
111 | /* sanity checks */ | 104 | /* sanity checks */ |
@@ -123,7 +116,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA | |||
123 | case IVTV_ENC_STREAM_TYPE_MPG: | 116 | case IVTV_ENC_STREAM_TYPE_MPG: |
124 | offset = data[1]; | 117 | offset = data[1]; |
125 | size = data[2]; | 118 | size = data[2]; |
126 | s->dma_pts = 0; | 119 | s->pending_pts = 0; |
127 | break; | 120 | break; |
128 | 121 | ||
129 | case IVTV_ENC_STREAM_TYPE_YUV: | 122 | case IVTV_ENC_STREAM_TYPE_YUV: |
@@ -131,13 +124,13 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA | |||
131 | size = data[2]; | 124 | size = data[2]; |
132 | UVoffset = data[3]; | 125 | UVoffset = data[3]; |
133 | UVsize = data[4]; | 126 | UVsize = data[4]; |
134 | s->dma_pts = ((u64) data[5] << 32) | data[6]; | 127 | s->pending_pts = ((u64) data[5] << 32) | data[6]; |
135 | break; | 128 | break; |
136 | 129 | ||
137 | case IVTV_ENC_STREAM_TYPE_PCM: | 130 | case IVTV_ENC_STREAM_TYPE_PCM: |
138 | offset = data[1] + 12; | 131 | offset = data[1] + 12; |
139 | size = data[2] - 12; | 132 | size = data[2] - 12; |
140 | s->dma_pts = read_dec(offset - 8) | | 133 | s->pending_pts = read_dec(offset - 8) | |
141 | ((u64)(read_dec(offset - 12)) << 32); | 134 | ((u64)(read_dec(offset - 12)) << 32); |
142 | if (itv->has_cx23415) | 135 | if (itv->has_cx23415) |
143 | offset += IVTV_DECODER_OFFSET; | 136 | offset += IVTV_DECODER_OFFSET; |
@@ -150,13 +143,13 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA | |||
150 | IVTV_DEBUG_INFO("VBI offset == 0\n"); | 143 | IVTV_DEBUG_INFO("VBI offset == 0\n"); |
151 | return -1; | 144 | return -1; |
152 | } | 145 | } |
153 | s->dma_pts = read_enc(offset - 4) | ((u64)read_enc(offset - 8) << 32); | 146 | s->pending_pts = read_enc(offset - 4) | ((u64)read_enc(offset - 8) << 32); |
154 | break; | 147 | break; |
155 | 148 | ||
156 | case IVTV_DEC_STREAM_TYPE_VBI: | 149 | case IVTV_DEC_STREAM_TYPE_VBI: |
157 | size = read_dec(itv->vbi.dec_start + 4) + 8; | 150 | size = read_dec(itv->vbi.dec_start + 4) + 8; |
158 | offset = read_dec(itv->vbi.dec_start) + itv->vbi.dec_start; | 151 | offset = read_dec(itv->vbi.dec_start) + itv->vbi.dec_start; |
159 | s->dma_pts = 0; | 152 | s->pending_pts = 0; |
160 | offset += IVTV_DECODER_OFFSET; | 153 | offset += IVTV_DECODER_OFFSET; |
161 | break; | 154 | break; |
162 | default: | 155 | default: |
@@ -165,17 +158,17 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA | |||
165 | } | 158 | } |
166 | 159 | ||
167 | /* if this is the start of the DMA then fill in the magic cookie */ | 160 | /* if this is the start of the DMA then fill in the magic cookie */ |
168 | if (s->SG_length == 0) { | 161 | if (s->sg_pending_size == 0 && ivtv_use_dma(s)) { |
169 | if (itv->has_cx23415 && (s->type == IVTV_ENC_STREAM_TYPE_PCM || | 162 | if (itv->has_cx23415 && (s->type == IVTV_ENC_STREAM_TYPE_PCM || |
170 | s->type == IVTV_DEC_STREAM_TYPE_VBI)) { | 163 | s->type == IVTV_DEC_STREAM_TYPE_VBI)) { |
171 | s->dma_backup = read_dec(offset - IVTV_DECODER_OFFSET); | 164 | s->pending_backup = read_dec(offset - IVTV_DECODER_OFFSET); |
172 | write_dec_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset - IVTV_DECODER_OFFSET); | 165 | write_dec_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset - IVTV_DECODER_OFFSET); |
173 | } | 166 | } |
174 | else { | 167 | else { |
175 | s->dma_backup = read_enc(offset); | 168 | s->pending_backup = read_enc(offset); |
176 | write_enc_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset); | 169 | write_enc_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset); |
177 | } | 170 | } |
178 | s->dma_offset = offset; | 171 | s->pending_offset = offset; |
179 | } | 172 | } |
180 | 173 | ||
181 | bytes_needed = size; | 174 | bytes_needed = size; |
@@ -202,18 +195,17 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA | |||
202 | } | 195 | } |
203 | s->buffers_stolen = rc; | 196 | s->buffers_stolen = rc; |
204 | 197 | ||
205 | /* got the buffers, now fill in SGarray (DMA) */ | 198 | /* got the buffers, now fill in sg_pending */ |
206 | buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list); | 199 | buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list); |
207 | memset(buf->buf, 0, 128); | 200 | memset(buf->buf, 0, 128); |
208 | list_for_each(p, &s->q_predma.list) { | 201 | list_for_each_entry(buf, &s->q_predma.list, list) { |
209 | struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list); | ||
210 | |||
211 | if (skip_bufs-- > 0) | 202 | if (skip_bufs-- > 0) |
212 | continue; | 203 | continue; |
213 | s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle); | 204 | s->sg_pending[idx].dst = buf->dma_handle; |
214 | s->SGarray[idx].src = cpu_to_le32(offset); | 205 | s->sg_pending[idx].src = offset; |
215 | s->SGarray[idx].size = cpu_to_le32(s->buf_size); | 206 | s->sg_pending[idx].size = s->buf_size; |
216 | buf->bytesused = (size < s->buf_size) ? size : s->buf_size; | 207 | buf->bytesused = (size < s->buf_size) ? size : s->buf_size; |
208 | buf->dma_xfer_cnt = s->dma_xfer_cnt; | ||
217 | 209 | ||
218 | s->q_predma.bytesused += buf->bytesused; | 210 | s->q_predma.bytesused += buf->bytesused; |
219 | size -= buf->bytesused; | 211 | size -= buf->bytesused; |
@@ -229,7 +221,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA | |||
229 | } | 221 | } |
230 | idx++; | 222 | idx++; |
231 | } | 223 | } |
232 | s->SG_length = idx; | 224 | s->sg_pending_size = idx; |
233 | return 0; | 225 | return 0; |
234 | } | 226 | } |
235 | 227 | ||
@@ -251,7 +243,7 @@ static void dma_post(struct ivtv_stream *s) | |||
251 | /* Sync Buffer */ | 243 | /* Sync Buffer */ |
252 | ivtv_buf_sync_for_cpu(s, buf); | 244 | ivtv_buf_sync_for_cpu(s, buf); |
253 | 245 | ||
254 | if (x == 0) { | 246 | if (x == 0 && ivtv_use_dma(s)) { |
255 | offset = s->dma_last_offset; | 247 | offset = s->dma_last_offset; |
256 | if (u32buf[offset / 4] != DMA_MAGIC_COOKIE) | 248 | if (u32buf[offset / 4] != DMA_MAGIC_COOKIE) |
257 | { | 249 | { |
@@ -286,14 +278,12 @@ static void dma_post(struct ivtv_stream *s) | |||
286 | /* flag byteswap ABCD -> DCBA for MPG & VBI data outside irq */ | 278 | /* flag byteswap ABCD -> DCBA for MPG & VBI data outside irq */ |
287 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG || | 279 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG || |
288 | s->type == IVTV_ENC_STREAM_TYPE_VBI) | 280 | s->type == IVTV_ENC_STREAM_TYPE_VBI) |
289 | set_bit(IVTV_F_B_NEED_BUF_SWAP, &buf->b_flags); | 281 | buf->b_flags |= IVTV_F_B_NEED_BUF_SWAP; |
290 | } | 282 | } |
291 | if (buf) | 283 | if (buf) |
292 | buf->bytesused += s->dma_last_offset; | 284 | buf->bytesused += s->dma_last_offset; |
293 | if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) { | 285 | if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) { |
294 | list_for_each(p, &s->q_dma.list) { | 286 | list_for_each_entry(buf, &s->q_dma.list, list) { |
295 | buf = list_entry(p, struct ivtv_buffer, list); | ||
296 | |||
297 | /* Parse and Groom VBI Data */ | 287 | /* Parse and Groom VBI Data */ |
298 | s->q_dma.bytesused -= buf->bytesused; | 288 | s->q_dma.bytesused -= buf->bytesused; |
299 | ivtv_process_vbi_data(itv, buf, 0, s->type); | 289 | ivtv_process_vbi_data(itv, buf, 0, s->type); |
@@ -313,7 +303,6 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) | |||
313 | { | 303 | { |
314 | struct ivtv *itv = s->itv; | 304 | struct ivtv *itv = s->itv; |
315 | struct ivtv_buffer *buf; | 305 | struct ivtv_buffer *buf; |
316 | struct list_head *p; | ||
317 | u32 y_size = itv->params.height * itv->params.width; | 306 | u32 y_size = itv->params.height * itv->params.width; |
318 | u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET; | 307 | u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET; |
319 | int y_done = 0; | 308 | int y_done = 0; |
@@ -322,18 +311,15 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) | |||
322 | int idx = 0; | 311 | int idx = 0; |
323 | 312 | ||
324 | IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset); | 313 | IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset); |
325 | buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list); | 314 | list_for_each_entry(buf, &s->q_predma.list, list) { |
326 | list_for_each(p, &s->q_predma.list) { | ||
327 | struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list); | ||
328 | |||
329 | /* YUV UV Offset from Y Buffer */ | 315 | /* YUV UV Offset from Y Buffer */ |
330 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done && bytes_written >= y_size) { | 316 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done && bytes_written >= y_size) { |
331 | offset = uv_offset; | 317 | offset = uv_offset; |
332 | y_done = 1; | 318 | y_done = 1; |
333 | } | 319 | } |
334 | s->SGarray[idx].src = cpu_to_le32(buf->dma_handle); | 320 | s->sg_pending[idx].src = buf->dma_handle; |
335 | s->SGarray[idx].dst = cpu_to_le32(offset); | 321 | s->sg_pending[idx].dst = offset; |
336 | s->SGarray[idx].size = cpu_to_le32(buf->bytesused); | 322 | s->sg_pending[idx].size = buf->bytesused; |
337 | 323 | ||
338 | offset += buf->bytesused; | 324 | offset += buf->bytesused; |
339 | bytes_written += buf->bytesused; | 325 | bytes_written += buf->bytesused; |
@@ -342,10 +328,7 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) | |||
342 | ivtv_buf_sync_for_device(s, buf); | 328 | ivtv_buf_sync_for_device(s, buf); |
343 | idx++; | 329 | idx++; |
344 | } | 330 | } |
345 | s->SG_length = idx; | 331 | s->sg_pending_size = idx; |
346 | |||
347 | /* Mark last buffer size for Interrupt flag */ | ||
348 | s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000); | ||
349 | 332 | ||
350 | /* Sync Hardware SG List of buffers */ | 333 | /* Sync Hardware SG List of buffers */ |
351 | ivtv_stream_sync_for_device(s); | 334 | ivtv_stream_sync_for_device(s); |
@@ -361,6 +344,34 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) | |||
361 | spin_unlock_irqrestore(&itv->dma_reg_lock, flags); | 344 | spin_unlock_irqrestore(&itv->dma_reg_lock, flags); |
362 | } | 345 | } |
363 | 346 | ||
347 | static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s) | ||
348 | { | ||
349 | struct ivtv *itv = s->itv; | ||
350 | |||
351 | s->sg_dma->src = cpu_to_le32(s->sg_processing[s->sg_processed].src); | ||
352 | s->sg_dma->dst = cpu_to_le32(s->sg_processing[s->sg_processed].dst); | ||
353 | s->sg_dma->size = cpu_to_le32(s->sg_processing[s->sg_processed].size | 0x80000000); | ||
354 | s->sg_processed++; | ||
355 | /* Sync Hardware SG List of buffers */ | ||
356 | ivtv_stream_sync_for_device(s); | ||
357 | write_reg(s->sg_handle, IVTV_REG_ENCDMAADDR); | ||
358 | write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER); | ||
359 | } | ||
360 | |||
361 | static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s) | ||
362 | { | ||
363 | struct ivtv *itv = s->itv; | ||
364 | |||
365 | s->sg_dma->src = cpu_to_le32(s->sg_processing[s->sg_processed].src); | ||
366 | s->sg_dma->dst = cpu_to_le32(s->sg_processing[s->sg_processed].dst); | ||
367 | s->sg_dma->size = cpu_to_le32(s->sg_processing[s->sg_processed].size | 0x80000000); | ||
368 | s->sg_processed++; | ||
369 | /* Sync Hardware SG List of buffers */ | ||
370 | ivtv_stream_sync_for_device(s); | ||
371 | write_reg(s->sg_handle, IVTV_REG_DECDMAADDR); | ||
372 | write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER); | ||
373 | } | ||
374 | |||
364 | /* start the encoder DMA */ | 375 | /* start the encoder DMA */ |
365 | static void ivtv_dma_enc_start(struct ivtv_stream *s) | 376 | static void ivtv_dma_enc_start(struct ivtv_stream *s) |
366 | { | 377 | { |
@@ -374,8 +385,7 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) | |||
374 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); | 385 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); |
375 | 386 | ||
376 | if (ivtv_use_dma(s)) | 387 | if (ivtv_use_dma(s)) |
377 | s->SGarray[s->SG_length - 1].size = | 388 | s->sg_pending[s->sg_pending_size - 1].size += 256; |
378 | cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256); | ||
379 | 389 | ||
380 | /* If this is an MPEG stream, and VBI data is also pending, then append the | 390 | /* If this is an MPEG stream, and VBI data is also pending, then append the |
381 | VBI DMA to the MPEG DMA and transfer both sets of data at once. | 391 | VBI DMA to the MPEG DMA and transfer both sets of data at once. |
@@ -386,43 +396,39 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) | |||
386 | sure we only use the MPEG DMA to transfer the VBI DMA if both are in | 396 | sure we only use the MPEG DMA to transfer the VBI DMA if both are in |
387 | use. This way no conflicts occur. */ | 397 | use. This way no conflicts occur. */ |
388 | clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags); | 398 | clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags); |
389 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->SG_length && | 399 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->sg_pending_size && |
390 | s->SG_length + s_vbi->SG_length <= s->buffers) { | 400 | s->sg_pending_size + s_vbi->sg_pending_size <= s->buffers) { |
391 | ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused); | 401 | ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused); |
392 | if (ivtv_use_dma(s_vbi)) | 402 | if (ivtv_use_dma(s_vbi)) |
393 | s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256); | 403 | s_vbi->sg_pending[s_vbi->sg_pending_size - 1].size += 256; |
394 | for (i = 0; i < s_vbi->SG_length; i++) { | 404 | for (i = 0; i < s_vbi->sg_pending_size; i++) { |
395 | s->SGarray[s->SG_length++] = s_vbi->SGarray[i]; | 405 | s->sg_pending[s->sg_pending_size++] = s_vbi->sg_pending[i]; |
396 | } | 406 | } |
397 | itv->vbi.dma_offset = s_vbi->dma_offset; | 407 | s_vbi->dma_offset = s_vbi->pending_offset; |
398 | s_vbi->SG_length = 0; | 408 | s_vbi->sg_pending_size = 0; |
409 | s_vbi->dma_xfer_cnt++; | ||
399 | set_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags); | 410 | set_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags); |
400 | IVTV_DEBUG_HI_DMA("include DMA for %s\n", s->name); | 411 | IVTV_DEBUG_HI_DMA("include DMA for %s\n", s->name); |
401 | } | 412 | } |
402 | 413 | ||
403 | /* Mark last buffer size for Interrupt flag */ | 414 | s->dma_xfer_cnt++; |
404 | s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000); | 415 | memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_element) * s->sg_pending_size); |
405 | 416 | s->sg_processing_size = s->sg_pending_size; | |
406 | if (s->type == IVTV_ENC_STREAM_TYPE_VBI) | 417 | s->sg_pending_size = 0; |
407 | set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); | 418 | s->sg_processed = 0; |
408 | else | 419 | s->dma_offset = s->pending_offset; |
409 | clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); | 420 | s->dma_backup = s->pending_backup; |
421 | s->dma_pts = s->pending_pts; | ||
410 | 422 | ||
411 | if (ivtv_use_pio(s)) { | 423 | if (ivtv_use_pio(s)) { |
412 | for (i = 0; i < s->SG_length; i++) { | ||
413 | s->PIOarray[i].src = le32_to_cpu(s->SGarray[i].src); | ||
414 | s->PIOarray[i].size = le32_to_cpu(s->SGarray[i].size); | ||
415 | } | ||
416 | set_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags); | 424 | set_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags); |
417 | set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); | 425 | set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); |
418 | set_bit(IVTV_F_I_PIO, &itv->i_flags); | 426 | set_bit(IVTV_F_I_PIO, &itv->i_flags); |
419 | itv->cur_pio_stream = s->type; | 427 | itv->cur_pio_stream = s->type; |
420 | } | 428 | } |
421 | else { | 429 | else { |
422 | /* Sync Hardware SG List of buffers */ | 430 | itv->dma_retries = 0; |
423 | ivtv_stream_sync_for_device(s); | 431 | ivtv_dma_enc_start_xfer(s); |
424 | write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR); | ||
425 | write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER); | ||
426 | set_bit(IVTV_F_I_DMA, &itv->i_flags); | 432 | set_bit(IVTV_F_I_DMA, &itv->i_flags); |
427 | itv->cur_dma_stream = s->type; | 433 | itv->cur_dma_stream = s->type; |
428 | itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); | 434 | itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); |
@@ -436,10 +442,15 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s) | |||
436 | 442 | ||
437 | if (s->q_predma.bytesused) | 443 | if (s->q_predma.bytesused) |
438 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); | 444 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); |
445 | s->dma_xfer_cnt++; | ||
446 | memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_element) * s->sg_pending_size); | ||
447 | s->sg_processing_size = s->sg_pending_size; | ||
448 | s->sg_pending_size = 0; | ||
449 | s->sg_processed = 0; | ||
450 | |||
439 | IVTV_DEBUG_HI_DMA("start DMA for %s\n", s->name); | 451 | IVTV_DEBUG_HI_DMA("start DMA for %s\n", s->name); |
440 | /* put SG Handle into register 0x0c */ | 452 | itv->dma_retries = 0; |
441 | write_reg(s->SG_handle, IVTV_REG_DECDMAADDR); | 453 | ivtv_dma_dec_start_xfer(s); |
442 | write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER); | ||
443 | set_bit(IVTV_F_I_DMA, &itv->i_flags); | 454 | set_bit(IVTV_F_I_DMA, &itv->i_flags); |
444 | itv->cur_dma_stream = s->type; | 455 | itv->cur_dma_stream = s->type; |
445 | itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); | 456 | itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); |
@@ -450,27 +461,44 @@ static void ivtv_irq_dma_read(struct ivtv *itv) | |||
450 | { | 461 | { |
451 | struct ivtv_stream *s = NULL; | 462 | struct ivtv_stream *s = NULL; |
452 | struct ivtv_buffer *buf; | 463 | struct ivtv_buffer *buf; |
453 | int hw_stream_type; | 464 | int hw_stream_type = 0; |
454 | 465 | ||
455 | IVTV_DEBUG_HI_IRQ("DEC DMA READ\n"); | 466 | IVTV_DEBUG_HI_IRQ("DEC DMA READ\n"); |
456 | del_timer(&itv->dma_timer); | 467 | if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0) { |
457 | if (read_reg(IVTV_REG_DMASTATUS) & 0x14) { | 468 | del_timer(&itv->dma_timer); |
458 | IVTV_DEBUG_WARN("DEC DMA ERROR %x\n", read_reg(IVTV_REG_DMASTATUS)); | 469 | return; |
459 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); | ||
460 | } | 470 | } |
471 | |||
461 | if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { | 472 | if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { |
462 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { | 473 | s = &itv->streams[itv->cur_dma_stream]; |
463 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; | 474 | ivtv_stream_sync_for_cpu(s); |
464 | hw_stream_type = 2; | 475 | |
476 | if (read_reg(IVTV_REG_DMASTATUS) & 0x14) { | ||
477 | IVTV_DEBUG_WARN("DEC DMA ERROR %x (xfer %d of %d, retry %d)\n", | ||
478 | read_reg(IVTV_REG_DMASTATUS), | ||
479 | s->sg_processed, s->sg_processing_size, itv->dma_retries); | ||
480 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); | ||
481 | if (itv->dma_retries == 3) { | ||
482 | /* Too many retries, give up on this frame */ | ||
483 | itv->dma_retries = 0; | ||
484 | s->sg_processed = s->sg_processing_size; | ||
485 | } | ||
486 | else { | ||
487 | /* Retry, starting with the first xfer segment. | ||
488 | Just retrying the current segment is not sufficient. */ | ||
489 | s->sg_processed = 0; | ||
490 | itv->dma_retries++; | ||
491 | } | ||
465 | } | 492 | } |
466 | else { | 493 | if (s->sg_processed < s->sg_processing_size) { |
467 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; | 494 | /* DMA next buffer */ |
468 | hw_stream_type = 0; | 495 | ivtv_dma_dec_start_xfer(s); |
496 | return; | ||
469 | } | 497 | } |
498 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV) | ||
499 | hw_stream_type = 2; | ||
470 | IVTV_DEBUG_HI_DMA("DEC DATA READ %s: %d\n", s->name, s->q_dma.bytesused); | 500 | IVTV_DEBUG_HI_DMA("DEC DATA READ %s: %d\n", s->name, s->q_dma.bytesused); |
471 | 501 | ||
472 | ivtv_stream_sync_for_cpu(s); | ||
473 | |||
474 | /* For some reason must kick the firmware, like PIO mode, | 502 | /* For some reason must kick the firmware, like PIO mode, |
475 | I think this tells the firmware we are done and the size | 503 | I think this tells the firmware we are done and the size |
476 | of the xfer so it can calculate what we need next. | 504 | of the xfer so it can calculate what we need next. |
@@ -487,6 +515,7 @@ static void ivtv_irq_dma_read(struct ivtv *itv) | |||
487 | } | 515 | } |
488 | wake_up(&s->waitq); | 516 | wake_up(&s->waitq); |
489 | } | 517 | } |
518 | del_timer(&itv->dma_timer); | ||
490 | clear_bit(IVTV_F_I_UDMA, &itv->i_flags); | 519 | clear_bit(IVTV_F_I_UDMA, &itv->i_flags); |
491 | clear_bit(IVTV_F_I_DMA, &itv->i_flags); | 520 | clear_bit(IVTV_F_I_DMA, &itv->i_flags); |
492 | itv->cur_dma_stream = -1; | 521 | itv->cur_dma_stream = -1; |
@@ -498,33 +527,46 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv) | |||
498 | u32 data[CX2341X_MBOX_MAX_DATA]; | 527 | u32 data[CX2341X_MBOX_MAX_DATA]; |
499 | struct ivtv_stream *s; | 528 | struct ivtv_stream *s; |
500 | 529 | ||
501 | del_timer(&itv->dma_timer); | ||
502 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data); | 530 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data); |
503 | IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d\n", data[0], data[1]); | 531 | IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream); |
504 | if (test_and_clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags)) | 532 | if (itv->cur_dma_stream < 0) { |
505 | data[1] = 3; | 533 | del_timer(&itv->dma_timer); |
506 | else if (data[1] > 2) | ||
507 | return; | 534 | return; |
508 | s = &itv->streams[ivtv_stream_map[data[1]]]; | 535 | } |
536 | s = &itv->streams[itv->cur_dma_stream]; | ||
537 | ivtv_stream_sync_for_cpu(s); | ||
538 | |||
509 | if (data[0] & 0x18) { | 539 | if (data[0] & 0x18) { |
510 | IVTV_DEBUG_WARN("ENC DMA ERROR %x\n", data[0]); | 540 | IVTV_DEBUG_WARN("ENC DMA ERROR %x (offset %08x, xfer %d of %d, retry %d)\n", data[0], |
541 | s->dma_offset, s->sg_processed, s->sg_processing_size, itv->dma_retries); | ||
511 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); | 542 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); |
512 | ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, data[1]); | 543 | if (itv->dma_retries == 3) { |
544 | /* Too many retries, give up on this frame */ | ||
545 | itv->dma_retries = 0; | ||
546 | s->sg_processed = s->sg_processing_size; | ||
547 | } | ||
548 | else { | ||
549 | /* Retry, starting with the first xfer segment. | ||
550 | Just retrying the current segment is not sufficient. */ | ||
551 | s->sg_processed = 0; | ||
552 | itv->dma_retries++; | ||
553 | } | ||
554 | } | ||
555 | if (s->sg_processed < s->sg_processing_size) { | ||
556 | /* DMA next buffer */ | ||
557 | ivtv_dma_enc_start_xfer(s); | ||
558 | return; | ||
513 | } | 559 | } |
514 | s->SG_length = 0; | 560 | del_timer(&itv->dma_timer); |
515 | clear_bit(IVTV_F_I_DMA, &itv->i_flags); | 561 | clear_bit(IVTV_F_I_DMA, &itv->i_flags); |
516 | itv->cur_dma_stream = -1; | 562 | itv->cur_dma_stream = -1; |
517 | dma_post(s); | 563 | dma_post(s); |
518 | ivtv_stream_sync_for_cpu(s); | ||
519 | if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) { | 564 | if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) { |
520 | u32 tmp; | ||
521 | |||
522 | s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; | 565 | s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; |
523 | tmp = s->dma_offset; | ||
524 | s->dma_offset = itv->vbi.dma_offset; | ||
525 | dma_post(s); | 566 | dma_post(s); |
526 | s->dma_offset = tmp; | ||
527 | } | 567 | } |
568 | s->sg_processing_size = 0; | ||
569 | s->sg_processed = 0; | ||
528 | wake_up(&itv->dma_waitq); | 570 | wake_up(&itv->dma_waitq); |
529 | } | 571 | } |
530 | 572 | ||
@@ -538,8 +580,6 @@ static void ivtv_irq_enc_pio_complete(struct ivtv *itv) | |||
538 | } | 580 | } |
539 | s = &itv->streams[itv->cur_pio_stream]; | 581 | s = &itv->streams[itv->cur_pio_stream]; |
540 | IVTV_DEBUG_HI_IRQ("ENC PIO COMPLETE %s\n", s->name); | 582 | IVTV_DEBUG_HI_IRQ("ENC PIO COMPLETE %s\n", s->name); |
541 | s->SG_length = 0; | ||
542 | clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); | ||
543 | clear_bit(IVTV_F_I_PIO, &itv->i_flags); | 583 | clear_bit(IVTV_F_I_PIO, &itv->i_flags); |
544 | itv->cur_pio_stream = -1; | 584 | itv->cur_pio_stream = -1; |
545 | dma_post(s); | 585 | dma_post(s); |
@@ -551,13 +591,8 @@ static void ivtv_irq_enc_pio_complete(struct ivtv *itv) | |||
551 | ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 2); | 591 | ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 2); |
552 | clear_bit(IVTV_F_I_PIO, &itv->i_flags); | 592 | clear_bit(IVTV_F_I_PIO, &itv->i_flags); |
553 | if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) { | 593 | if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) { |
554 | u32 tmp; | ||
555 | |||
556 | s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; | 594 | s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; |
557 | tmp = s->dma_offset; | ||
558 | s->dma_offset = itv->vbi.dma_offset; | ||
559 | dma_post(s); | 595 | dma_post(s); |
560 | s->dma_offset = tmp; | ||
561 | } | 596 | } |
562 | wake_up(&itv->dma_waitq); | 597 | wake_up(&itv->dma_waitq); |
563 | } | 598 | } |
@@ -569,19 +604,23 @@ static void ivtv_irq_dma_err(struct ivtv *itv) | |||
569 | del_timer(&itv->dma_timer); | 604 | del_timer(&itv->dma_timer); |
570 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data); | 605 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data); |
571 | IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1], | 606 | IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1], |
572 | read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream); | 607 | read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream); |
608 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); | ||
573 | if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && | 609 | if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && |
574 | itv->cur_dma_stream >= 0 && itv->cur_dma_stream < IVTV_MAX_STREAMS) { | 610 | itv->cur_dma_stream >= 0 && itv->cur_dma_stream < IVTV_MAX_STREAMS) { |
575 | struct ivtv_stream *s = &itv->streams[itv->cur_dma_stream]; | 611 | struct ivtv_stream *s = &itv->streams[itv->cur_dma_stream]; |
576 | 612 | ||
577 | /* retry */ | 613 | /* retry */ |
578 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); | ||
579 | if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) | 614 | if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) |
580 | ivtv_dma_dec_start(s); | 615 | ivtv_dma_dec_start(s); |
581 | else | 616 | else |
582 | ivtv_dma_enc_start(s); | 617 | ivtv_dma_enc_start(s); |
583 | return; | 618 | return; |
584 | } | 619 | } |
620 | if (test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { | ||
621 | ivtv_udma_start(itv); | ||
622 | return; | ||
623 | } | ||
585 | clear_bit(IVTV_F_I_UDMA, &itv->i_flags); | 624 | clear_bit(IVTV_F_I_UDMA, &itv->i_flags); |
586 | clear_bit(IVTV_F_I_DMA, &itv->i_flags); | 625 | clear_bit(IVTV_F_I_DMA, &itv->i_flags); |
587 | itv->cur_dma_stream = -1; | 626 | itv->cur_dma_stream = -1; |
@@ -625,14 +664,12 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) | |||
625 | DMA the data. Since at most four VBI DMA buffers are available, | 664 | DMA the data. Since at most four VBI DMA buffers are available, |
626 | we just drop the old requests when there are already three | 665 | we just drop the old requests when there are already three |
627 | requests queued. */ | 666 | requests queued. */ |
628 | if (s->SG_length > 2) { | 667 | if (s->sg_pending_size > 2) { |
629 | struct list_head *p; | 668 | struct ivtv_buffer *buf; |
630 | list_for_each(p, &s->q_predma.list) { | 669 | list_for_each_entry(buf, &s->q_predma.list, list) |
631 | struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list); | ||
632 | ivtv_buf_sync_for_cpu(s, buf); | 670 | ivtv_buf_sync_for_cpu(s, buf); |
633 | } | ||
634 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0); | 671 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0); |
635 | s->SG_length = 0; | 672 | s->sg_pending_size = 0; |
636 | } | 673 | } |
637 | /* if we can append the data, and the MPEG stream isn't capturing, | 674 | /* if we can append the data, and the MPEG stream isn't capturing, |
638 | then start a DMA request for just the VBI data. */ | 675 | then start a DMA request for just the VBI data. */ |
@@ -698,23 +735,27 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
698 | 735 | ||
699 | if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); | 736 | if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); |
700 | 737 | ||
701 | if (((frame ^ itv->yuv_info.lace_sync_field) == 0 && ((itv->lastVsyncFrame & 1) ^ itv->yuv_info.lace_sync_field)) || | 738 | if (((frame ^ itv->yuv_info.sync_field[last_dma_frame]) == 0 && |
702 | (frame != (itv->lastVsyncFrame & 1) && !itv->yuv_info.frame_interlaced)) { | 739 | ((itv->last_vsync_field & 1) ^ itv->yuv_info.sync_field[last_dma_frame])) || |
740 | (frame != (itv->last_vsync_field & 1) && !itv->yuv_info.frame_interlaced)) { | ||
703 | int next_dma_frame = last_dma_frame; | 741 | int next_dma_frame = last_dma_frame; |
704 | 742 | ||
705 | if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&itv->yuv_info.next_fill_frame)) { | 743 | if (!(itv->yuv_info.frame_interlaced && itv->yuv_info.field_delay[next_dma_frame] && itv->yuv_info.fields_lapsed < 1)) { |
706 | write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c); | 744 | if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&itv->yuv_info.next_fill_frame)) { |
707 | write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830); | 745 | write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c); |
708 | write_reg(yuv_offset[next_dma_frame] >> 4, 0x834); | 746 | write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830); |
709 | write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838); | 747 | write_reg(yuv_offset[next_dma_frame] >> 4, 0x834); |
710 | next_dma_frame = (next_dma_frame + 1) & 0x3; | 748 | write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838); |
711 | atomic_set(&itv->yuv_info.next_dma_frame, next_dma_frame); | 749 | next_dma_frame = (next_dma_frame + 1) & 0x3; |
750 | atomic_set(&itv->yuv_info.next_dma_frame, next_dma_frame); | ||
751 | itv->yuv_info.fields_lapsed = -1; | ||
752 | } | ||
712 | } | 753 | } |
713 | } | 754 | } |
714 | if (frame != (itv->lastVsyncFrame & 1)) { | 755 | if (frame != (itv->last_vsync_field & 1)) { |
715 | struct ivtv_stream *s = ivtv_get_output_stream(itv); | 756 | struct ivtv_stream *s = ivtv_get_output_stream(itv); |
716 | 757 | ||
717 | itv->lastVsyncFrame += 1; | 758 | itv->last_vsync_field += 1; |
718 | if (frame == 0) { | 759 | if (frame == 0) { |
719 | clear_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); | 760 | clear_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); |
720 | clear_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags); | 761 | clear_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags); |
@@ -731,7 +772,10 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
731 | wake_up(&s->waitq); | 772 | wake_up(&s->waitq); |
732 | 773 | ||
733 | /* Send VBI to saa7127 */ | 774 | /* Send VBI to saa7127 */ |
734 | if (frame) { | 775 | if (frame && (itv->output_mode == OUT_PASSTHROUGH || |
776 | test_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags) || | ||
777 | test_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags) || | ||
778 | test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags))) { | ||
735 | set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags); | 779 | set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags); |
736 | set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); | 780 | set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); |
737 | } | 781 | } |
@@ -749,10 +793,12 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
749 | set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); | 793 | set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); |
750 | } | 794 | } |
751 | } | 795 | } |
796 | |||
797 | itv->yuv_info.fields_lapsed ++; | ||
752 | } | 798 | } |
753 | } | 799 | } |
754 | 800 | ||
755 | #define IVTV_IRQ_DMA (IVTV_IRQ_DMA_READ | IVTV_IRQ_ENC_DMA_COMPLETE | IVTV_IRQ_DMA_ERR | IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_VBI_CAP | IVTV_IRQ_DEC_DATA_REQ) | 801 | #define IVTV_IRQ_DMA (IVTV_IRQ_DMA_READ | IVTV_IRQ_ENC_DMA_COMPLETE | IVTV_IRQ_DMA_ERR | IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_VBI_CAP | IVTV_IRQ_DEC_DATA_REQ | IVTV_IRQ_DEC_VBI_RE_INSERT) |
756 | 802 | ||
757 | irqreturn_t ivtv_irq_handler(int irq, void *dev_id) | 803 | irqreturn_t ivtv_irq_handler(int irq, void *dev_id) |
758 | { | 804 | { |
@@ -777,7 +823,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) | |||
777 | */ | 823 | */ |
778 | if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) { | 824 | if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) { |
779 | /* vsync is enabled, see if we're in a new field */ | 825 | /* vsync is enabled, see if we're in a new field */ |
780 | if ((itv->lastVsyncFrame & 1) != (read_reg(0x28c0) & 1)) { | 826 | if ((itv->last_vsync_field & 1) != (read_reg(0x28c0) & 1)) { |
781 | /* New field, looks like we missed it */ | 827 | /* New field, looks like we missed it */ |
782 | IVTV_DEBUG_YUV("VSync interrupt missed %d\n",read_reg(0x28c0)>>16); | 828 | IVTV_DEBUG_YUV("VSync interrupt missed %d\n",read_reg(0x28c0)>>16); |
783 | vsync_force = 1; | 829 | vsync_force = 1; |
@@ -831,7 +877,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) | |||
831 | if (combo & IVTV_IRQ_ENC_EOS) { | 877 | if (combo & IVTV_IRQ_ENC_EOS) { |
832 | IVTV_DEBUG_IRQ("ENC EOS\n"); | 878 | IVTV_DEBUG_IRQ("ENC EOS\n"); |
833 | set_bit(IVTV_F_I_EOS, &itv->i_flags); | 879 | set_bit(IVTV_F_I_EOS, &itv->i_flags); |
834 | wake_up(&itv->cap_w); | 880 | wake_up(&itv->eos_waitq); |
835 | } | 881 | } |
836 | 882 | ||
837 | if (combo & IVTV_IRQ_DEC_DATA_REQ) { | 883 | if (combo & IVTV_IRQ_DEC_DATA_REQ) { |
@@ -853,8 +899,9 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) | |||
853 | } | 899 | } |
854 | 900 | ||
855 | if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_DMA, &itv->i_flags)) { | 901 | if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_DMA, &itv->i_flags)) { |
902 | itv->irq_rr_idx++; | ||
856 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { | 903 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { |
857 | int idx = (i + itv->irq_rr_idx++) % IVTV_MAX_STREAMS; | 904 | int idx = (i + itv->irq_rr_idx) % IVTV_MAX_STREAMS; |
858 | struct ivtv_stream *s = &itv->streams[idx]; | 905 | struct ivtv_stream *s = &itv->streams[idx]; |
859 | 906 | ||
860 | if (!test_and_clear_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) | 907 | if (!test_and_clear_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) |
@@ -871,8 +918,9 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) | |||
871 | } | 918 | } |
872 | 919 | ||
873 | if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) { | 920 | if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) { |
921 | itv->irq_rr_idx++; | ||
874 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { | 922 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { |
875 | int idx = (i + itv->irq_rr_idx++) % IVTV_MAX_STREAMS; | 923 | int idx = (i + itv->irq_rr_idx) % IVTV_MAX_STREAMS; |
876 | struct ivtv_stream *s = &itv->streams[idx]; | 924 | struct ivtv_stream *s = &itv->streams[idx]; |
877 | 925 | ||
878 | if (!test_and_clear_bit(IVTV_F_S_PIO_PENDING, &s->s_flags)) | 926 | if (!test_and_clear_bit(IVTV_F_S_PIO_PENDING, &s->s_flags)) |
@@ -883,8 +931,9 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) | |||
883 | } | 931 | } |
884 | } | 932 | } |
885 | 933 | ||
886 | if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) | 934 | if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) { |
887 | queue_work(itv->irq_work_queues, &itv->irq_work_queue); | 935 | queue_work(itv->irq_work_queues, &itv->irq_work_queue); |
936 | } | ||
888 | 937 | ||
889 | spin_unlock(&itv->dma_reg_lock); | 938 | spin_unlock(&itv->dma_reg_lock); |
890 | 939 | ||
diff --git a/drivers/media/video/ivtv/ivtv-irq.h b/drivers/media/video/ivtv/ivtv-irq.h index a43348a30309..f879a5822e71 100644 --- a/drivers/media/video/ivtv/ivtv-irq.h +++ b/drivers/media/video/ivtv/ivtv-irq.h | |||
@@ -19,8 +19,35 @@ | |||
19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #ifndef IVTV_IRQ_H | ||
23 | #define IVTV_IRQ_H | ||
24 | |||
25 | #define IVTV_IRQ_ENC_START_CAP (0x1 << 31) | ||
26 | #define IVTV_IRQ_ENC_EOS (0x1 << 30) | ||
27 | #define IVTV_IRQ_ENC_VBI_CAP (0x1 << 29) | ||
28 | #define IVTV_IRQ_ENC_VIM_RST (0x1 << 28) | ||
29 | #define IVTV_IRQ_ENC_DMA_COMPLETE (0x1 << 27) | ||
30 | #define IVTV_IRQ_ENC_PIO_COMPLETE (0x1 << 25) | ||
31 | #define IVTV_IRQ_DEC_AUD_MODE_CHG (0x1 << 24) | ||
32 | #define IVTV_IRQ_DEC_DATA_REQ (0x1 << 22) | ||
33 | #define IVTV_IRQ_DEC_DMA_COMPLETE (0x1 << 20) | ||
34 | #define IVTV_IRQ_DEC_VBI_RE_INSERT (0x1 << 19) | ||
35 | #define IVTV_IRQ_DMA_ERR (0x1 << 18) | ||
36 | #define IVTV_IRQ_DMA_WRITE (0x1 << 17) | ||
37 | #define IVTV_IRQ_DMA_READ (0x1 << 16) | ||
38 | #define IVTV_IRQ_DEC_VSYNC (0x1 << 10) | ||
39 | |||
40 | /* IRQ Masks */ | ||
41 | #define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|\ | ||
42 | IVTV_IRQ_DMA_READ|IVTV_IRQ_ENC_PIO_COMPLETE) | ||
43 | |||
44 | #define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS) | ||
45 | #define IVTV_IRQ_MASK_DECODE (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG) | ||
46 | |||
22 | irqreturn_t ivtv_irq_handler(int irq, void *dev_id); | 47 | irqreturn_t ivtv_irq_handler(int irq, void *dev_id); |
23 | 48 | ||
24 | void ivtv_irq_work_handler(struct work_struct *work); | 49 | void ivtv_irq_work_handler(struct work_struct *work); |
25 | void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock); | 50 | void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock); |
26 | void ivtv_unfinished_dma(unsigned long arg); | 51 | void ivtv_unfinished_dma(unsigned long arg); |
52 | |||
53 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c index 5e3b679202ae..b05436da7136 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.c +++ b/drivers/media/video/ivtv/ivtv-mailbox.c | |||
@@ -225,15 +225,15 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) | |||
225 | } | 225 | } |
226 | if (args < 0 || args > CX2341X_MBOX_MAX_DATA || | 226 | if (args < 0 || args > CX2341X_MBOX_MAX_DATA || |
227 | cmd < 0 || cmd > 255 || api_info[cmd].name == NULL) { | 227 | cmd < 0 || cmd > 255 || api_info[cmd].name == NULL) { |
228 | IVTV_ERR("Invalid API call: cmd = 0x%02x, args = %d\n", cmd, args); | 228 | IVTV_ERR("Invalid MB call: cmd = 0x%02x, args = %d\n", cmd, args); |
229 | return -EINVAL; | 229 | return -EINVAL; |
230 | } | 230 | } |
231 | 231 | ||
232 | if (api_info[cmd].flags & API_HIGH_VOL) { | 232 | if (api_info[cmd].flags & API_HIGH_VOL) { |
233 | IVTV_DEBUG_HI_API("API Call: %s\n", api_info[cmd].name); | 233 | IVTV_DEBUG_HI_MB("MB Call: %s\n", api_info[cmd].name); |
234 | } | 234 | } |
235 | else { | 235 | else { |
236 | IVTV_DEBUG_API("API Call: %s\n", api_info[cmd].name); | 236 | IVTV_DEBUG_MB("MB Call: %s\n", api_info[cmd].name); |
237 | } | 237 | } |
238 | 238 | ||
239 | /* clear possibly uninitialized part of data array */ | 239 | /* clear possibly uninitialized part of data array */ |
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.h b/drivers/media/video/ivtv/ivtv-mailbox.h index 79b8aec14370..71a54eef8fc7 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.h +++ b/drivers/media/video/ivtv/ivtv-mailbox.h | |||
@@ -18,8 +18,16 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef IVTV_MAILBOX_H | ||
22 | #define IVTV_MAILBOX_H | ||
23 | |||
24 | #define IVTV_MBOX_DMA_END 8 | ||
25 | #define IVTV_MBOX_DMA 9 | ||
26 | |||
21 | void ivtv_api_get_data(struct ivtv_mailbox_data *mbox, int mb, u32 data[]); | 27 | void ivtv_api_get_data(struct ivtv_mailbox_data *mbox, int mb, u32 data[]); |
22 | int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]); | 28 | int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]); |
23 | int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...); | 29 | int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...); |
24 | int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...); | 30 | int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...); |
25 | int ivtv_api_func(void *priv, int cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]); | 31 | int ivtv_api_func(void *priv, int cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]); |
32 | |||
33 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c index a04f9387f63d..39a216713244 100644 --- a/drivers/media/video/ivtv/ivtv-queue.c +++ b/drivers/media/video/ivtv/ivtv-queue.c | |||
@@ -20,9 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include "ivtv-driver.h" | 22 | #include "ivtv-driver.h" |
23 | #include "ivtv-streams.h" | ||
24 | #include "ivtv-queue.h" | 23 | #include "ivtv-queue.h" |
25 | #include "ivtv-mailbox.h" | ||
26 | 24 | ||
27 | int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes) | 25 | int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes) |
28 | { | 26 | { |
@@ -60,6 +58,7 @@ void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_qu | |||
60 | buf->bytesused = 0; | 58 | buf->bytesused = 0; |
61 | buf->readpos = 0; | 59 | buf->readpos = 0; |
62 | buf->b_flags = 0; | 60 | buf->b_flags = 0; |
61 | buf->dma_xfer_cnt = 0; | ||
63 | } | 62 | } |
64 | spin_lock_irqsave(&s->qlock, flags); | 63 | spin_lock_irqsave(&s->qlock, flags); |
65 | list_add_tail(&buf->list, &q->list); | 64 | list_add_tail(&buf->list, &q->list); |
@@ -87,7 +86,7 @@ struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q) | |||
87 | } | 86 | } |
88 | 87 | ||
89 | static void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from, | 88 | static void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from, |
90 | struct ivtv_queue *to, int clear, int full) | 89 | struct ivtv_queue *to, int clear) |
91 | { | 90 | { |
92 | struct ivtv_buffer *buf = list_entry(from->list.next, struct ivtv_buffer, list); | 91 | struct ivtv_buffer *buf = list_entry(from->list.next, struct ivtv_buffer, list); |
93 | 92 | ||
@@ -97,13 +96,7 @@ static void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from, | |||
97 | from->bytesused -= buf->bytesused - buf->readpos; | 96 | from->bytesused -= buf->bytesused - buf->readpos; |
98 | /* special handling for q_free */ | 97 | /* special handling for q_free */ |
99 | if (clear) | 98 | if (clear) |
100 | buf->bytesused = buf->readpos = buf->b_flags = 0; | 99 | buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0; |
101 | else if (full) { | ||
102 | /* special handling for stolen buffers, assume | ||
103 | all bytes are used. */ | ||
104 | buf->bytesused = s->buf_size; | ||
105 | buf->readpos = buf->b_flags = 0; | ||
106 | } | ||
107 | to->buffers++; | 100 | to->buffers++; |
108 | to->length += s->buf_size; | 101 | to->length += s->buf_size; |
109 | to->bytesused += buf->bytesused - buf->readpos; | 102 | to->bytesused += buf->bytesused - buf->readpos; |
@@ -112,7 +105,7 @@ static void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from, | |||
112 | /* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'. | 105 | /* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'. |
113 | If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'. | 106 | If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'. |
114 | If 'steal' != NULL, then buffers may also taken from that queue if | 107 | If 'steal' != NULL, then buffers may also taken from that queue if |
115 | needed. | 108 | needed, but only if 'from' is the free queue. |
116 | 109 | ||
117 | The buffer is automatically cleared if it goes to the free queue. It is | 110 | The buffer is automatically cleared if it goes to the free queue. It is |
118 | also cleared if buffers need to be taken from the 'steal' queue and | 111 | also cleared if buffers need to be taken from the 'steal' queue and |
@@ -133,7 +126,7 @@ int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_ | |||
133 | int rc = 0; | 126 | int rc = 0; |
134 | int from_free = from == &s->q_free; | 127 | int from_free = from == &s->q_free; |
135 | int to_free = to == &s->q_free; | 128 | int to_free = to == &s->q_free; |
136 | int bytes_available; | 129 | int bytes_available, bytes_steal; |
137 | 130 | ||
138 | spin_lock_irqsave(&s->qlock, flags); | 131 | spin_lock_irqsave(&s->qlock, flags); |
139 | if (needed_bytes == 0) { | 132 | if (needed_bytes == 0) { |
@@ -142,32 +135,47 @@ int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_ | |||
142 | } | 135 | } |
143 | 136 | ||
144 | bytes_available = from_free ? from->length : from->bytesused; | 137 | bytes_available = from_free ? from->length : from->bytesused; |
145 | bytes_available += steal ? steal->length : 0; | 138 | bytes_steal = (from_free && steal) ? steal->length : 0; |
146 | 139 | ||
147 | if (bytes_available < needed_bytes) { | 140 | if (bytes_available + bytes_steal < needed_bytes) { |
148 | spin_unlock_irqrestore(&s->qlock, flags); | 141 | spin_unlock_irqrestore(&s->qlock, flags); |
149 | return -ENOMEM; | 142 | return -ENOMEM; |
150 | } | 143 | } |
144 | while (bytes_available < needed_bytes) { | ||
145 | struct ivtv_buffer *buf = list_entry(steal->list.prev, struct ivtv_buffer, list); | ||
146 | u16 dma_xfer_cnt = buf->dma_xfer_cnt; | ||
147 | |||
148 | /* move buffers from the tail of the 'steal' queue to the tail of the | ||
149 | 'from' queue. Always copy all the buffers with the same dma_xfer_cnt | ||
150 | value, this ensures that you do not end up with partial frame data | ||
151 | if one frame is stored in multiple buffers. */ | ||
152 | while (dma_xfer_cnt == buf->dma_xfer_cnt) { | ||
153 | list_move_tail(steal->list.prev, &from->list); | ||
154 | rc++; | ||
155 | steal->buffers--; | ||
156 | steal->length -= s->buf_size; | ||
157 | steal->bytesused -= buf->bytesused - buf->readpos; | ||
158 | buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0; | ||
159 | from->buffers++; | ||
160 | from->length += s->buf_size; | ||
161 | bytes_available += s->buf_size; | ||
162 | if (list_empty(&steal->list)) | ||
163 | break; | ||
164 | buf = list_entry(steal->list.prev, struct ivtv_buffer, list); | ||
165 | } | ||
166 | } | ||
151 | if (from_free) { | 167 | if (from_free) { |
152 | u32 old_length = to->length; | 168 | u32 old_length = to->length; |
153 | 169 | ||
154 | while (to->length - old_length < needed_bytes) { | 170 | while (to->length - old_length < needed_bytes) { |
155 | if (list_empty(&from->list)) | 171 | ivtv_queue_move_buf(s, from, to, 1); |
156 | from = steal; | ||
157 | if (from == steal) | ||
158 | rc++; /* keep track of 'stolen' buffers */ | ||
159 | ivtv_queue_move_buf(s, from, to, 1, 0); | ||
160 | } | 172 | } |
161 | } | 173 | } |
162 | else { | 174 | else { |
163 | u32 old_bytesused = to->bytesused; | 175 | u32 old_bytesused = to->bytesused; |
164 | 176 | ||
165 | while (to->bytesused - old_bytesused < needed_bytes) { | 177 | while (to->bytesused - old_bytesused < needed_bytes) { |
166 | if (list_empty(&from->list)) | 178 | ivtv_queue_move_buf(s, from, to, to_free); |
167 | from = steal; | ||
168 | if (from == steal) | ||
169 | rc++; /* keep track of 'stolen' buffers */ | ||
170 | ivtv_queue_move_buf(s, from, to, to_free, rc); | ||
171 | } | 179 | } |
172 | } | 180 | } |
173 | spin_unlock_irqrestore(&s->qlock, flags); | 181 | spin_unlock_irqrestore(&s->qlock, flags); |
@@ -185,7 +193,7 @@ void ivtv_flush_queues(struct ivtv_stream *s) | |||
185 | int ivtv_stream_alloc(struct ivtv_stream *s) | 193 | int ivtv_stream_alloc(struct ivtv_stream *s) |
186 | { | 194 | { |
187 | struct ivtv *itv = s->itv; | 195 | struct ivtv *itv = s->itv; |
188 | int SGsize = sizeof(struct ivtv_SG_element) * s->buffers; | 196 | int SGsize = sizeof(struct ivtv_sg_element) * s->buffers; |
189 | int i; | 197 | int i; |
190 | 198 | ||
191 | if (s->buffers == 0) | 199 | if (s->buffers == 0) |
@@ -195,27 +203,33 @@ int ivtv_stream_alloc(struct ivtv_stream *s) | |||
195 | s->dma != PCI_DMA_NONE ? "DMA " : "", | 203 | s->dma != PCI_DMA_NONE ? "DMA " : "", |
196 | s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); | 204 | s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); |
197 | 205 | ||
198 | if (ivtv_might_use_pio(s)) { | 206 | s->sg_pending = kzalloc(SGsize, GFP_KERNEL); |
199 | s->PIOarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL); | 207 | if (s->sg_pending == NULL) { |
200 | if (s->PIOarray == NULL) { | 208 | IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name); |
201 | IVTV_ERR("Could not allocate PIOarray for %s stream\n", s->name); | 209 | return -ENOMEM; |
202 | return -ENOMEM; | ||
203 | } | ||
204 | } | 210 | } |
211 | s->sg_pending_size = 0; | ||
205 | 212 | ||
206 | /* Allocate DMA SG Arrays */ | 213 | s->sg_processing = kzalloc(SGsize, GFP_KERNEL); |
207 | s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL); | 214 | if (s->sg_processing == NULL) { |
208 | if (s->SGarray == NULL) { | 215 | IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name); |
209 | IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name); | 216 | kfree(s->sg_pending); |
210 | if (ivtv_might_use_pio(s)) { | 217 | s->sg_pending = NULL; |
211 | kfree(s->PIOarray); | 218 | return -ENOMEM; |
212 | s->PIOarray = NULL; | 219 | } |
213 | } | 220 | s->sg_processing_size = 0; |
221 | |||
222 | s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element), GFP_KERNEL); | ||
223 | if (s->sg_dma == NULL) { | ||
224 | IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name); | ||
225 | kfree(s->sg_pending); | ||
226 | s->sg_pending = NULL; | ||
227 | kfree(s->sg_processing); | ||
228 | s->sg_processing = NULL; | ||
214 | return -ENOMEM; | 229 | return -ENOMEM; |
215 | } | 230 | } |
216 | s->SG_length = 0; | ||
217 | if (ivtv_might_use_dma(s)) { | 231 | if (ivtv_might_use_dma(s)) { |
218 | s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize, s->dma); | 232 | s->sg_handle = pci_map_single(itv->dev, s->sg_dma, sizeof(struct ivtv_sg_element), s->dma); |
219 | ivtv_stream_sync_for_cpu(s); | 233 | ivtv_stream_sync_for_cpu(s); |
220 | } | 234 | } |
221 | 235 | ||
@@ -262,16 +276,19 @@ void ivtv_stream_free(struct ivtv_stream *s) | |||
262 | } | 276 | } |
263 | 277 | ||
264 | /* Free SG Array/Lists */ | 278 | /* Free SG Array/Lists */ |
265 | if (s->SGarray != NULL) { | 279 | if (s->sg_dma != NULL) { |
266 | if (s->SG_handle != IVTV_DMA_UNMAPPED) { | 280 | if (s->sg_handle != IVTV_DMA_UNMAPPED) { |
267 | pci_unmap_single(s->itv->dev, s->SG_handle, | 281 | pci_unmap_single(s->itv->dev, s->sg_handle, |
268 | sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); | 282 | sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); |
269 | s->SG_handle = IVTV_DMA_UNMAPPED; | 283 | s->sg_handle = IVTV_DMA_UNMAPPED; |
270 | } | 284 | } |
271 | kfree(s->SGarray); | 285 | kfree(s->sg_pending); |
272 | kfree(s->PIOarray); | 286 | kfree(s->sg_processing); |
273 | s->PIOarray = NULL; | 287 | kfree(s->sg_dma); |
274 | s->SGarray = NULL; | 288 | s->sg_pending = NULL; |
275 | s->SG_length = 0; | 289 | s->sg_processing = NULL; |
290 | s->sg_dma = NULL; | ||
291 | s->sg_pending_size = 0; | ||
292 | s->sg_processing_size = 0; | ||
276 | } | 293 | } |
277 | } | 294 | } |
diff --git a/drivers/media/video/ivtv/ivtv-queue.h b/drivers/media/video/ivtv/ivtv-queue.h index 2ed8d548255d..7cfc0c9ab050 100644 --- a/drivers/media/video/ivtv/ivtv-queue.h +++ b/drivers/media/video/ivtv/ivtv-queue.h | |||
@@ -19,6 +19,9 @@ | |||
19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #ifndef IVTV_QUEUE_H | ||
23 | #define IVTV_QUEUE_H | ||
24 | |||
22 | #define IVTV_DMA_UNMAPPED ((u32) -1) | 25 | #define IVTV_DMA_UNMAPPED ((u32) -1) |
23 | #define SLICED_VBI_PIO 1 | 26 | #define SLICED_VBI_PIO 1 |
24 | 27 | ||
@@ -79,13 +82,15 @@ void ivtv_stream_free(struct ivtv_stream *s); | |||
79 | static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s) | 82 | static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s) |
80 | { | 83 | { |
81 | if (ivtv_use_dma(s)) | 84 | if (ivtv_use_dma(s)) |
82 | pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle, | 85 | pci_dma_sync_single_for_cpu(s->itv->dev, s->sg_handle, |
83 | sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); | 86 | sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); |
84 | } | 87 | } |
85 | 88 | ||
86 | static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s) | 89 | static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s) |
87 | { | 90 | { |
88 | if (ivtv_use_dma(s)) | 91 | if (ivtv_use_dma(s)) |
89 | pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle, | 92 | pci_dma_sync_single_for_device(s->itv->dev, s->sg_handle, |
90 | sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); | 93 | sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); |
91 | } | 94 | } |
95 | |||
96 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-video.c b/drivers/media/video/ivtv/ivtv-routing.c index 5858b197d510..398bd33033ed 100644 --- a/drivers/media/video/ivtv/ivtv-video.c +++ b/drivers/media/video/ivtv/ivtv-routing.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | saa7127 interface functions | 2 | Audio/video-routing-related ivtv functions. |
3 | Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl> | 3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> |
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
4 | 5 | ||
5 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by | 7 | it under the terms of the GNU General Public License as published by |
@@ -18,73 +19,46 @@ | |||
18 | */ | 19 | */ |
19 | 20 | ||
20 | #include "ivtv-driver.h" | 21 | #include "ivtv-driver.h" |
21 | #include "ivtv-video.h" | ||
22 | #include "ivtv-i2c.h" | 22 | #include "ivtv-i2c.h" |
23 | #include "ivtv-gpio.h" | ||
24 | #include "ivtv-cards.h" | 23 | #include "ivtv-cards.h" |
24 | #include "ivtv-gpio.h" | ||
25 | #include "ivtv-routing.h" | ||
26 | |||
27 | #include <media/msp3400.h> | ||
25 | #include <media/upd64031a.h> | 28 | #include <media/upd64031a.h> |
26 | #include <media/upd64083.h> | 29 | #include <media/upd64083.h> |
27 | 30 | ||
28 | void ivtv_set_vps(struct ivtv *itv, int enabled, u8 vps1, u8 vps2, u8 vps3, | 31 | /* Selects the audio input and output according to the current |
29 | u8 vps4, u8 vps5) | 32 | settings. */ |
33 | void ivtv_audio_set_io(struct ivtv *itv) | ||
30 | { | 34 | { |
31 | struct v4l2_sliced_vbi_data data; | 35 | struct v4l2_routing route; |
32 | 36 | u32 audio_input; | |
33 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | 37 | int mux_input; |
34 | return; | ||
35 | data.id = V4L2_SLICED_VPS; | ||
36 | data.field = 0; | ||
37 | data.line = enabled ? 16 : 0; | ||
38 | data.data[4] = vps1; | ||
39 | data.data[10] = vps2; | ||
40 | data.data[11] = vps3; | ||
41 | data.data[12] = vps4; | ||
42 | data.data[13] = vps5; | ||
43 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | ||
44 | } | ||
45 | 38 | ||
46 | void ivtv_set_cc(struct ivtv *itv, int mode, u8 cc1, u8 cc2, u8 cc3, u8 cc4) | 39 | /* Determine which input to use */ |
47 | { | 40 | if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) { |
48 | struct v4l2_sliced_vbi_data data; | 41 | audio_input = itv->card->radio_input.audio_input; |
49 | 42 | mux_input = itv->card->radio_input.muxer_input; | |
50 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | 43 | } else { |
51 | return; | 44 | audio_input = itv->card->audio_inputs[itv->audio_input].audio_input; |
52 | data.id = V4L2_SLICED_CAPTION_525; | 45 | mux_input = itv->card->audio_inputs[itv->audio_input].muxer_input; |
53 | data.field = 0; | 46 | } |
54 | data.line = (mode & 1) ? 21 : 0; | ||
55 | data.data[0] = cc1; | ||
56 | data.data[1] = cc2; | ||
57 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | ||
58 | data.field = 1; | ||
59 | data.line = (mode & 2) ? 21 : 0; | ||
60 | data.data[0] = cc3; | ||
61 | data.data[1] = cc4; | ||
62 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | ||
63 | } | ||
64 | 47 | ||
65 | void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) | 48 | /* handle muxer chips */ |
66 | { | 49 | route.input = mux_input; |
67 | struct v4l2_sliced_vbi_data data; | 50 | route.output = 0; |
68 | 51 | ivtv_i2c_hw(itv, itv->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route); | |
69 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | 52 | |
70 | return; | 53 | route.input = audio_input; |
71 | /* When using a 50 Hz system, always turn on the | 54 | if (itv->card->hw_audio & IVTV_HW_MSP34XX) { |
72 | wide screen signal with 4x3 ratio as the default. | 55 | route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); |
73 | Turning this signal on and off can confuse certain | ||
74 | TVs. As far as I can tell there is no reason not to | ||
75 | transmit this signal. */ | ||
76 | if ((itv->std & V4L2_STD_625_50) && !enabled) { | ||
77 | enabled = 1; | ||
78 | mode = 0x08; /* 4x3 full format */ | ||
79 | } | 56 | } |
80 | data.id = V4L2_SLICED_WSS_625; | 57 | ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, &route); |
81 | data.field = 0; | ||
82 | data.line = enabled ? 23 : 0; | ||
83 | data.data[0] = mode & 0xff; | ||
84 | data.data[1] = (mode >> 8) & 0xff; | ||
85 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | ||
86 | } | 58 | } |
87 | 59 | ||
60 | /* Selects the video input and output according to the current | ||
61 | settings. */ | ||
88 | void ivtv_video_set_io(struct ivtv *itv) | 62 | void ivtv_video_set_io(struct ivtv *itv) |
89 | { | 63 | { |
90 | struct v4l2_routing route; | 64 | struct v4l2_routing route; |
diff --git a/drivers/media/video/ivtv/ivtv-audio.h b/drivers/media/video/ivtv/ivtv-routing.h index 9c42846d8124..c72a9731ca01 100644 --- a/drivers/media/video/ivtv/ivtv-audio.h +++ b/drivers/media/video/ivtv/ivtv-routing.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Audio-related ivtv functions. | 2 | Audio/video-routing-related ivtv functions. |
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | 3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> |
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | 4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> |
5 | 5 | ||
@@ -18,6 +18,10 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | int ivtv_audio_set_io(struct ivtv *itv); | 21 | #ifndef IVTV_ROUTING_H |
22 | void ivtv_audio_set_route(struct ivtv *itv, struct v4l2_routing *route); | 22 | #define IVTV_ROUTING_H |
23 | void ivtv_audio_set_audio_clock_freq(struct ivtv *itv, u8 freq); | 23 | |
24 | void ivtv_audio_set_io(struct ivtv *itv); | ||
25 | void ivtv_video_set_io(struct ivtv *itv); | ||
26 | |||
27 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 51df3f855031..fd135985e70f 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -35,16 +35,13 @@ | |||
35 | 35 | ||
36 | #include "ivtv-driver.h" | 36 | #include "ivtv-driver.h" |
37 | #include "ivtv-fileops.h" | 37 | #include "ivtv-fileops.h" |
38 | #include "ivtv-i2c.h" | ||
39 | #include "ivtv-queue.h" | 38 | #include "ivtv-queue.h" |
40 | #include "ivtv-mailbox.h" | 39 | #include "ivtv-mailbox.h" |
41 | #include "ivtv-audio.h" | ||
42 | #include "ivtv-video.h" | ||
43 | #include "ivtv-vbi.h" | ||
44 | #include "ivtv-ioctl.h" | 40 | #include "ivtv-ioctl.h" |
45 | #include "ivtv-irq.h" | 41 | #include "ivtv-irq.h" |
46 | #include "ivtv-streams.h" | 42 | #include "ivtv-yuv.h" |
47 | #include "ivtv-cards.h" | 43 | #include "ivtv-cards.h" |
44 | #include "ivtv-streams.h" | ||
48 | 45 | ||
49 | static struct file_operations ivtv_v4l2_enc_fops = { | 46 | static struct file_operations ivtv_v4l2_enc_fops = { |
50 | .owner = THIS_MODULE, | 47 | .owner = THIS_MODULE, |
@@ -66,6 +63,13 @@ static struct file_operations ivtv_v4l2_dec_fops = { | |||
66 | .poll = ivtv_v4l2_dec_poll, | 63 | .poll = ivtv_v4l2_dec_poll, |
67 | }; | 64 | }; |
68 | 65 | ||
66 | #define IVTV_V4L2_DEC_MPG_OFFSET 16 /* offset from 0 to register decoder mpg v4l2 minors on */ | ||
67 | #define IVTV_V4L2_ENC_PCM_OFFSET 24 /* offset from 0 to register pcm v4l2 minors on */ | ||
68 | #define IVTV_V4L2_ENC_YUV_OFFSET 32 /* offset from 0 to register yuv v4l2 minors on */ | ||
69 | #define IVTV_V4L2_DEC_YUV_OFFSET 48 /* offset from 0 to register decoder yuv v4l2 minors on */ | ||
70 | #define IVTV_V4L2_DEC_VBI_OFFSET 8 /* offset from 0 to register decoder vbi input v4l2 minors on */ | ||
71 | #define IVTV_V4L2_DEC_VOUT_OFFSET 16 /* offset from 0 to register vbi output v4l2 minors on */ | ||
72 | |||
69 | static struct { | 73 | static struct { |
70 | const char *name; | 74 | const char *name; |
71 | int vfl_type; | 75 | int vfl_type; |
@@ -75,7 +79,7 @@ static struct { | |||
75 | struct file_operations *fops; | 79 | struct file_operations *fops; |
76 | } ivtv_stream_info[] = { | 80 | } ivtv_stream_info[] = { |
77 | { /* IVTV_ENC_STREAM_TYPE_MPG */ | 81 | { /* IVTV_ENC_STREAM_TYPE_MPG */ |
78 | "encoder MPEG", | 82 | "encoder MPG", |
79 | VFL_TYPE_GRABBER, 0, | 83 | VFL_TYPE_GRABBER, 0, |
80 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, | 84 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
81 | &ivtv_v4l2_enc_fops | 85 | &ivtv_v4l2_enc_fops |
@@ -93,7 +97,7 @@ static struct { | |||
93 | &ivtv_v4l2_enc_fops | 97 | &ivtv_v4l2_enc_fops |
94 | }, | 98 | }, |
95 | { /* IVTV_ENC_STREAM_TYPE_PCM */ | 99 | { /* IVTV_ENC_STREAM_TYPE_PCM */ |
96 | "encoder PCM audio", | 100 | "encoder PCM", |
97 | VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET, | 101 | VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET, |
98 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE, | 102 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE, |
99 | &ivtv_v4l2_enc_fops | 103 | &ivtv_v4l2_enc_fops |
@@ -105,7 +109,7 @@ static struct { | |||
105 | &ivtv_v4l2_enc_fops | 109 | &ivtv_v4l2_enc_fops |
106 | }, | 110 | }, |
107 | { /* IVTV_DEC_STREAM_TYPE_MPG */ | 111 | { /* IVTV_DEC_STREAM_TYPE_MPG */ |
108 | "decoder MPEG", | 112 | "decoder MPG", |
109 | VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET, | 113 | VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET, |
110 | PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, | 114 | PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, |
111 | &ivtv_v4l2_dec_fops | 115 | &ivtv_v4l2_dec_fops |
@@ -150,11 +154,11 @@ static void ivtv_stream_init(struct ivtv *itv, int type) | |||
150 | s->dma = ivtv_stream_info[type].dma; | 154 | s->dma = ivtv_stream_info[type].dma; |
151 | s->buf_size = itv->stream_buf_size[type]; | 155 | s->buf_size = itv->stream_buf_size[type]; |
152 | if (s->buf_size) | 156 | if (s->buf_size) |
153 | s->buffers = itv->options.megabytes[type] * 1024 * 1024 / s->buf_size; | 157 | s->buffers = (itv->options.kilobytes[type] * 1024 + s->buf_size - 1) / s->buf_size; |
154 | spin_lock_init(&s->qlock); | 158 | spin_lock_init(&s->qlock); |
155 | init_waitqueue_head(&s->waitq); | 159 | init_waitqueue_head(&s->waitq); |
156 | s->id = -1; | 160 | s->id = -1; |
157 | s->SG_handle = IVTV_DMA_UNMAPPED; | 161 | s->sg_handle = IVTV_DMA_UNMAPPED; |
158 | ivtv_queue_init(&s->q_free); | 162 | ivtv_queue_init(&s->q_free); |
159 | ivtv_queue_init(&s->q_full); | 163 | ivtv_queue_init(&s->q_full); |
160 | ivtv_queue_init(&s->q_dma); | 164 | ivtv_queue_init(&s->q_dma); |
@@ -192,7 +196,7 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) | |||
192 | /* User explicitly selected 0 buffers for these streams, so don't | 196 | /* User explicitly selected 0 buffers for these streams, so don't |
193 | create them. */ | 197 | create them. */ |
194 | if (minor >= 0 && ivtv_stream_info[type].dma != PCI_DMA_NONE && | 198 | if (minor >= 0 && ivtv_stream_info[type].dma != PCI_DMA_NONE && |
195 | itv->options.megabytes[type] == 0) { | 199 | itv->options.kilobytes[type] == 0) { |
196 | IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name); | 200 | IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name); |
197 | return 0; | 201 | return 0; |
198 | } | 202 | } |
@@ -238,18 +242,18 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) | |||
238 | 242 | ||
239 | switch (vfl_type) { | 243 | switch (vfl_type) { |
240 | case VFL_TYPE_GRABBER: | 244 | case VFL_TYPE_GRABBER: |
241 | IVTV_INFO("Registered device video%d for %s (%d MB)\n", | 245 | IVTV_INFO("Registered device video%d for %s (%d kB)\n", |
242 | s->v4l2dev->minor, s->name, itv->options.megabytes[type]); | 246 | s->v4l2dev->minor, s->name, itv->options.kilobytes[type]); |
243 | break; | 247 | break; |
244 | case VFL_TYPE_RADIO: | 248 | case VFL_TYPE_RADIO: |
245 | IVTV_INFO("Registered device radio%d for %s\n", | 249 | IVTV_INFO("Registered device radio%d for %s\n", |
246 | s->v4l2dev->minor - MINOR_VFL_TYPE_RADIO_MIN, s->name); | 250 | s->v4l2dev->minor - MINOR_VFL_TYPE_RADIO_MIN, s->name); |
247 | break; | 251 | break; |
248 | case VFL_TYPE_VBI: | 252 | case VFL_TYPE_VBI: |
249 | if (itv->options.megabytes[type]) | 253 | if (itv->options.kilobytes[type]) |
250 | IVTV_INFO("Registered device vbi%d for %s (%d MB)\n", | 254 | IVTV_INFO("Registered device vbi%d for %s (%d kB)\n", |
251 | s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, | 255 | s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, |
252 | s->name, itv->options.megabytes[type]); | 256 | s->name, itv->options.kilobytes[type]); |
253 | else | 257 | else |
254 | IVTV_INFO("Registered device vbi%d for %s\n", | 258 | IVTV_INFO("Registered device vbi%d for %s\n", |
255 | s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, s->name); | 259 | s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, s->name); |
@@ -314,28 +318,9 @@ static void ivtv_vbi_setup(struct ivtv *itv) | |||
314 | int lines; | 318 | int lines; |
315 | int i; | 319 | int i; |
316 | 320 | ||
317 | /* If Embed then streamtype must be Program */ | ||
318 | /* TODO: should we really do this? */ | ||
319 | if (0 && !raw && itv->vbi.insert_mpeg) { | ||
320 | itv->params.stream_type = 0; | ||
321 | |||
322 | /* assign stream type */ | ||
323 | ivtv_vapi(itv, CX2341X_ENC_SET_STREAM_TYPE, 1, itv->params.stream_type); | ||
324 | } | ||
325 | |||
326 | /* Reset VBI */ | 321 | /* Reset VBI */ |
327 | ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0); | 322 | ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0); |
328 | 323 | ||
329 | if (itv->is_60hz) { | ||
330 | itv->vbi.count = 12; | ||
331 | itv->vbi.start[0] = 10; | ||
332 | itv->vbi.start[1] = 273; | ||
333 | } else { /* PAL/SECAM */ | ||
334 | itv->vbi.count = 18; | ||
335 | itv->vbi.start[0] = 6; | ||
336 | itv->vbi.start[1] = 318; | ||
337 | } | ||
338 | |||
339 | /* setup VBI registers */ | 324 | /* setup VBI registers */ |
340 | itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in); | 325 | itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in); |
341 | 326 | ||
@@ -409,8 +394,8 @@ static void ivtv_vbi_setup(struct ivtv *itv) | |||
409 | if (!itv->vbi.fpi) | 394 | if (!itv->vbi.fpi) |
410 | itv->vbi.fpi = 1; | 395 | itv->vbi.fpi = 1; |
411 | 396 | ||
412 | IVTV_DEBUG_INFO("Setup VBI start 0x%08x frames %d fpi %d lines 0x%08x\n", | 397 | IVTV_DEBUG_INFO("Setup VBI start 0x%08x frames %d fpi %d\n", |
413 | itv->vbi.enc_start, data[1], itv->vbi.fpi, itv->digitizer); | 398 | itv->vbi.enc_start, data[1], itv->vbi.fpi); |
414 | 399 | ||
415 | /* select VBI lines. | 400 | /* select VBI lines. |
416 | Note that the sliced argument seems to have no effect. */ | 401 | Note that the sliced argument seems to have no effect. */ |
@@ -446,9 +431,6 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
446 | if (s->v4l2dev == NULL) | 431 | if (s->v4l2dev == NULL) |
447 | return -EINVAL; | 432 | return -EINVAL; |
448 | 433 | ||
449 | /* Big serialization lock to ensure no two streams are started | ||
450 | simultaneously: that can give all sorts of weird results. */ | ||
451 | mutex_lock(&itv->serialize_lock); | ||
452 | IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name); | 434 | IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name); |
453 | 435 | ||
454 | switch (s->type) { | 436 | switch (s->type) { |
@@ -490,7 +472,6 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
490 | 0, sizeof(itv->vbi.sliced_mpeg_size)); | 472 | 0, sizeof(itv->vbi.sliced_mpeg_size)); |
491 | break; | 473 | break; |
492 | default: | 474 | default: |
493 | mutex_unlock(&itv->serialize_lock); | ||
494 | return -EINVAL; | 475 | return -EINVAL; |
495 | } | 476 | } |
496 | s->subtype = subtype; | 477 | s->subtype = subtype; |
@@ -503,6 +484,8 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
503 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | 484 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); |
504 | 485 | ||
505 | if (atomic_read(&itv->capturing) == 0) { | 486 | if (atomic_read(&itv->capturing) == 0) { |
487 | int digitizer; | ||
488 | |||
506 | /* Always use frame based mode. Experiments have demonstrated that byte | 489 | /* Always use frame based mode. Experiments have demonstrated that byte |
507 | stream based mode results in dropped frames and corruption. Not often, | 490 | stream based mode results in dropped frames and corruption. Not often, |
508 | but occasionally. Many thanks go to Leonard Orb who spent a lot of | 491 | but occasionally. Many thanks go to Leonard Orb who spent a lot of |
@@ -528,7 +511,14 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
528 | ivtv_vapi(itv, CX2341X_ENC_SET_PLACEHOLDER, 12, | 511 | ivtv_vapi(itv, CX2341X_ENC_SET_PLACEHOLDER, 12, |
529 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | 512 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); |
530 | 513 | ||
531 | ivtv_vapi(itv, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, itv->digitizer, itv->digitizer); | 514 | if (itv->card->hw_all & (IVTV_HW_SAA7115 | IVTV_HW_SAA717X)) |
515 | digitizer = 0xF1; | ||
516 | else if (itv->card->hw_all & IVTV_HW_SAA7114) | ||
517 | digitizer = 0xEF; | ||
518 | else /* cx25840 */ | ||
519 | digitizer = 0x140; | ||
520 | |||
521 | ivtv_vapi(itv, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, digitizer, digitizer); | ||
532 | 522 | ||
533 | /* Setup VBI */ | 523 | /* Setup VBI */ |
534 | if (itv->v4l2_cap & V4L2_CAP_VBI_CAPTURE) { | 524 | if (itv->v4l2_cap & V4L2_CAP_VBI_CAPTURE) { |
@@ -563,16 +553,16 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
563 | clear_bit(IVTV_F_I_EOS, &itv->i_flags); | 553 | clear_bit(IVTV_F_I_EOS, &itv->i_flags); |
564 | 554 | ||
565 | /* Initialize Digitizer for Capture */ | 555 | /* Initialize Digitizer for Capture */ |
556 | itv->video_dec_func(itv, VIDIOC_STREAMOFF, 0); | ||
557 | ivtv_msleep_timeout(300, 1); | ||
566 | ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); | 558 | ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); |
567 | 559 | itv->video_dec_func(itv, VIDIOC_STREAMON, 0); | |
568 | ivtv_msleep_timeout(100, 0); | ||
569 | } | 560 | } |
570 | 561 | ||
571 | /* begin_capture */ | 562 | /* begin_capture */ |
572 | if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype)) | 563 | if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype)) |
573 | { | 564 | { |
574 | IVTV_DEBUG_WARN( "Error starting capture!\n"); | 565 | IVTV_DEBUG_WARN( "Error starting capture!\n"); |
575 | mutex_unlock(&itv->serialize_lock); | ||
576 | return -EINVAL; | 566 | return -EINVAL; |
577 | } | 567 | } |
578 | 568 | ||
@@ -588,7 +578,6 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
588 | 578 | ||
589 | /* you're live! sit back and await interrupts :) */ | 579 | /* you're live! sit back and await interrupts :) */ |
590 | atomic_inc(&itv->capturing); | 580 | atomic_inc(&itv->capturing); |
591 | mutex_unlock(&itv->serialize_lock); | ||
592 | return 0; | 581 | return 0; |
593 | } | 582 | } |
594 | 583 | ||
@@ -676,10 +665,10 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset) | |||
676 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | 665 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); |
677 | 666 | ||
678 | /* Zero out decoder counters */ | 667 | /* Zero out decoder counters */ |
679 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_FIELD_DISPLAYED].data[0]); | 668 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[0]); |
680 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_FIELD_DISPLAYED].data[1]); | 669 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[1]); |
681 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_FIELD_DISPLAYED].data[2]); | 670 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[2]); |
682 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_FIELD_DISPLAYED].data[3]); | 671 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[3]); |
683 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[0]); | 672 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[0]); |
684 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[1]); | 673 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[1]); |
685 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[2]); | 674 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[2]); |
@@ -720,9 +709,7 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
720 | struct ivtv *itv = s->itv; | 709 | struct ivtv *itv = s->itv; |
721 | DECLARE_WAITQUEUE(wait, current); | 710 | DECLARE_WAITQUEUE(wait, current); |
722 | int cap_type; | 711 | int cap_type; |
723 | unsigned long then; | ||
724 | int stopmode; | 712 | int stopmode; |
725 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
726 | 713 | ||
727 | if (s->v4l2dev == NULL) | 714 | if (s->v4l2dev == NULL) |
728 | return -EINVAL; | 715 | return -EINVAL; |
@@ -764,15 +751,13 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
764 | /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ | 751 | /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ |
765 | ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype); | 752 | ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype); |
766 | 753 | ||
767 | then = jiffies; | ||
768 | |||
769 | if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { | 754 | if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { |
770 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) { | 755 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) { |
771 | /* only run these if we're shutting down the last cap */ | 756 | /* only run these if we're shutting down the last cap */ |
772 | unsigned long duration; | 757 | unsigned long duration; |
758 | unsigned long then = jiffies; | ||
773 | 759 | ||
774 | then = jiffies; | 760 | add_wait_queue(&itv->eos_waitq, &wait); |
775 | add_wait_queue(&itv->cap_w, &wait); | ||
776 | 761 | ||
777 | set_current_state(TASK_INTERRUPTIBLE); | 762 | set_current_state(TASK_INTERRUPTIBLE); |
778 | 763 | ||
@@ -798,31 +783,12 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
798 | IVTV_DEBUG_INFO("%s: EOS took %lu ms to occur.\n", s->name, duration); | 783 | IVTV_DEBUG_INFO("%s: EOS took %lu ms to occur.\n", s->name, duration); |
799 | } | 784 | } |
800 | set_current_state(TASK_RUNNING); | 785 | set_current_state(TASK_RUNNING); |
801 | remove_wait_queue(&itv->cap_w, &wait); | 786 | remove_wait_queue(&itv->eos_waitq, &wait); |
787 | set_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | ||
802 | } | 788 | } |
803 | 789 | ||
804 | then = jiffies; | 790 | /* Handle any pending interrupts */ |
805 | /* Make sure DMA is complete */ | 791 | ivtv_msleep_timeout(100, 1); |
806 | add_wait_queue(&s->waitq, &wait); | ||
807 | do { | ||
808 | /* check if DMA is pending */ | ||
809 | if ((s->type == IVTV_ENC_STREAM_TYPE_MPG) && /* MPG Only */ | ||
810 | (read_reg(IVTV_REG_DMASTATUS) & 0x02)) { | ||
811 | /* Check for last DMA */ | ||
812 | ivtv_vapi_result(itv, data, CX2341X_ENC_GET_SEQ_END, 2, 0, 0); | ||
813 | |||
814 | if (data[0] == 1) { | ||
815 | IVTV_DEBUG_DMA("%s: Last DMA of size 0x%08x\n", s->name, data[1]); | ||
816 | break; | ||
817 | } | ||
818 | } else if (read_reg(IVTV_REG_DMASTATUS) & 0x02) { | ||
819 | break; | ||
820 | } | ||
821 | } while (!ivtv_msleep_timeout(10, 1) && | ||
822 | then + msecs_to_jiffies(2000) > jiffies); | ||
823 | |||
824 | set_current_state(TASK_RUNNING); | ||
825 | remove_wait_queue(&s->waitq, &wait); | ||
826 | } | 792 | } |
827 | 793 | ||
828 | atomic_dec(&itv->capturing); | 794 | atomic_dec(&itv->capturing); |
@@ -830,19 +796,16 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
830 | /* Clear capture and no-read bits */ | 796 | /* Clear capture and no-read bits */ |
831 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); | 797 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); |
832 | 798 | ||
833 | /* ensure these global cleanup actions are done only once */ | ||
834 | mutex_lock(&itv->serialize_lock); | ||
835 | |||
836 | if (s->type == IVTV_ENC_STREAM_TYPE_VBI) | 799 | if (s->type == IVTV_ENC_STREAM_TYPE_VBI) |
837 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); | 800 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); |
838 | 801 | ||
839 | if (atomic_read(&itv->capturing) > 0) { | 802 | if (atomic_read(&itv->capturing) > 0) { |
840 | mutex_unlock(&itv->serialize_lock); | ||
841 | return 0; | 803 | return 0; |
842 | } | 804 | } |
843 | 805 | ||
844 | /* Set the following Interrupt mask bits for capture */ | 806 | /* Set the following Interrupt mask bits for capture */ |
845 | ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); | 807 | ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); |
808 | del_timer(&itv->dma_timer); | ||
846 | 809 | ||
847 | /* event notification (off) */ | 810 | /* event notification (off) */ |
848 | if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { | 811 | if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { |
@@ -853,7 +816,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
853 | } | 816 | } |
854 | 817 | ||
855 | wake_up(&s->waitq); | 818 | wake_up(&s->waitq); |
856 | mutex_unlock(&itv->serialize_lock); | ||
857 | 819 | ||
858 | return 0; | 820 | return 0; |
859 | } | 821 | } |
@@ -900,6 +862,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) | |||
900 | ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); | 862 | ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); |
901 | 863 | ||
902 | ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_DECODE); | 864 | ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_DECODE); |
865 | del_timer(&itv->dma_timer); | ||
903 | 866 | ||
904 | clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); | 867 | clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); |
905 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); | 868 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); |
diff --git a/drivers/media/video/ivtv/ivtv-streams.h b/drivers/media/video/ivtv/ivtv-streams.h index 8597b75384a7..8f5f5b1c7c89 100644 --- a/drivers/media/video/ivtv/ivtv-streams.h +++ b/drivers/media/video/ivtv/ivtv-streams.h | |||
@@ -18,6 +18,9 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef IVTV_STREAMS_H | ||
22 | #define IVTV_STREAMS_H | ||
23 | |||
21 | int ivtv_streams_setup(struct ivtv *itv); | 24 | int ivtv_streams_setup(struct ivtv *itv); |
22 | void ivtv_streams_cleanup(struct ivtv *itv); | 25 | void ivtv_streams_cleanup(struct ivtv *itv); |
23 | 26 | ||
@@ -29,3 +32,5 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts); | |||
29 | 32 | ||
30 | void ivtv_stop_all_captures(struct ivtv *itv); | 33 | void ivtv_stop_all_captures(struct ivtv *itv); |
31 | int ivtv_passthrough_mode(struct ivtv *itv, int enable); | 34 | int ivtv_passthrough_mode(struct ivtv *itv, int enable); |
35 | |||
36 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c index bd642e1aafc3..c4626d1cdf41 100644 --- a/drivers/media/video/ivtv/ivtv-udma.c +++ b/drivers/media/video/ivtv/ivtv-udma.c | |||
@@ -21,7 +21,6 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include "ivtv-driver.h" | 23 | #include "ivtv-driver.h" |
24 | #include "ivtv-streams.h" | ||
25 | #include "ivtv-udma.h" | 24 | #include "ivtv-udma.h" |
26 | 25 | ||
27 | void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size) | 26 | void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size) |
@@ -38,19 +37,37 @@ void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long | |||
38 | int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset) | 37 | int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset) |
39 | { | 38 | { |
40 | int i, offset; | 39 | int i, offset; |
40 | unsigned long flags; | ||
41 | |||
42 | if (map_offset < 0) | ||
43 | return map_offset; | ||
41 | 44 | ||
42 | offset = dma_page->offset; | 45 | offset = dma_page->offset; |
43 | 46 | ||
44 | /* Fill SG Array with new values */ | 47 | /* Fill SG Array with new values */ |
45 | for (i = 0; i < dma_page->page_count; i++) { | 48 | for (i = 0; i < dma_page->page_count; i++) { |
46 | if (i == dma_page->page_count - 1) { | 49 | unsigned int len = (i == dma_page->page_count - 1) ? |
47 | dma->SGlist[map_offset].length = dma_page->tail; | 50 | dma_page->tail : PAGE_SIZE - offset; |
51 | |||
52 | dma->SGlist[map_offset].length = len; | ||
53 | dma->SGlist[map_offset].offset = offset; | ||
54 | if (PageHighMem(dma->map[map_offset])) { | ||
55 | void *src; | ||
56 | |||
57 | if (dma->bouncemap[map_offset] == NULL) | ||
58 | dma->bouncemap[map_offset] = alloc_page(GFP_KERNEL); | ||
59 | if (dma->bouncemap[map_offset] == NULL) | ||
60 | return -1; | ||
61 | local_irq_save(flags); | ||
62 | src = kmap_atomic(dma->map[map_offset], KM_BOUNCE_READ) + offset; | ||
63 | memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len); | ||
64 | kunmap_atomic(src, KM_BOUNCE_READ); | ||
65 | local_irq_restore(flags); | ||
66 | dma->SGlist[map_offset].page = dma->bouncemap[map_offset]; | ||
48 | } | 67 | } |
49 | else { | 68 | else { |
50 | dma->SGlist[map_offset].length = PAGE_SIZE - offset; | 69 | dma->SGlist[map_offset].page = dma->map[map_offset]; |
51 | } | 70 | } |
52 | dma->SGlist[map_offset].offset = offset; | ||
53 | dma->SGlist[map_offset].page = dma->map[map_offset]; | ||
54 | offset = 0; | 71 | offset = 0; |
55 | map_offset++; | 72 | map_offset++; |
56 | } | 73 | } |
@@ -89,7 +106,7 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, | |||
89 | { | 106 | { |
90 | struct ivtv_dma_page_info user_dma; | 107 | struct ivtv_dma_page_info user_dma; |
91 | struct ivtv_user_dma *dma = &itv->udma; | 108 | struct ivtv_user_dma *dma = &itv->udma; |
92 | int err; | 109 | int i, err; |
93 | 110 | ||
94 | IVTV_DEBUG_DMA("ivtv_udma_setup, dst: 0x%08x\n", (unsigned int)ivtv_dest_addr); | 111 | IVTV_DEBUG_DMA("ivtv_udma_setup, dst: 0x%08x\n", (unsigned int)ivtv_dest_addr); |
95 | 112 | ||
@@ -123,7 +140,13 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, | |||
123 | dma->page_count = user_dma.page_count; | 140 | dma->page_count = user_dma.page_count; |
124 | 141 | ||
125 | /* Fill SG List with new values */ | 142 | /* Fill SG List with new values */ |
126 | ivtv_udma_fill_sg_list(dma, &user_dma, 0); | 143 | if (ivtv_udma_fill_sg_list(dma, &user_dma, 0) < 0) { |
144 | for (i = 0; i < dma->page_count; i++) { | ||
145 | put_page(dma->map[i]); | ||
146 | } | ||
147 | dma->page_count = 0; | ||
148 | return -ENOMEM; | ||
149 | } | ||
127 | 150 | ||
128 | /* Map SG List */ | 151 | /* Map SG List */ |
129 | dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); | 152 | dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); |
@@ -166,6 +189,8 @@ void ivtv_udma_unmap(struct ivtv *itv) | |||
166 | 189 | ||
167 | void ivtv_udma_free(struct ivtv *itv) | 190 | void ivtv_udma_free(struct ivtv *itv) |
168 | { | 191 | { |
192 | int i; | ||
193 | |||
169 | /* Unmap SG Array */ | 194 | /* Unmap SG Array */ |
170 | if (itv->udma.SG_handle) { | 195 | if (itv->udma.SG_handle) { |
171 | pci_unmap_single(itv->dev, itv->udma.SG_handle, | 196 | pci_unmap_single(itv->dev, itv->udma.SG_handle, |
@@ -176,6 +201,11 @@ void ivtv_udma_free(struct ivtv *itv) | |||
176 | if (itv->udma.SG_length) { | 201 | if (itv->udma.SG_length) { |
177 | pci_unmap_sg(itv->dev, itv->udma.SGlist, itv->udma.page_count, PCI_DMA_TODEVICE); | 202 | pci_unmap_sg(itv->dev, itv->udma.SGlist, itv->udma.page_count, PCI_DMA_TODEVICE); |
178 | } | 203 | } |
204 | |||
205 | for (i = 0; i < IVTV_DMA_SG_OSD_ENT; i++) { | ||
206 | if (itv->udma.bouncemap[i]) | ||
207 | __free_page(itv->udma.bouncemap[i]); | ||
208 | } | ||
179 | } | 209 | } |
180 | 210 | ||
181 | void ivtv_udma_start(struct ivtv *itv) | 211 | void ivtv_udma_start(struct ivtv *itv) |
diff --git a/drivers/media/video/ivtv/ivtv-udma.h b/drivers/media/video/ivtv/ivtv-udma.h index e131bccedec0..df727e23be0a 100644 --- a/drivers/media/video/ivtv/ivtv-udma.h +++ b/drivers/media/video/ivtv/ivtv-udma.h | |||
@@ -18,6 +18,9 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef IVTV_UDMA_H | ||
22 | #define IVTV_UDMA_H | ||
23 | |||
21 | /* User DMA functions */ | 24 | /* User DMA functions */ |
22 | void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size); | 25 | void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size); |
23 | int ivtv_udma_fill_sg_list(struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset); | 26 | int ivtv_udma_fill_sg_list(struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset); |
@@ -41,3 +44,5 @@ static inline void ivtv_udma_sync_for_cpu(struct ivtv *itv) | |||
41 | pci_dma_sync_single_for_cpu((struct pci_dev *)itv->dev, itv->udma.SG_handle, | 44 | pci_dma_sync_single_for_cpu((struct pci_dev *)itv->dev, itv->udma.SG_handle, |
42 | sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); | 45 | sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); |
43 | } | 46 | } |
47 | |||
48 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index a7282a91bd97..c151bcf5519a 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c | |||
@@ -18,10 +18,69 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include "ivtv-driver.h" | 20 | #include "ivtv-driver.h" |
21 | #include "ivtv-video.h" | 21 | #include "ivtv-i2c.h" |
22 | #include "ivtv-vbi.h" | ||
23 | #include "ivtv-ioctl.h" | 22 | #include "ivtv-ioctl.h" |
24 | #include "ivtv-queue.h" | 23 | #include "ivtv-queue.h" |
24 | #include "ivtv-vbi.h" | ||
25 | |||
26 | static void ivtv_set_vps(struct ivtv *itv, int enabled) | ||
27 | { | ||
28 | struct v4l2_sliced_vbi_data data; | ||
29 | |||
30 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
31 | return; | ||
32 | data.id = V4L2_SLICED_VPS; | ||
33 | data.field = 0; | ||
34 | data.line = enabled ? 16 : 0; | ||
35 | data.data[2] = itv->vbi.vps_payload.data[0]; | ||
36 | data.data[8] = itv->vbi.vps_payload.data[1]; | ||
37 | data.data[9] = itv->vbi.vps_payload.data[2]; | ||
38 | data.data[10] = itv->vbi.vps_payload.data[3]; | ||
39 | data.data[11] = itv->vbi.vps_payload.data[4]; | ||
40 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | ||
41 | } | ||
42 | |||
43 | static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) | ||
44 | { | ||
45 | struct v4l2_sliced_vbi_data data; | ||
46 | |||
47 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
48 | return; | ||
49 | data.id = V4L2_SLICED_CAPTION_525; | ||
50 | data.field = 0; | ||
51 | data.line = (mode & 1) ? 21 : 0; | ||
52 | data.data[0] = cc->odd[0]; | ||
53 | data.data[1] = cc->odd[1]; | ||
54 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | ||
55 | data.field = 1; | ||
56 | data.line = (mode & 2) ? 21 : 0; | ||
57 | data.data[0] = cc->even[0]; | ||
58 | data.data[1] = cc->even[1]; | ||
59 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | ||
60 | } | ||
61 | |||
62 | static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) | ||
63 | { | ||
64 | struct v4l2_sliced_vbi_data data; | ||
65 | |||
66 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
67 | return; | ||
68 | /* When using a 50 Hz system, always turn on the | ||
69 | wide screen signal with 4x3 ratio as the default. | ||
70 | Turning this signal on and off can confuse certain | ||
71 | TVs. As far as I can tell there is no reason not to | ||
72 | transmit this signal. */ | ||
73 | if ((itv->std & V4L2_STD_625_50) && !enabled) { | ||
74 | enabled = 1; | ||
75 | mode = 0x08; /* 4x3 full format */ | ||
76 | } | ||
77 | data.id = V4L2_SLICED_WSS_625; | ||
78 | data.field = 0; | ||
79 | data.line = enabled ? 23 : 0; | ||
80 | data.data[0] = mode & 0xff; | ||
81 | data.data[1] = (mode >> 8) & 0xff; | ||
82 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | ||
83 | } | ||
25 | 84 | ||
26 | static int odd_parity(u8 c) | 85 | static int odd_parity(u8 c) |
27 | { | 86 | { |
@@ -32,62 +91,50 @@ static int odd_parity(u8 c) | |||
32 | return c & 1; | 91 | return c & 1; |
33 | } | 92 | } |
34 | 93 | ||
35 | static void passthrough_vbi_data(struct ivtv *itv, int cnt) | 94 | void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t cnt) |
36 | { | 95 | { |
37 | int wss = 0; | 96 | struct vbi_info *vi = &itv->vbi; |
38 | u8 cc[4] = { 0x80, 0x80, 0x80, 0x80 }; | 97 | struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; |
39 | u8 vps[13]; | ||
40 | int found_cc = 0; | 98 | int found_cc = 0; |
41 | int found_wss = 0; | 99 | size_t i; |
42 | int found_vps = 0; | ||
43 | int cc_pos = itv->vbi.cc_pos; | ||
44 | int i; | ||
45 | 100 | ||
46 | for (i = 0; i < cnt; i++) { | 101 | for (i = 0; i < cnt; i++) { |
47 | struct v4l2_sliced_vbi_data *d = itv->vbi.sliced_dec_data + i; | 102 | const struct v4l2_sliced_vbi_data *d = sliced + i; |
48 | 103 | ||
49 | if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { | 104 | if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { |
50 | found_cc = 1; | ||
51 | if (d->field) { | 105 | if (d->field) { |
52 | cc[2] = d->data[0]; | 106 | cc.even[0] = d->data[0]; |
53 | cc[3] = d->data[1]; | 107 | cc.even[1] = d->data[1]; |
54 | } else { | 108 | } else { |
55 | cc[0] = d->data[0]; | 109 | cc.odd[0] = d->data[0]; |
56 | cc[1] = d->data[1]; | 110 | cc.odd[1] = d->data[1]; |
57 | } | 111 | } |
112 | found_cc = 1; | ||
58 | } | 113 | } |
59 | else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { | 114 | else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { |
60 | memcpy(vps, d->data, sizeof(vps)); | 115 | struct vbi_vps vps; |
61 | found_vps = 1; | 116 | |
117 | vps.data[0] = d->data[2]; | ||
118 | vps.data[1] = d->data[8]; | ||
119 | vps.data[2] = d->data[9]; | ||
120 | vps.data[3] = d->data[10]; | ||
121 | vps.data[4] = d->data[11]; | ||
122 | if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) { | ||
123 | vi->vps_payload = vps; | ||
124 | set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); | ||
125 | } | ||
62 | } | 126 | } |
63 | else if (d->id == V4L2_SLICED_WSS_625 && d->line == 23 && d->field == 0) { | 127 | else if (d->id == V4L2_SLICED_WSS_625 && d->line == 23 && d->field == 0) { |
64 | wss = d->data[0] | d->data[1] << 8; | 128 | int wss = d->data[0] | d->data[1] << 8; |
65 | found_wss = 1; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | if (itv->vbi.wss_found != found_wss || itv->vbi.wss != wss) { | ||
70 | itv->vbi.wss = wss; | ||
71 | itv->vbi.wss_found = found_wss; | ||
72 | set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); | ||
73 | } | ||
74 | 129 | ||
75 | if (found_vps || itv->vbi.vps_found) { | 130 | if (vi->wss_payload != wss) { |
76 | itv->vbi.vps[0] = vps[2]; | 131 | vi->wss_payload = wss; |
77 | itv->vbi.vps[1] = vps[8]; | 132 | set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); |
78 | itv->vbi.vps[2] = vps[9]; | 133 | } |
79 | itv->vbi.vps[3] = vps[10]; | 134 | } |
80 | itv->vbi.vps[4] = vps[11]; | ||
81 | itv->vbi.vps_found = found_vps; | ||
82 | set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); | ||
83 | } | 135 | } |
84 | 136 | if (found_cc && vi->cc_payload_idx < sizeof(vi->cc_payload)) { | |
85 | if (found_cc && cc_pos < sizeof(itv->vbi.cc_data_even)) { | 137 | vi->cc_payload[vi->cc_payload_idx++] = cc; |
86 | itv->vbi.cc_data_odd[cc_pos] = cc[0]; | ||
87 | itv->vbi.cc_data_odd[cc_pos + 1] = cc[1]; | ||
88 | itv->vbi.cc_data_even[cc_pos] = cc[2]; | ||
89 | itv->vbi.cc_data_even[cc_pos + 1] = cc[3]; | ||
90 | itv->vbi.cc_pos = cc_pos + 2; | ||
91 | set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); | 138 | set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); |
92 | } | 139 | } |
93 | } | 140 | } |
@@ -163,8 +210,8 @@ static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p) | |||
163 | linemask[1] = 0xf; | 210 | linemask[1] = 0xf; |
164 | p += 4; | 211 | p += 4; |
165 | } else { | 212 | } else { |
166 | /* unknown VBI data stream */ | 213 | /* unknown VBI data, convert to empty VBI frame */ |
167 | return 0; | 214 | linemask[0] = linemask[1] = 0; |
168 | } | 215 | } |
169 | for (i = 0; i < 36; i++) { | 216 | for (i = 0; i < 36; i++) { |
170 | int err = 0; | 217 | int err = 0; |
@@ -211,69 +258,6 @@ static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p) | |||
211 | return line * sizeof(itv->vbi.sliced_dec_data[0]); | 258 | return line * sizeof(itv->vbi.sliced_dec_data[0]); |
212 | } | 259 | } |
213 | 260 | ||
214 | ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count) | ||
215 | { | ||
216 | /* Should be a __user pointer, but sparse doesn't parse this bit correctly. */ | ||
217 | const struct v4l2_sliced_vbi_data *p = (const struct v4l2_sliced_vbi_data *)ubuf; | ||
218 | u8 cc[4] = { 0x80, 0x80, 0x80, 0x80 }; | ||
219 | int found_cc = 0; | ||
220 | int cc_pos = itv->vbi.cc_pos; | ||
221 | |||
222 | while (count >= sizeof(struct v4l2_sliced_vbi_data)) { | ||
223 | switch (p->id) { | ||
224 | case V4L2_SLICED_CAPTION_525: | ||
225 | if (p->line == 21) { | ||
226 | found_cc = 1; | ||
227 | if (p->field) { | ||
228 | cc[2] = p->data[0]; | ||
229 | cc[3] = p->data[1]; | ||
230 | } else { | ||
231 | cc[0] = p->data[0]; | ||
232 | cc[1] = p->data[1]; | ||
233 | } | ||
234 | } | ||
235 | break; | ||
236 | |||
237 | case V4L2_SLICED_VPS: | ||
238 | if (p->line == 16 && p->field == 0) { | ||
239 | itv->vbi.vps[0] = p->data[2]; | ||
240 | itv->vbi.vps[1] = p->data[8]; | ||
241 | itv->vbi.vps[2] = p->data[9]; | ||
242 | itv->vbi.vps[3] = p->data[10]; | ||
243 | itv->vbi.vps[4] = p->data[11]; | ||
244 | itv->vbi.vps_found = 1; | ||
245 | set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); | ||
246 | } | ||
247 | break; | ||
248 | |||
249 | case V4L2_SLICED_WSS_625: | ||
250 | if (p->line == 23 && p->field == 0) { | ||
251 | /* No lock needed for WSS */ | ||
252 | itv->vbi.wss = p->data[0] | (p->data[1] << 8); | ||
253 | itv->vbi.wss_found = 1; | ||
254 | set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); | ||
255 | } | ||
256 | break; | ||
257 | |||
258 | default: | ||
259 | break; | ||
260 | } | ||
261 | count -= sizeof(*p); | ||
262 | p++; | ||
263 | } | ||
264 | |||
265 | if (found_cc && cc_pos < sizeof(itv->vbi.cc_data_even)) { | ||
266 | itv->vbi.cc_data_odd[cc_pos] = cc[0]; | ||
267 | itv->vbi.cc_data_odd[cc_pos + 1] = cc[1]; | ||
268 | itv->vbi.cc_data_even[cc_pos] = cc[2]; | ||
269 | itv->vbi.cc_data_even[cc_pos + 1] = cc[3]; | ||
270 | itv->vbi.cc_pos = cc_pos + 2; | ||
271 | set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); | ||
272 | } | ||
273 | |||
274 | return (const char __user *)p - ubuf; | ||
275 | } | ||
276 | |||
277 | /* Compress raw VBI format, removes leading SAV codes and surplus space after the | 261 | /* Compress raw VBI format, removes leading SAV codes and surplus space after the |
278 | field. | 262 | field. |
279 | Returns new compressed size. */ | 263 | Returns new compressed size. */ |
@@ -422,108 +406,95 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, | |||
422 | memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt); | 406 | memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt); |
423 | buf->bytesused = cnt; | 407 | buf->bytesused = cnt; |
424 | 408 | ||
425 | passthrough_vbi_data(itv, cnt / sizeof(itv->vbi.sliced_dec_data[0])); | 409 | ivtv_write_vbi(itv, itv->vbi.sliced_dec_data, |
410 | cnt / sizeof(itv->vbi.sliced_dec_data[0])); | ||
426 | return; | 411 | return; |
427 | } | 412 | } |
428 | } | 413 | } |
429 | 414 | ||
430 | void ivtv_disable_vbi(struct ivtv *itv) | 415 | void ivtv_disable_cc(struct ivtv *itv) |
431 | { | 416 | { |
432 | clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); | 417 | struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; |
433 | clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); | 418 | |
434 | clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); | 419 | clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); |
435 | ivtv_set_wss(itv, 0, 0); | 420 | ivtv_set_cc(itv, 0, &cc); |
436 | ivtv_set_cc(itv, 0, 0, 0, 0, 0); | 421 | itv->vbi.cc_payload_idx = 0; |
437 | ivtv_set_vps(itv, 0, 0, 0, 0, 0, 0); | ||
438 | itv->vbi.vps_found = itv->vbi.wss_found = 0; | ||
439 | itv->vbi.wss = 0; | ||
440 | itv->vbi.cc_pos = 0; | ||
441 | } | 422 | } |
442 | 423 | ||
443 | 424 | ||
444 | void ivtv_vbi_work_handler(struct ivtv *itv) | 425 | void ivtv_vbi_work_handler(struct ivtv *itv) |
445 | { | 426 | { |
427 | struct vbi_info *vi = &itv->vbi; | ||
446 | struct v4l2_sliced_vbi_data data; | 428 | struct v4l2_sliced_vbi_data data; |
429 | struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; | ||
447 | 430 | ||
448 | /* Lock */ | 431 | /* Lock */ |
449 | if (itv->output_mode == OUT_PASSTHROUGH) { | 432 | if (itv->output_mode == OUT_PASSTHROUGH) { |
450 | /* Note: currently only the saa7115 is used in a PVR350, | ||
451 | so these commands are for now saa7115 specific. */ | ||
452 | if (itv->is_50hz) { | 433 | if (itv->is_50hz) { |
453 | data.id = V4L2_SLICED_WSS_625; | 434 | data.id = V4L2_SLICED_WSS_625; |
454 | data.field = 0; | 435 | data.field = 0; |
455 | 436 | ||
456 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { | 437 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { |
457 | ivtv_set_wss(itv, 1, data.data[0] & 0xf); | 438 | ivtv_set_wss(itv, 1, data.data[0] & 0xf); |
458 | itv->vbi.wss_no_update = 0; | 439 | vi->wss_missing_cnt = 0; |
459 | } else if (itv->vbi.wss_no_update == 4) { | 440 | } else if (vi->wss_missing_cnt == 4) { |
460 | ivtv_set_wss(itv, 1, 0x8); /* 4x3 full format */ | 441 | ivtv_set_wss(itv, 1, 0x8); /* 4x3 full format */ |
461 | } else { | 442 | } else { |
462 | itv->vbi.wss_no_update++; | 443 | vi->wss_missing_cnt++; |
463 | } | 444 | } |
464 | } | 445 | } |
465 | else { | 446 | else { |
466 | u8 c1 = 0, c2 = 0, c3 = 0, c4 = 0; | ||
467 | int mode = 0; | 447 | int mode = 0; |
468 | 448 | ||
469 | data.id = V4L2_SLICED_CAPTION_525; | 449 | data.id = V4L2_SLICED_CAPTION_525; |
470 | data.field = 0; | 450 | data.field = 0; |
471 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { | 451 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { |
472 | mode |= 1; | 452 | mode |= 1; |
473 | c1 = data.data[0]; | 453 | cc.odd[0] = data.data[0]; |
474 | c2 = data.data[1]; | 454 | cc.odd[1] = data.data[1]; |
475 | } | 455 | } |
476 | data.field = 1; | 456 | data.field = 1; |
477 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { | 457 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { |
478 | mode |= 2; | 458 | mode |= 2; |
479 | c3 = data.data[0]; | 459 | cc.even[0] = data.data[0]; |
480 | c4 = data.data[1]; | 460 | cc.even[1] = data.data[1]; |
481 | } | 461 | } |
482 | if (mode) { | 462 | if (mode) { |
483 | itv->vbi.cc_no_update = 0; | 463 | vi->cc_missing_cnt = 0; |
484 | ivtv_set_cc(itv, mode, c1, c2, c3, c4); | 464 | ivtv_set_cc(itv, mode, &cc); |
485 | } else if (itv->vbi.cc_no_update == 4) { | 465 | } else if (vi->cc_missing_cnt == 4) { |
486 | ivtv_set_cc(itv, 0, 0, 0, 0, 0); | 466 | ivtv_set_cc(itv, 0, &cc); |
487 | } else { | 467 | } else { |
488 | itv->vbi.cc_no_update++; | 468 | vi->cc_missing_cnt++; |
489 | } | 469 | } |
490 | } | 470 | } |
491 | return; | 471 | return; |
492 | } | 472 | } |
493 | 473 | ||
494 | if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) { | 474 | if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) { |
495 | /* Lock */ | 475 | ivtv_set_wss(itv, 1, vi->wss_payload & 0xf); |
496 | ivtv_set_wss(itv, itv->vbi.wss_found, itv->vbi.wss & 0xf); | ||
497 | } | 476 | } |
498 | 477 | ||
499 | if (test_and_clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) { | 478 | if (test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) { |
500 | if (itv->vbi.cc_pos == 0) { | 479 | if (vi->cc_payload_idx == 0) { |
501 | ivtv_set_cc(itv, 3, 0x80, 0x80, 0x80, 0x80); | 480 | clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); |
481 | ivtv_set_cc(itv, 3, &cc); | ||
502 | } | 482 | } |
503 | while (itv->vbi.cc_pos) { | 483 | while (vi->cc_payload_idx) { |
504 | u8 cc_odd0 = itv->vbi.cc_data_odd[0]; | 484 | cc = vi->cc_payload[0]; |
505 | u8 cc_odd1 = itv->vbi.cc_data_odd[1]; | 485 | |
506 | u8 cc_even0 = itv->vbi.cc_data_even[0]; | 486 | memcpy(vi->cc_payload, vi->cc_payload + 1, |
507 | u8 cc_even1 = itv->vbi.cc_data_even[1]; | 487 | sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0])); |
508 | 488 | vi->cc_payload_idx--; | |
509 | memcpy(itv->vbi.cc_data_odd, itv->vbi.cc_data_odd + 2, sizeof(itv->vbi.cc_data_odd) - 2); | 489 | if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80) |
510 | memcpy(itv->vbi.cc_data_even, itv->vbi.cc_data_even + 2, sizeof(itv->vbi.cc_data_even) - 2); | ||
511 | itv->vbi.cc_pos -= 2; | ||
512 | if (itv->vbi.cc_pos && cc_odd0 == 0x80 && cc_odd1 == 0x80) | ||
513 | continue; | 490 | continue; |
514 | 491 | ||
515 | /* Send to Saa7127 */ | 492 | ivtv_set_cc(itv, 3, &cc); |
516 | ivtv_set_cc(itv, 3, cc_odd0, cc_odd1, cc_even0, cc_even1); | ||
517 | if (itv->vbi.cc_pos == 0) | ||
518 | set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); | ||
519 | break; | 493 | break; |
520 | } | 494 | } |
521 | } | 495 | } |
522 | 496 | ||
523 | if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) { | 497 | if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) { |
524 | /* Lock */ | 498 | ivtv_set_vps(itv, 1); |
525 | ivtv_set_vps(itv, itv->vbi.vps_found, | ||
526 | itv->vbi.vps[0], itv->vbi.vps[1], | ||
527 | itv->vbi.vps[2], itv->vbi.vps[3], itv->vbi.vps[4]); | ||
528 | } | 499 | } |
529 | } | 500 | } |
diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h index ec211b49702c..970567b9194d 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.h +++ b/drivers/media/video/ivtv/ivtv-vbi.h | |||
@@ -17,10 +17,15 @@ | |||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | 19 | ||
20 | ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count); | 20 | #ifndef IVTV_VBI_H |
21 | #define IVTV_VBI_H | ||
22 | |||
23 | void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t count); | ||
21 | void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, | 24 | void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, |
22 | u64 pts_stamp, int streamtype); | 25 | u64 pts_stamp, int streamtype); |
23 | int ivtv_used_line(struct ivtv *itv, int line, int field); | 26 | int ivtv_used_line(struct ivtv *itv, int line, int field); |
24 | void ivtv_disable_vbi(struct ivtv *itv); | 27 | void ivtv_disable_cc(struct ivtv *itv); |
25 | void ivtv_set_vbi(unsigned long arg); | 28 | void ivtv_set_vbi(unsigned long arg); |
26 | void ivtv_vbi_work_handler(struct ivtv *itv); | 29 | void ivtv_vbi_work_handler(struct ivtv *itv); |
30 | |||
31 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h index 85530a3cd369..d050de2a7229 100644 --- a/drivers/media/video/ivtv/ivtv-version.h +++ b/drivers/media/video/ivtv/ivtv-version.h | |||
@@ -17,10 +17,15 @@ | |||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #ifndef IVTV_VERSION_H | ||
21 | #define IVTV_VERSION_H | ||
22 | |||
20 | #define IVTV_DRIVER_NAME "ivtv" | 23 | #define IVTV_DRIVER_NAME "ivtv" |
21 | #define IVTV_DRIVER_VERSION_MAJOR 1 | 24 | #define IVTV_DRIVER_VERSION_MAJOR 1 |
22 | #define IVTV_DRIVER_VERSION_MINOR 0 | 25 | #define IVTV_DRIVER_VERSION_MINOR 1 |
23 | #define IVTV_DRIVER_VERSION_PATCHLEVEL 0 | 26 | #define IVTV_DRIVER_VERSION_PATCHLEVEL 0 |
24 | 27 | ||
25 | #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL) | 28 | #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL) |
26 | #define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL) | 29 | #define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL) |
30 | |||
31 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index bcea09542e5a..e2288f224ab6 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c | |||
@@ -19,11 +19,16 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include "ivtv-driver.h" | 21 | #include "ivtv-driver.h" |
22 | #include "ivtv-queue.h" | ||
23 | #include "ivtv-udma.h" | 22 | #include "ivtv-udma.h" |
24 | #include "ivtv-irq.h" | ||
25 | #include "ivtv-yuv.h" | 23 | #include "ivtv-yuv.h" |
26 | 24 | ||
25 | const u32 yuv_offset[4] = { | ||
26 | IVTV_YUV_BUFFER_OFFSET, | ||
27 | IVTV_YUV_BUFFER_OFFSET_1, | ||
28 | IVTV_YUV_BUFFER_OFFSET_2, | ||
29 | IVTV_YUV_BUFFER_OFFSET_3 | ||
30 | }; | ||
31 | |||
27 | static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, | 32 | static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, |
28 | struct ivtv_dma_frame *args) | 33 | struct ivtv_dma_frame *args) |
29 | { | 34 | { |
@@ -37,7 +42,7 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, | |||
37 | int y_decode_height, uv_decode_height, y_size; | 42 | int y_decode_height, uv_decode_height, y_size; |
38 | int frame = atomic_read(&itv->yuv_info.next_fill_frame); | 43 | int frame = atomic_read(&itv->yuv_info.next_fill_frame); |
39 | 44 | ||
40 | y_buffer_offset = IVTV_DEC_MEM_START + yuv_offset[frame]; | 45 | y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame]; |
41 | uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET; | 46 | uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET; |
42 | 47 | ||
43 | y_decode_height = uv_decode_height = args->src.height + args->src.top; | 48 | y_decode_height = uv_decode_height = args->src.height + args->src.top; |
@@ -83,7 +88,14 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, | |||
83 | } | 88 | } |
84 | 89 | ||
85 | /* Fill & map SG List */ | 90 | /* Fill & map SG List */ |
86 | ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)); | 91 | if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) { |
92 | IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n"); | ||
93 | for (i = 0; i < dma->page_count; i++) { | ||
94 | put_page(dma->map[i]); | ||
95 | } | ||
96 | dma->page_count = 0; | ||
97 | return -ENOMEM; | ||
98 | } | ||
87 | dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); | 99 | dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); |
88 | 100 | ||
89 | /* Fill SG Array with new values */ | 101 | /* Fill SG Array with new values */ |
@@ -94,7 +106,7 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, | |||
94 | if (itv->yuv_info.blanking_dmaptr) { | 106 | if (itv->yuv_info.blanking_dmaptr) { |
95 | dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16); | 107 | dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16); |
96 | dma->SGarray[dma->SG_length].src = cpu_to_le32(itv->yuv_info.blanking_dmaptr); | 108 | dma->SGarray[dma->SG_length].src = cpu_to_le32(itv->yuv_info.blanking_dmaptr); |
97 | dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DEC_MEM_START + yuv_offset[frame]); | 109 | dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]); |
98 | dma->SG_length++; | 110 | dma->SG_length++; |
99 | } | 111 | } |
100 | } | 112 | } |
@@ -612,7 +624,6 @@ static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *wi | |||
612 | itv->yuv_info.v_filter_2 = v_filter_2; | 624 | itv->yuv_info.v_filter_2 = v_filter_2; |
613 | } | 625 | } |
614 | 626 | ||
615 | itv->yuv_info.frame_interlaced_last = itv->yuv_info.frame_interlaced; | ||
616 | } | 627 | } |
617 | 628 | ||
618 | /* Modify the supplied coordinate information to fit the visible osd area */ | 629 | /* Modify the supplied coordinate information to fit the visible osd area */ |
@@ -799,6 +810,7 @@ static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *windo | |||
799 | (itv->yuv_info.old_frame_info.src_y != window->src_y) || | 810 | (itv->yuv_info.old_frame_info.src_y != window->src_y) || |
800 | (itv->yuv_info.old_frame_info.pan_y != window->pan_y) || | 811 | (itv->yuv_info.old_frame_info.pan_y != window->pan_y) || |
801 | (itv->yuv_info.old_frame_info.vis_h != window->vis_h) || | 812 | (itv->yuv_info.old_frame_info.vis_h != window->vis_h) || |
813 | (itv->yuv_info.old_frame_info.lace_mode != window->lace_mode) || | ||
802 | (itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) || | 814 | (itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) || |
803 | (itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) { | 815 | (itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) { |
804 | yuv_update |= IVTV_YUV_UPDATE_VERTICAL; | 816 | yuv_update |= IVTV_YUV_UPDATE_VERTICAL; |
@@ -898,8 +910,21 @@ static void ivtv_yuv_init (struct ivtv *itv) | |||
898 | itv->yuv_info.decode_height = 480; | 910 | itv->yuv_info.decode_height = 480; |
899 | 911 | ||
900 | /* If no visible size set, assume full size */ | 912 | /* If no visible size set, assume full size */ |
901 | if (!itv->yuv_info.osd_vis_w) itv->yuv_info.osd_vis_w = 720 - itv->yuv_info.osd_x_offset; | 913 | if (!itv->yuv_info.osd_vis_w) |
902 | if (!itv->yuv_info.osd_vis_h) itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset; | 914 | itv->yuv_info.osd_vis_w = 720 - itv->yuv_info.osd_x_offset; |
915 | |||
916 | if (!itv->yuv_info.osd_vis_h) { | ||
917 | itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset; | ||
918 | } else { | ||
919 | /* If output video standard has changed, requested height may | ||
920 | not be legal */ | ||
921 | if (itv->yuv_info.osd_vis_h + itv->yuv_info.osd_y_offset > itv->yuv_info.decode_height) { | ||
922 | IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n", | ||
923 | itv->yuv_info.osd_vis_h + itv->yuv_info.osd_y_offset, | ||
924 | itv->yuv_info.decode_height); | ||
925 | itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset; | ||
926 | } | ||
927 | } | ||
903 | 928 | ||
904 | /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ | 929 | /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ |
905 | itv->yuv_info.blanking_ptr = kzalloc(720*16,GFP_KERNEL); | 930 | itv->yuv_info.blanking_ptr = kzalloc(720*16,GFP_KERNEL); |
@@ -927,6 +952,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | |||
927 | int rc = 0; | 952 | int rc = 0; |
928 | int got_sig = 0; | 953 | int got_sig = 0; |
929 | int frame, next_fill_frame, last_fill_frame; | 954 | int frame, next_fill_frame, last_fill_frame; |
955 | int register_update = 0; | ||
930 | 956 | ||
931 | IVTV_DEBUG_INFO("yuv_prep_frame\n"); | 957 | IVTV_DEBUG_INFO("yuv_prep_frame\n"); |
932 | 958 | ||
@@ -940,6 +966,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | |||
940 | /* Buffers are full - Overwrite the last frame */ | 966 | /* Buffers are full - Overwrite the last frame */ |
941 | next_fill_frame = frame; | 967 | next_fill_frame = frame; |
942 | frame = (frame - 1) & 3; | 968 | frame = (frame - 1) & 3; |
969 | register_update = itv->yuv_info.new_frame_info[frame].update; | ||
943 | } | 970 | } |
944 | 971 | ||
945 | /* Take a snapshot of the yuv coordinate information */ | 972 | /* Take a snapshot of the yuv coordinate information */ |
@@ -955,6 +982,9 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | |||
955 | itv->yuv_info.new_frame_info[frame].tru_w = args->src_width; | 982 | itv->yuv_info.new_frame_info[frame].tru_w = args->src_width; |
956 | itv->yuv_info.new_frame_info[frame].tru_h = args->src_height; | 983 | itv->yuv_info.new_frame_info[frame].tru_h = args->src_height; |
957 | 984 | ||
985 | /* Snapshot field order */ | ||
986 | itv->yuv_info.sync_field[frame] = itv->yuv_info.lace_sync_field; | ||
987 | |||
958 | /* Are we going to offset the Y plane */ | 988 | /* Are we going to offset the Y plane */ |
959 | if (args->src.height + args->src.top < 512-16) | 989 | if (args->src.height + args->src.top < 512-16) |
960 | itv->yuv_info.new_frame_info[frame].offset_y = 1; | 990 | itv->yuv_info.new_frame_info[frame].offset_y = 1; |
@@ -970,6 +1000,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | |||
970 | itv->yuv_info.new_frame_info[frame].update = 0; | 1000 | itv->yuv_info.new_frame_info[frame].update = 0; |
971 | itv->yuv_info.new_frame_info[frame].interlaced_y = 0; | 1001 | itv->yuv_info.new_frame_info[frame].interlaced_y = 0; |
972 | itv->yuv_info.new_frame_info[frame].interlaced_uv = 0; | 1002 | itv->yuv_info.new_frame_info[frame].interlaced_uv = 0; |
1003 | itv->yuv_info.new_frame_info[frame].lace_mode = itv->yuv_info.lace_mode; | ||
973 | 1004 | ||
974 | if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame], | 1005 | if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame], |
975 | sizeof (itv->yuv_info.new_frame_info[frame]))) { | 1006 | sizeof (itv->yuv_info.new_frame_info[frame]))) { |
@@ -978,6 +1009,14 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | |||
978 | /* IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */ | 1009 | /* IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */ |
979 | } | 1010 | } |
980 | 1011 | ||
1012 | itv->yuv_info.new_frame_info[frame].update |= register_update; | ||
1013 | |||
1014 | /* Should this frame be delayed ? */ | ||
1015 | if (itv->yuv_info.sync_field[frame] != itv->yuv_info.sync_field[(frame - 1) & 3]) | ||
1016 | itv->yuv_info.field_delay[frame] = 1; | ||
1017 | else | ||
1018 | itv->yuv_info.field_delay[frame] = 0; | ||
1019 | |||
981 | /* DMA the frame */ | 1020 | /* DMA the frame */ |
982 | mutex_lock(&itv->udma.lock); | 1021 | mutex_lock(&itv->udma.lock); |
983 | 1022 | ||
diff --git a/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/video/ivtv/ivtv-yuv.h index 88972d3f77c4..f7215eeca018 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.h +++ b/drivers/media/video/ivtv/ivtv-yuv.h | |||
@@ -18,7 +18,28 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef IVTV_YUV_H | ||
22 | #define IVTV_YUV_H | ||
23 | |||
24 | /* Buffers on hardware offsets */ | ||
25 | #define IVTV_YUV_BUFFER_OFFSET 0x001a8600 /* First YUV Buffer */ | ||
26 | #define IVTV_YUV_BUFFER_OFFSET_1 0x00240400 /* Second YUV Buffer */ | ||
27 | #define IVTV_YUV_BUFFER_OFFSET_2 0x002d8200 /* Third YUV Buffer */ | ||
28 | #define IVTV_YUV_BUFFER_OFFSET_3 0x00370000 /* Fourth YUV Buffer */ | ||
29 | #define IVTV_YUV_BUFFER_UV_OFFSET 0x65400 /* Offset to UV Buffer */ | ||
30 | |||
31 | /* Offset to filter table in firmware */ | ||
32 | #define IVTV_YUV_HORIZONTAL_FILTER_OFFSET 0x025d8 | ||
33 | #define IVTV_YUV_VERTICAL_FILTER_OFFSET 0x03358 | ||
34 | |||
35 | #define IVTV_YUV_UPDATE_HORIZONTAL 0x01 | ||
36 | #define IVTV_YUV_UPDATE_VERTICAL 0x02 | ||
37 | |||
38 | extern const u32 yuv_offset[4]; | ||
39 | |||
21 | int ivtv_yuv_filter_check(struct ivtv *itv); | 40 | int ivtv_yuv_filter_check(struct ivtv *itv); |
22 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args); | 41 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args); |
23 | void ivtv_yuv_close(struct ivtv *itv); | 42 | void ivtv_yuv_close(struct ivtv *itv); |
24 | void ivtv_yuv_work_handler (struct ivtv *itv); | 43 | void ivtv_yuv_work_handler (struct ivtv *itv); |
44 | |||
45 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c new file mode 100644 index 000000000000..9684048fe56c --- /dev/null +++ b/drivers/media/video/ivtv/ivtvfb.c | |||
@@ -0,0 +1,1190 @@ | |||
1 | /* | ||
2 | On Screen Display cx23415 Framebuffer driver | ||
3 | |||
4 | This module presents the cx23415 OSD (onscreen display) framebuffer memory | ||
5 | as a standard Linux /dev/fb style framebuffer device. The framebuffer has | ||
6 | support for 8, 16 & 32 bpp packed pixel formats with alpha channel. In 16bpp | ||
7 | mode, there is a choice of a three color depths (12, 15 or 16 bits), but no | ||
8 | local alpha. The colorspace is selectable between rgb & yuv. | ||
9 | Depending on the TV standard configured in the ivtv module at load time, | ||
10 | the initial resolution is either 640x400 (NTSC) or 640x480 (PAL) at 8bpp. | ||
11 | Video timings are locked to ensure a vertical refresh rate of 50Hz (PAL) | ||
12 | or 59.94 (NTSC) | ||
13 | |||
14 | Copyright (c) 2003 Matt T. Yourst <yourst@yourst.com> | ||
15 | |||
16 | Derived from drivers/video/vesafb.c | ||
17 | Portions (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> | ||
18 | |||
19 | 2.6 kernel port: | ||
20 | Copyright (C) 2004 Matthias Badaire | ||
21 | |||
22 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
23 | |||
24 | Copyright (C) 2006 Ian Armstrong <ian@iarmst.demon.co.uk> | ||
25 | |||
26 | This program is free software; you can redistribute it and/or modify | ||
27 | it under the terms of the GNU General Public License as published by | ||
28 | the Free Software Foundation; either version 2 of the License, or | ||
29 | (at your option) any later version. | ||
30 | |||
31 | This program is distributed in the hope that it will be useful, | ||
32 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
33 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
34 | GNU General Public License for more details. | ||
35 | |||
36 | You should have received a copy of the GNU General Public License | ||
37 | along with this program; if not, write to the Free Software | ||
38 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
39 | */ | ||
40 | |||
41 | #include <linux/module.h> | ||
42 | #include <linux/kernel.h> | ||
43 | #include <linux/fb.h> | ||
44 | #include <linux/ivtvfb.h> | ||
45 | |||
46 | #ifdef CONFIG_MTRR | ||
47 | #include <asm/mtrr.h> | ||
48 | #endif | ||
49 | |||
50 | #include "ivtv-driver.h" | ||
51 | #include "ivtv-udma.h" | ||
52 | #include "ivtv-mailbox.h" | ||
53 | |||
54 | /* card parameters */ | ||
55 | static int ivtvfb_card_id = -1; | ||
56 | static int ivtvfb_debug = 0; | ||
57 | static int osd_laced; | ||
58 | static int osd_compat; | ||
59 | static int osd_depth; | ||
60 | static int osd_upper; | ||
61 | static int osd_left; | ||
62 | static int osd_yres; | ||
63 | static int osd_xres; | ||
64 | |||
65 | module_param(ivtvfb_card_id, int, 0444); | ||
66 | module_param_named(debug,ivtvfb_debug, int, 0644); | ||
67 | module_param(osd_laced, bool, 0444); | ||
68 | module_param(osd_compat, bool, 0444); | ||
69 | module_param(osd_depth, int, 0444); | ||
70 | module_param(osd_upper, int, 0444); | ||
71 | module_param(osd_left, int, 0444); | ||
72 | module_param(osd_yres, int, 0444); | ||
73 | module_param(osd_xres, int, 0444); | ||
74 | |||
75 | MODULE_PARM_DESC(ivtvfb_card_id, | ||
76 | "Only use framebuffer of the specified ivtv card (0-31)\n" | ||
77 | "\t\t\tdefault -1: initialize all available framebuffers"); | ||
78 | |||
79 | MODULE_PARM_DESC(debug, | ||
80 | "Debug level (bitmask). Default: errors only\n" | ||
81 | "\t\t\t(debug = 3 gives full debugging)"); | ||
82 | |||
83 | MODULE_PARM_DESC(osd_compat, | ||
84 | "Compatibility mode - Display size is locked (use for old X drivers)\n" | ||
85 | "\t\t\t0=off\n" | ||
86 | "\t\t\t1=on\n" | ||
87 | "\t\t\tdefault off"); | ||
88 | |||
89 | /* Why upper, left, xres, yres, depth, laced ? To match terminology used | ||
90 | by fbset. | ||
91 | Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */ | ||
92 | |||
93 | MODULE_PARM_DESC(osd_laced, | ||
94 | "Interlaced mode\n" | ||
95 | "\t\t\t0=off\n" | ||
96 | "\t\t\t1=on\n" | ||
97 | "\t\t\tdefault off"); | ||
98 | |||
99 | MODULE_PARM_DESC(osd_depth, | ||
100 | "Bits per pixel - 8, 16, 32\n" | ||
101 | "\t\t\tdefault 8"); | ||
102 | |||
103 | MODULE_PARM_DESC(osd_upper, | ||
104 | "Vertical start position\n" | ||
105 | "\t\t\tdefault 0 (Centered)"); | ||
106 | |||
107 | MODULE_PARM_DESC(osd_left, | ||
108 | "Horizontal start position\n" | ||
109 | "\t\t\tdefault 0 (Centered)"); | ||
110 | |||
111 | MODULE_PARM_DESC(osd_yres, | ||
112 | "Display height\n" | ||
113 | "\t\t\tdefault 480 (PAL)\n" | ||
114 | "\t\t\t 400 (NTSC)"); | ||
115 | |||
116 | MODULE_PARM_DESC(osd_xres, | ||
117 | "Display width\n" | ||
118 | "\t\t\tdefault 640"); | ||
119 | |||
120 | MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong"); | ||
121 | MODULE_LICENSE("GPL"); | ||
122 | |||
123 | /* --------------------------------------------------------------------- */ | ||
124 | |||
125 | #define IVTVFB_DBGFLG_WARN (1 << 0) | ||
126 | #define IVTVFB_DBGFLG_INFO (1 << 1) | ||
127 | |||
128 | #define IVTVFB_DEBUG(x, type, fmt, args...) \ | ||
129 | do { \ | ||
130 | if ((x) & ivtvfb_debug) \ | ||
131 | printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->num , ## args); \ | ||
132 | } while (0) | ||
133 | #define IVTVFB_DEBUG_WARN(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args) | ||
134 | #define IVTVFB_DEBUG_INFO(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args) | ||
135 | |||
136 | /* Standard kernel messages */ | ||
137 | #define IVTVFB_ERR(fmt, args...) printk(KERN_ERR "ivtvfb%d: " fmt, itv->num , ## args) | ||
138 | #define IVTVFB_WARN(fmt, args...) printk(KERN_WARNING "ivtvfb%d: " fmt, itv->num , ## args) | ||
139 | #define IVTVFB_INFO(fmt, args...) printk(KERN_INFO "ivtvfb%d: " fmt, itv->num , ## args) | ||
140 | |||
141 | /* --------------------------------------------------------------------- */ | ||
142 | |||
143 | #define IVTV_OSD_MAX_WIDTH 720 | ||
144 | #define IVTV_OSD_MAX_HEIGHT 576 | ||
145 | |||
146 | #define IVTV_OSD_BPP_8 0x00 | ||
147 | #define IVTV_OSD_BPP_16_444 0x03 | ||
148 | #define IVTV_OSD_BPP_16_555 0x02 | ||
149 | #define IVTV_OSD_BPP_16_565 0x01 | ||
150 | #define IVTV_OSD_BPP_32 0x04 | ||
151 | |||
152 | struct osd_info { | ||
153 | /* Physical base address */ | ||
154 | unsigned long video_pbase; | ||
155 | /* Relative base address (relative to start of decoder memory) */ | ||
156 | u32 video_rbase; | ||
157 | /* Mapped base address */ | ||
158 | volatile char __iomem *video_vbase; | ||
159 | /* Buffer size */ | ||
160 | u32 video_buffer_size; | ||
161 | |||
162 | #ifdef CONFIG_MTRR | ||
163 | /* video_base rounded down as required by hardware MTRRs */ | ||
164 | unsigned long fb_start_aligned_physaddr; | ||
165 | /* video_base rounded up as required by hardware MTRRs */ | ||
166 | unsigned long fb_end_aligned_physaddr; | ||
167 | #endif | ||
168 | |||
169 | /* Current osd mode */ | ||
170 | int osd_mode; | ||
171 | |||
172 | /* Store the buffer offset */ | ||
173 | int set_osd_coords_x; | ||
174 | int set_osd_coords_y; | ||
175 | |||
176 | /* Current dimensions (NOT VISIBLE SIZE!) */ | ||
177 | int display_width; | ||
178 | int display_height; | ||
179 | int display_byte_stride; | ||
180 | |||
181 | /* Current bits per pixel */ | ||
182 | int bits_per_pixel; | ||
183 | int bytes_per_pixel; | ||
184 | |||
185 | /* Frame buffer stuff */ | ||
186 | struct fb_info ivtvfb_info; | ||
187 | struct fb_var_screeninfo ivtvfb_defined; | ||
188 | struct fb_fix_screeninfo ivtvfb_fix; | ||
189 | }; | ||
190 | |||
191 | struct ivtv_osd_coords { | ||
192 | unsigned long offset; | ||
193 | unsigned long max_offset; | ||
194 | int pixel_stride; | ||
195 | int lines; | ||
196 | int x; | ||
197 | int y; | ||
198 | }; | ||
199 | |||
200 | /* --------------------------------------------------------------------- */ | ||
201 | |||
202 | /* ivtv API calls for framebuffer related support */ | ||
203 | |||
204 | static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase, | ||
205 | u32 *fblength) | ||
206 | { | ||
207 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
208 | int rc; | ||
209 | |||
210 | rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0); | ||
211 | *fbbase = data[0]; | ||
212 | *fblength = data[1]; | ||
213 | return rc; | ||
214 | } | ||
215 | |||
216 | static int ivtvfb_get_osd_coords(struct ivtv *itv, | ||
217 | struct ivtv_osd_coords *osd) | ||
218 | { | ||
219 | struct osd_info *oi = itv->osd_info; | ||
220 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
221 | |||
222 | ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0); | ||
223 | |||
224 | osd->offset = data[0] - oi->video_rbase; | ||
225 | osd->max_offset = oi->display_width * oi->display_height * 4; | ||
226 | osd->pixel_stride = data[1]; | ||
227 | osd->lines = data[2]; | ||
228 | osd->x = data[3]; | ||
229 | osd->y = data[4]; | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd) | ||
234 | { | ||
235 | struct osd_info *oi = itv->osd_info; | ||
236 | |||
237 | oi->display_width = osd->pixel_stride; | ||
238 | oi->display_byte_stride = osd->pixel_stride * oi->bytes_per_pixel; | ||
239 | oi->set_osd_coords_x += osd->x; | ||
240 | oi->set_osd_coords_y = osd->y; | ||
241 | |||
242 | return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5, | ||
243 | osd->offset + oi->video_rbase, | ||
244 | osd->pixel_stride, | ||
245 | osd->lines, osd->x, osd->y); | ||
246 | } | ||
247 | |||
248 | static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window) | ||
249 | { | ||
250 | int osd_height_limit = itv->is_50hz ? 576 : 480; | ||
251 | |||
252 | /* Only fail if resolution too high, otherwise fudge the start coords. */ | ||
253 | if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH)) | ||
254 | return -EINVAL; | ||
255 | |||
256 | /* Ensure we don't exceed display limits */ | ||
257 | if (ivtv_window->top + ivtv_window->height > osd_height_limit) { | ||
258 | IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n", | ||
259 | ivtv_window->top, ivtv_window->height); | ||
260 | ivtv_window->top = osd_height_limit - ivtv_window->height; | ||
261 | } | ||
262 | |||
263 | if (ivtv_window->left + ivtv_window->width > IVTV_OSD_MAX_WIDTH) { | ||
264 | IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n", | ||
265 | ivtv_window->left, ivtv_window->width); | ||
266 | ivtv_window->left = IVTV_OSD_MAX_WIDTH - ivtv_window->width; | ||
267 | } | ||
268 | |||
269 | /* Set the OSD origin */ | ||
270 | write_reg((ivtv_window->top << 16) | ivtv_window->left, 0x02a04); | ||
271 | |||
272 | /* How much to display */ | ||
273 | write_reg(((ivtv_window->top+ivtv_window->height) << 16) | (ivtv_window->left+ivtv_window->width), 0x02a08); | ||
274 | |||
275 | /* Pass this info back the yuv handler */ | ||
276 | itv->yuv_info.osd_vis_w = ivtv_window->width; | ||
277 | itv->yuv_info.osd_vis_h = ivtv_window->height; | ||
278 | itv->yuv_info.osd_x_offset = ivtv_window->left; | ||
279 | itv->yuv_info.osd_y_offset = ivtv_window->top; | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, | ||
285 | unsigned long ivtv_dest_addr, void __user *userbuf, | ||
286 | int size_in_bytes) | ||
287 | { | ||
288 | DEFINE_WAIT(wait); | ||
289 | int ret = 0; | ||
290 | int got_sig = 0; | ||
291 | |||
292 | mutex_lock(&itv->udma.lock); | ||
293 | /* Map User DMA */ | ||
294 | if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) { | ||
295 | mutex_unlock(&itv->udma.lock); | ||
296 | IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, " | ||
297 | "Error with get_user_pages: %d bytes, %d pages returned\n", | ||
298 | size_in_bytes, itv->udma.page_count); | ||
299 | |||
300 | /* get_user_pages must have failed completely */ | ||
301 | return -EIO; | ||
302 | } | ||
303 | |||
304 | IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n", | ||
305 | size_in_bytes, itv->udma.page_count); | ||
306 | |||
307 | ivtv_udma_prepare(itv); | ||
308 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); | ||
309 | /* if no UDMA is pending and no UDMA is in progress, then the DMA | ||
310 | is finished */ | ||
311 | while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) { | ||
312 | /* don't interrupt if the DMA is in progress but break off | ||
313 | a still pending DMA. */ | ||
314 | got_sig = signal_pending(current); | ||
315 | if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags)) | ||
316 | break; | ||
317 | got_sig = 0; | ||
318 | schedule(); | ||
319 | } | ||
320 | finish_wait(&itv->dma_waitq, &wait); | ||
321 | |||
322 | /* Unmap Last DMA Xfer */ | ||
323 | ivtv_udma_unmap(itv); | ||
324 | mutex_unlock(&itv->udma.lock); | ||
325 | if (got_sig) { | ||
326 | IVTV_DEBUG_INFO("User stopped OSD\n"); | ||
327 | return -EINTR; | ||
328 | } | ||
329 | |||
330 | return ret; | ||
331 | } | ||
332 | |||
333 | static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source, | ||
334 | unsigned long dest_offset, int count) | ||
335 | { | ||
336 | DEFINE_WAIT(wait); | ||
337 | struct osd_info *oi = itv->osd_info; | ||
338 | |||
339 | /* Nothing to do */ | ||
340 | if (count == 0) { | ||
341 | IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n"); | ||
342 | return -EINVAL; | ||
343 | } | ||
344 | |||
345 | /* Check Total FB Size */ | ||
346 | if ((dest_offset + count) > oi->video_buffer_size) { | ||
347 | IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n", | ||
348 | dest_offset + count, oi->video_buffer_size); | ||
349 | return -E2BIG; | ||
350 | } | ||
351 | |||
352 | /* Not fatal, but will have undesirable results */ | ||
353 | if ((unsigned long)source & 3) | ||
354 | IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n", | ||
355 | (unsigned long)source); | ||
356 | |||
357 | if (dest_offset & 3) | ||
358 | IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset); | ||
359 | |||
360 | if (count & 3) | ||
361 | IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count); | ||
362 | |||
363 | /* Check Source */ | ||
364 | if (!access_ok(VERIFY_READ, source + dest_offset, count)) { | ||
365 | IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n", | ||
366 | (unsigned long)source); | ||
367 | |||
368 | IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n", | ||
369 | dest_offset, (unsigned long)source, | ||
370 | count); | ||
371 | return -EINVAL; | ||
372 | } | ||
373 | |||
374 | /* OSD Address to send DMA to */ | ||
375 | dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase; | ||
376 | |||
377 | /* Fill Buffers */ | ||
378 | return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count); | ||
379 | } | ||
380 | |||
381 | static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) | ||
382 | { | ||
383 | DEFINE_WAIT(wait); | ||
384 | struct ivtv *itv = (struct ivtv *)info->par; | ||
385 | int rc = 0; | ||
386 | |||
387 | switch (cmd) { | ||
388 | case FBIOGET_VBLANK: { | ||
389 | struct fb_vblank vblank; | ||
390 | u32 trace; | ||
391 | |||
392 | vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | | ||
393 | FB_VBLANK_HAVE_VSYNC; | ||
394 | trace = read_reg(0x028c0) >> 16; | ||
395 | if (itv->is_50hz && trace > 312) trace -= 312; | ||
396 | else if (itv->is_60hz && trace > 262) trace -= 262; | ||
397 | if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING; | ||
398 | vblank.count = itv->last_vsync_field; | ||
399 | vblank.vcount = trace; | ||
400 | vblank.hcount = 0; | ||
401 | if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank))) | ||
402 | return -EFAULT; | ||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | case FBIO_WAITFORVSYNC: | ||
407 | prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE); | ||
408 | if (!schedule_timeout(msecs_to_jiffies(50))) rc = -ETIMEDOUT; | ||
409 | finish_wait(&itv->vsync_waitq, &wait); | ||
410 | return rc; | ||
411 | |||
412 | case IVTVFB_IOC_DMA_FRAME: { | ||
413 | struct ivtvfb_dma_frame args; | ||
414 | |||
415 | IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n"); | ||
416 | if (copy_from_user(&args, (void __user *)arg, sizeof(args))) | ||
417 | return -EFAULT; | ||
418 | |||
419 | return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count); | ||
420 | } | ||
421 | |||
422 | default: | ||
423 | IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd); | ||
424 | return -EINVAL; | ||
425 | } | ||
426 | return 0; | ||
427 | } | ||
428 | |||
429 | /* Framebuffer device handling */ | ||
430 | |||
431 | static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var) | ||
432 | { | ||
433 | struct osd_info *oi = itv->osd_info; | ||
434 | struct ivtv_osd_coords ivtv_osd; | ||
435 | struct v4l2_rect ivtv_window; | ||
436 | int osd_mode = -1; | ||
437 | |||
438 | IVTVFB_DEBUG_INFO("ivtvfb_set_var\n"); | ||
439 | |||
440 | /* Select color space */ | ||
441 | if (var->nonstd) /* YUV */ | ||
442 | write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00); | ||
443 | else /* RGB */ | ||
444 | write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00); | ||
445 | |||
446 | /* Set the color mode */ | ||
447 | switch (var->bits_per_pixel) { | ||
448 | case 8: | ||
449 | osd_mode = IVTV_OSD_BPP_8; | ||
450 | break; | ||
451 | case 32: | ||
452 | osd_mode = IVTV_OSD_BPP_32; | ||
453 | break; | ||
454 | case 16: | ||
455 | switch (var->green.length) { | ||
456 | case 4: | ||
457 | osd_mode = IVTV_OSD_BPP_16_444; | ||
458 | break; | ||
459 | case 5: | ||
460 | osd_mode = IVTV_OSD_BPP_16_555; | ||
461 | break; | ||
462 | case 6: | ||
463 | osd_mode = IVTV_OSD_BPP_16_565; | ||
464 | break; | ||
465 | default: | ||
466 | IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n"); | ||
467 | } | ||
468 | break; | ||
469 | default: | ||
470 | IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n"); | ||
471 | } | ||
472 | |||
473 | /* Change osd mode if needed. | ||
474 | Although rare, things can go wrong. The extra mode | ||
475 | change seems to help... */ | ||
476 | if (osd_mode != -1 && osd_mode != oi->osd_mode) { | ||
477 | ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0); | ||
478 | ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode); | ||
479 | oi->osd_mode = osd_mode; | ||
480 | } | ||
481 | |||
482 | oi->bits_per_pixel = var->bits_per_pixel; | ||
483 | oi->bytes_per_pixel = var->bits_per_pixel / 8; | ||
484 | |||
485 | /* Set the flicker filter */ | ||
486 | switch (var->vmode & FB_VMODE_MASK) { | ||
487 | case FB_VMODE_NONINTERLACED: /* Filter on */ | ||
488 | ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1); | ||
489 | break; | ||
490 | case FB_VMODE_INTERLACED: /* Filter off */ | ||
491 | ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0); | ||
492 | break; | ||
493 | default: | ||
494 | IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n"); | ||
495 | } | ||
496 | |||
497 | /* Read the current osd info */ | ||
498 | ivtvfb_get_osd_coords(itv, &ivtv_osd); | ||
499 | |||
500 | /* Now set the OSD to the size we want */ | ||
501 | ivtv_osd.pixel_stride = var->xres_virtual; | ||
502 | ivtv_osd.lines = var->yres_virtual; | ||
503 | ivtv_osd.x = 0; | ||
504 | ivtv_osd.y = 0; | ||
505 | ivtvfb_set_osd_coords(itv, &ivtv_osd); | ||
506 | |||
507 | /* Can't seem to find the right API combo for this. | ||
508 | Use another function which does what we need through direct register access. */ | ||
509 | ivtv_window.width = var->xres; | ||
510 | ivtv_window.height = var->yres; | ||
511 | |||
512 | /* Minimum margin cannot be 0, as X won't allow such a mode */ | ||
513 | if (!var->upper_margin) var->upper_margin++; | ||
514 | if (!var->left_margin) var->left_margin++; | ||
515 | ivtv_window.top = var->upper_margin - 1; | ||
516 | ivtv_window.left = var->left_margin - 1; | ||
517 | |||
518 | ivtvfb_set_display_window(itv, &ivtv_window); | ||
519 | |||
520 | /* Force update of yuv registers */ | ||
521 | itv->yuv_info.yuv_forced_update = 1; | ||
522 | |||
523 | IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n", | ||
524 | var->xres, var->yres, | ||
525 | var->xres_virtual, var->yres_virtual, | ||
526 | var->bits_per_pixel); | ||
527 | |||
528 | IVTVFB_DEBUG_INFO("Display position: %d, %d\n", | ||
529 | var->left_margin, var->upper_margin); | ||
530 | |||
531 | IVTVFB_DEBUG_INFO("Display filter: %s\n", | ||
532 | (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off"); | ||
533 | IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB"); | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix) | ||
539 | { | ||
540 | struct osd_info *oi = itv->osd_info; | ||
541 | |||
542 | IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n"); | ||
543 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | ||
544 | strcpy(fix->id, "cx23415 TV out"); | ||
545 | fix->smem_start = oi->video_pbase; | ||
546 | fix->smem_len = oi->video_buffer_size; | ||
547 | fix->type = FB_TYPE_PACKED_PIXELS; | ||
548 | fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | ||
549 | fix->xpanstep = 1; | ||
550 | fix->ypanstep = 1; | ||
551 | fix->ywrapstep = 0; | ||
552 | fix->line_length = oi->display_byte_stride; | ||
553 | fix->accel = FB_ACCEL_NONE; | ||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | /* Check the requested display mode, returning -EINVAL if we can't | ||
558 | handle it. */ | ||
559 | |||
560 | static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv) | ||
561 | { | ||
562 | struct osd_info *oi = itv->osd_info; | ||
563 | int osd_height_limit; | ||
564 | u32 pixclock, hlimit, vlimit; | ||
565 | |||
566 | IVTVFB_DEBUG_INFO("ivtvfb_check_var\n"); | ||
567 | |||
568 | /* Set base references for mode calcs. */ | ||
569 | if (itv->is_50hz) { | ||
570 | pixclock = 84316; | ||
571 | hlimit = 776; | ||
572 | vlimit = 591; | ||
573 | osd_height_limit = 576; | ||
574 | } | ||
575 | else { | ||
576 | pixclock = 83926; | ||
577 | hlimit = 776; | ||
578 | vlimit = 495; | ||
579 | osd_height_limit = 480; | ||
580 | } | ||
581 | |||
582 | /* Check the bits per pixel */ | ||
583 | if (osd_compat) { | ||
584 | if (var->bits_per_pixel != 32) { | ||
585 | IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel); | ||
586 | return -EINVAL; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) { | ||
591 | var->transp.offset = 24; | ||
592 | var->transp.length = 8; | ||
593 | var->red.offset = 16; | ||
594 | var->red.length = 8; | ||
595 | var->green.offset = 8; | ||
596 | var->green.length = 8; | ||
597 | var->blue.offset = 0; | ||
598 | var->blue.length = 8; | ||
599 | } | ||
600 | else if (var->bits_per_pixel == 16) { | ||
601 | /* To find out the true mode, check green length */ | ||
602 | switch (var->green.length) { | ||
603 | case 4: | ||
604 | var->red.offset = 8; | ||
605 | var->red.length = 4; | ||
606 | var->green.offset = 4; | ||
607 | var->green.length = 4; | ||
608 | var->blue.offset = 0; | ||
609 | var->blue.length = 4; | ||
610 | var->transp.offset = 12; | ||
611 | var->transp.length = 1; | ||
612 | break; | ||
613 | case 5: | ||
614 | var->red.offset = 10; | ||
615 | var->red.length = 5; | ||
616 | var->green.offset = 5; | ||
617 | var->green.length = 5; | ||
618 | var->blue.offset = 0; | ||
619 | var->blue.length = 5; | ||
620 | var->transp.offset = 15; | ||
621 | var->transp.length = 1; | ||
622 | break; | ||
623 | default: | ||
624 | var->red.offset = 11; | ||
625 | var->red.length = 5; | ||
626 | var->green.offset = 5; | ||
627 | var->green.length = 6; | ||
628 | var->blue.offset = 0; | ||
629 | var->blue.length = 5; | ||
630 | var->transp.offset = 0; | ||
631 | var->transp.length = 0; | ||
632 | break; | ||
633 | } | ||
634 | } | ||
635 | else { | ||
636 | IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel); | ||
637 | return -EINVAL; | ||
638 | } | ||
639 | |||
640 | /* Check the resolution */ | ||
641 | if (osd_compat) { | ||
642 | if (var->xres != oi->ivtvfb_defined.xres || | ||
643 | var->yres != oi->ivtvfb_defined.yres || | ||
644 | var->xres_virtual != oi->ivtvfb_defined.xres_virtual || | ||
645 | var->yres_virtual != oi->ivtvfb_defined.yres_virtual) { | ||
646 | IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d (virtual %dx%d)\n", | ||
647 | var->xres, var->yres, var->xres_virtual, var->yres_virtual); | ||
648 | return -EINVAL; | ||
649 | } | ||
650 | } | ||
651 | else { | ||
652 | if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) { | ||
653 | IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n", | ||
654 | var->xres, var->yres); | ||
655 | return -EINVAL; | ||
656 | } | ||
657 | |||
658 | /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */ | ||
659 | if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) || | ||
660 | var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size || | ||
661 | var->xres_virtual < var->xres || | ||
662 | var->yres_virtual < var->yres) { | ||
663 | IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n", | ||
664 | var->xres_virtual, var->yres_virtual); | ||
665 | return -EINVAL; | ||
666 | } | ||
667 | } | ||
668 | |||
669 | /* Some extra checks if in 8 bit mode */ | ||
670 | if (var->bits_per_pixel == 8) { | ||
671 | /* Width must be a multiple of 4 */ | ||
672 | if (var->xres & 3) { | ||
673 | IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres); | ||
674 | return -EINVAL; | ||
675 | } | ||
676 | if (var->xres_virtual & 3) { | ||
677 | IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual); | ||
678 | return -EINVAL; | ||
679 | } | ||
680 | } | ||
681 | else if (var->bits_per_pixel == 16) { | ||
682 | /* Width must be a multiple of 2 */ | ||
683 | if (var->xres & 1) { | ||
684 | IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres); | ||
685 | return -EINVAL; | ||
686 | } | ||
687 | if (var->xres_virtual & 1) { | ||
688 | IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual); | ||
689 | return -EINVAL; | ||
690 | } | ||
691 | } | ||
692 | |||
693 | /* Now check the offsets */ | ||
694 | if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) { | ||
695 | IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n", | ||
696 | var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual); | ||
697 | return -EINVAL; | ||
698 | } | ||
699 | |||
700 | /* Check pixel format */ | ||
701 | if (var->nonstd > 1) { | ||
702 | IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd); | ||
703 | return -EINVAL; | ||
704 | } | ||
705 | |||
706 | /* Check video mode */ | ||
707 | if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) && | ||
708 | ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) { | ||
709 | IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK); | ||
710 | return -EINVAL; | ||
711 | } | ||
712 | |||
713 | /* Check the left & upper margins | ||
714 | If the margins are too large, just center the screen | ||
715 | (enforcing margins causes too many problems) */ | ||
716 | |||
717 | if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1) { | ||
718 | var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2); | ||
719 | } | ||
720 | if (var->upper_margin + var->yres > (itv->is_50hz ? 577 : 481)) { | ||
721 | var->upper_margin = 1 + (((itv->is_50hz ? 576 : 480) - var->yres) / 2); | ||
722 | } | ||
723 | |||
724 | /* Maintain overall 'size' for a constant refresh rate */ | ||
725 | var->right_margin = hlimit - var->left_margin - var->xres; | ||
726 | var->lower_margin = vlimit - var->upper_margin - var->yres; | ||
727 | |||
728 | /* Fixed sync times */ | ||
729 | var->hsync_len = 24; | ||
730 | var->vsync_len = 2; | ||
731 | |||
732 | /* Non-interlaced / interlaced mode is used to switch the OSD filter | ||
733 | on or off. Adjust the clock timings to maintain a constant | ||
734 | vertical refresh rate. */ | ||
735 | if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) | ||
736 | var->pixclock = pixclock / 2; | ||
737 | else | ||
738 | var->pixclock = pixclock; | ||
739 | |||
740 | IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n", | ||
741 | var->xres, var->yres, | ||
742 | var->xres_virtual, var->yres_virtual, | ||
743 | var->bits_per_pixel); | ||
744 | |||
745 | IVTVFB_DEBUG_INFO("Display position: %d, %d\n", | ||
746 | var->left_margin, var->upper_margin); | ||
747 | |||
748 | IVTVFB_DEBUG_INFO("Display filter: %s\n", | ||
749 | (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off"); | ||
750 | IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB"); | ||
751 | return 0; | ||
752 | } | ||
753 | |||
754 | static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | ||
755 | { | ||
756 | struct ivtv *itv = (struct ivtv *) info->par; | ||
757 | IVTVFB_DEBUG_INFO("ivtvfb_check_var\n"); | ||
758 | return _ivtvfb_check_var(var, itv); | ||
759 | } | ||
760 | |||
761 | static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | ||
762 | { | ||
763 | u32 osd_pan_index; | ||
764 | struct ivtv *itv = (struct ivtv *) info->par; | ||
765 | |||
766 | osd_pan_index = (var->xoffset + (var->yoffset * var->xres_virtual))*var->bits_per_pixel/8; | ||
767 | write_reg(osd_pan_index, 0x02A0C); | ||
768 | |||
769 | /* Pass this info back the yuv handler */ | ||
770 | itv->yuv_info.osd_x_pan = var->xoffset; | ||
771 | itv->yuv_info.osd_y_pan = var->yoffset; | ||
772 | /* Force update of yuv registers */ | ||
773 | itv->yuv_info.yuv_forced_update = 1; | ||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static int ivtvfb_set_par(struct fb_info *info) | ||
778 | { | ||
779 | int rc = 0; | ||
780 | struct ivtv *itv = (struct ivtv *) info->par; | ||
781 | |||
782 | IVTVFB_DEBUG_INFO("ivtvfb_set_par\n"); | ||
783 | |||
784 | rc = ivtvfb_set_var(itv, &info->var); | ||
785 | ivtvfb_pan_display(&info->var, info); | ||
786 | ivtvfb_get_fix(itv, &info->fix); | ||
787 | return rc; | ||
788 | } | ||
789 | |||
790 | static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
791 | unsigned blue, unsigned transp, | ||
792 | struct fb_info *info) | ||
793 | { | ||
794 | u32 color, *palette; | ||
795 | struct ivtv *itv = (struct ivtv *)info->par; | ||
796 | |||
797 | if (regno >= info->cmap.len) | ||
798 | return -EINVAL; | ||
799 | |||
800 | color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8); | ||
801 | if (info->var.bits_per_pixel <= 8) { | ||
802 | write_reg(regno, 0x02a30); | ||
803 | write_reg(color, 0x02a34); | ||
804 | return 0; | ||
805 | } | ||
806 | if (regno >= 16) | ||
807 | return -EINVAL; | ||
808 | |||
809 | palette = info->pseudo_palette; | ||
810 | if (info->var.bits_per_pixel == 16) { | ||
811 | switch (info->var.green.length) { | ||
812 | case 4: | ||
813 | color = ((red & 0xf000) >> 4) | | ||
814 | ((green & 0xf000) >> 8) | | ||
815 | ((blue & 0xf000) >> 12); | ||
816 | break; | ||
817 | case 5: | ||
818 | color = ((red & 0xf800) >> 1) | | ||
819 | ((green & 0xf800) >> 6) | | ||
820 | ((blue & 0xf800) >> 11); | ||
821 | break; | ||
822 | case 6: | ||
823 | color = (red & 0xf800 ) | | ||
824 | ((green & 0xfc00) >> 5) | | ||
825 | ((blue & 0xf800) >> 11); | ||
826 | break; | ||
827 | } | ||
828 | } | ||
829 | palette[regno] = color; | ||
830 | return 0; | ||
831 | } | ||
832 | |||
833 | /* We don't really support blanking. All this does is enable or | ||
834 | disable the OSD. */ | ||
835 | static int ivtvfb_blank(int blank_mode, struct fb_info *info) | ||
836 | { | ||
837 | struct ivtv *itv = (struct ivtv *)info->par; | ||
838 | |||
839 | IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode); | ||
840 | switch (blank_mode) { | ||
841 | case FB_BLANK_UNBLANK: | ||
842 | ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1); | ||
843 | break; | ||
844 | case FB_BLANK_NORMAL: | ||
845 | case FB_BLANK_HSYNC_SUSPEND: | ||
846 | case FB_BLANK_VSYNC_SUSPEND: | ||
847 | case FB_BLANK_POWERDOWN: | ||
848 | ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); | ||
849 | break; | ||
850 | } | ||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | static struct fb_ops ivtvfb_ops = { | ||
855 | .owner = THIS_MODULE, | ||
856 | .fb_check_var = ivtvfb_check_var, | ||
857 | .fb_set_par = ivtvfb_set_par, | ||
858 | .fb_setcolreg = ivtvfb_setcolreg, | ||
859 | .fb_fillrect = cfb_fillrect, | ||
860 | .fb_copyarea = cfb_copyarea, | ||
861 | .fb_imageblit = cfb_imageblit, | ||
862 | .fb_cursor = NULL, | ||
863 | .fb_ioctl = ivtvfb_ioctl, | ||
864 | .fb_pan_display = ivtvfb_pan_display, | ||
865 | .fb_blank = ivtvfb_blank, | ||
866 | }; | ||
867 | |||
868 | /* Initialization */ | ||
869 | |||
870 | |||
871 | /* Setup our initial video mode */ | ||
872 | static int ivtvfb_init_vidmode(struct ivtv *itv) | ||
873 | { | ||
874 | struct osd_info *oi = itv->osd_info; | ||
875 | struct v4l2_rect start_window; | ||
876 | int max_height; | ||
877 | |||
878 | /* Color mode */ | ||
879 | |||
880 | if (osd_compat) osd_depth = 32; | ||
881 | if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32) osd_depth = 8; | ||
882 | oi->bits_per_pixel = osd_depth; | ||
883 | oi->bytes_per_pixel = oi->bits_per_pixel / 8; | ||
884 | |||
885 | /* Invalidate current osd mode to force a mode switch later */ | ||
886 | oi->osd_mode = -1; | ||
887 | |||
888 | /* Horizontal size & position */ | ||
889 | |||
890 | if (osd_xres > 720) osd_xres = 720; | ||
891 | |||
892 | /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */ | ||
893 | if (osd_depth == 8) | ||
894 | osd_xres &= ~3; | ||
895 | else if (osd_depth == 16) | ||
896 | osd_xres &= ~1; | ||
897 | |||
898 | if (osd_xres) | ||
899 | start_window.width = osd_xres; | ||
900 | else | ||
901 | start_window.width = osd_compat ? 720: 640; | ||
902 | |||
903 | /* Check horizontal start (osd_left). */ | ||
904 | if (osd_left && osd_left + start_window.width > 721) { | ||
905 | IVTVFB_ERR("Invalid osd_left - assuming default\n"); | ||
906 | osd_left = 0; | ||
907 | } | ||
908 | |||
909 | /* Hardware coords start at 0, user coords start at 1. */ | ||
910 | osd_left--; | ||
911 | |||
912 | start_window.left = osd_left >= 0 ? osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2); | ||
913 | |||
914 | oi->display_byte_stride = | ||
915 | start_window.width * oi->bytes_per_pixel; | ||
916 | |||
917 | /* Vertical size & position */ | ||
918 | |||
919 | max_height = itv->is_50hz ? 576 : 480; | ||
920 | |||
921 | if (osd_yres > max_height) | ||
922 | osd_yres = max_height; | ||
923 | |||
924 | if (osd_yres) | ||
925 | start_window.height = osd_yres; | ||
926 | else | ||
927 | start_window.height = osd_compat ? max_height : (itv->is_50hz ? 480 : 400); | ||
928 | |||
929 | /* Check vertical start (osd_upper). */ | ||
930 | if (osd_upper + start_window.height > max_height + 1) { | ||
931 | IVTVFB_ERR("Invalid osd_upper - assuming default\n"); | ||
932 | osd_upper = 0; | ||
933 | } | ||
934 | |||
935 | /* Hardware coords start at 0, user coords start at 1. */ | ||
936 | osd_upper--; | ||
937 | |||
938 | start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2); | ||
939 | |||
940 | oi->display_width = start_window.width; | ||
941 | oi->display_height = start_window.height; | ||
942 | |||
943 | /* Generate a valid fb_var_screeninfo */ | ||
944 | |||
945 | oi->ivtvfb_defined.xres = oi->display_width; | ||
946 | oi->ivtvfb_defined.yres = oi->display_height; | ||
947 | oi->ivtvfb_defined.xres_virtual = oi->display_width; | ||
948 | oi->ivtvfb_defined.yres_virtual = oi->display_height; | ||
949 | oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel; | ||
950 | oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED); | ||
951 | oi->ivtvfb_defined.left_margin = start_window.left + 1; | ||
952 | oi->ivtvfb_defined.upper_margin = start_window.top + 1; | ||
953 | oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE; | ||
954 | oi->ivtvfb_defined.nonstd = 0; | ||
955 | |||
956 | /* We've filled in the most data, let the usual mode check | ||
957 | routine fill in the rest. */ | ||
958 | _ivtvfb_check_var(&oi->ivtvfb_defined, itv); | ||
959 | |||
960 | /* Generate valid fb_fix_screeninfo */ | ||
961 | |||
962 | ivtvfb_get_fix(itv, &oi->ivtvfb_fix); | ||
963 | |||
964 | /* Generate valid fb_info */ | ||
965 | |||
966 | oi->ivtvfb_info.node = -1; | ||
967 | oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT; | ||
968 | oi->ivtvfb_info.fbops = &ivtvfb_ops; | ||
969 | oi->ivtvfb_info.par = itv; | ||
970 | oi->ivtvfb_info.var = oi->ivtvfb_defined; | ||
971 | oi->ivtvfb_info.fix = oi->ivtvfb_fix; | ||
972 | oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase; | ||
973 | oi->ivtvfb_info.fbops = &ivtvfb_ops; | ||
974 | |||
975 | /* Supply some monitor specs. Bogus values will do for now */ | ||
976 | oi->ivtvfb_info.monspecs.hfmin = 8000; | ||
977 | oi->ivtvfb_info.monspecs.hfmax = 70000; | ||
978 | oi->ivtvfb_info.monspecs.vfmin = 10; | ||
979 | oi->ivtvfb_info.monspecs.vfmax = 100; | ||
980 | |||
981 | /* Allocate color map */ | ||
982 | if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) { | ||
983 | IVTVFB_ERR("abort, unable to alloc cmap\n"); | ||
984 | return -ENOMEM; | ||
985 | } | ||
986 | |||
987 | /* Allocate the pseudo palette */ | ||
988 | oi->ivtvfb_info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); | ||
989 | |||
990 | if (!oi->ivtvfb_info.pseudo_palette) { | ||
991 | IVTVFB_ERR("abort, unable to alloc pseudo pallete\n"); | ||
992 | return -ENOMEM; | ||
993 | } | ||
994 | |||
995 | return 0; | ||
996 | } | ||
997 | |||
998 | /* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */ | ||
999 | |||
1000 | static int ivtvfb_init_io(struct ivtv *itv) | ||
1001 | { | ||
1002 | struct osd_info *oi = itv->osd_info; | ||
1003 | |||
1004 | mutex_lock(&itv->serialize_lock); | ||
1005 | if (ivtv_init_on_first_open(itv)) { | ||
1006 | mutex_unlock(&itv->serialize_lock); | ||
1007 | IVTVFB_ERR("Failed to initialize ivtv\n"); | ||
1008 | return -ENXIO; | ||
1009 | } | ||
1010 | mutex_unlock(&itv->serialize_lock); | ||
1011 | |||
1012 | ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size); | ||
1013 | |||
1014 | /* The osd buffer size depends on the number of video buffers allocated | ||
1015 | on the PVR350 itself. For now we'll hardcode the smallest osd buffer | ||
1016 | size to prevent any overlap. */ | ||
1017 | oi->video_buffer_size = 1704960; | ||
1018 | |||
1019 | oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase; | ||
1020 | oi->video_vbase = itv->dec_mem + oi->video_rbase; | ||
1021 | |||
1022 | if (!oi->video_vbase) { | ||
1023 | IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n", | ||
1024 | oi->video_buffer_size, oi->video_pbase); | ||
1025 | return -EIO; | ||
1026 | } | ||
1027 | |||
1028 | IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n", | ||
1029 | oi->video_pbase, oi->video_vbase, | ||
1030 | oi->video_buffer_size / 1024); | ||
1031 | |||
1032 | #ifdef CONFIG_MTRR | ||
1033 | { | ||
1034 | /* Find the largest power of two that maps the whole buffer */ | ||
1035 | int size_shift = 31; | ||
1036 | |||
1037 | while (!(oi->video_buffer_size & (1 << size_shift))) { | ||
1038 | size_shift--; | ||
1039 | } | ||
1040 | size_shift++; | ||
1041 | oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1); | ||
1042 | oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size; | ||
1043 | oi->fb_end_aligned_physaddr += (1 << size_shift) - 1; | ||
1044 | oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1); | ||
1045 | if (mtrr_add(oi->fb_start_aligned_physaddr, | ||
1046 | oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr, | ||
1047 | MTRR_TYPE_WRCOMB, 1) < 0) { | ||
1048 | IVTVFB_INFO("disabled mttr\n"); | ||
1049 | oi->fb_start_aligned_physaddr = 0; | ||
1050 | oi->fb_end_aligned_physaddr = 0; | ||
1051 | } | ||
1052 | } | ||
1053 | #endif | ||
1054 | |||
1055 | /* Blank the entire osd. */ | ||
1056 | memset_io(oi->video_vbase, 0, oi->video_buffer_size); | ||
1057 | |||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | /* Release any memory we've grabbed & remove mtrr entry */ | ||
1062 | static void ivtvfb_release_buffers (struct ivtv *itv) | ||
1063 | { | ||
1064 | struct osd_info *oi = itv->osd_info; | ||
1065 | |||
1066 | /* Release cmap */ | ||
1067 | if (oi->ivtvfb_info.cmap.len) | ||
1068 | fb_dealloc_cmap(&oi->ivtvfb_info.cmap); | ||
1069 | |||
1070 | /* Release pseudo palette */ | ||
1071 | if (oi->ivtvfb_info.pseudo_palette) | ||
1072 | kfree(oi->ivtvfb_info.pseudo_palette); | ||
1073 | |||
1074 | #ifdef CONFIG_MTRR | ||
1075 | if (oi->fb_end_aligned_physaddr) { | ||
1076 | mtrr_del(-1, oi->fb_start_aligned_physaddr, | ||
1077 | oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr); | ||
1078 | } | ||
1079 | #endif | ||
1080 | |||
1081 | kfree(oi); | ||
1082 | itv->osd_info = NULL; | ||
1083 | } | ||
1084 | |||
1085 | /* Initialize the specified card */ | ||
1086 | |||
1087 | static int ivtvfb_init_card(struct ivtv *itv) | ||
1088 | { | ||
1089 | int rc; | ||
1090 | |||
1091 | if (itv->osd_info) { | ||
1092 | IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id); | ||
1093 | return -EBUSY; | ||
1094 | } | ||
1095 | |||
1096 | itv->osd_info = kzalloc(sizeof(struct osd_info), GFP_ATOMIC); | ||
1097 | if (itv->osd_info == 0) { | ||
1098 | IVTVFB_ERR("Failed to allocate memory for osd_info\n"); | ||
1099 | return -ENOMEM; | ||
1100 | } | ||
1101 | |||
1102 | /* Find & setup the OSD buffer */ | ||
1103 | if ((rc = ivtvfb_init_io(itv))) | ||
1104 | return rc; | ||
1105 | |||
1106 | /* Set the startup video mode information */ | ||
1107 | if ((rc = ivtvfb_init_vidmode(itv))) { | ||
1108 | ivtvfb_release_buffers(itv); | ||
1109 | return rc; | ||
1110 | } | ||
1111 | |||
1112 | /* Register the framebuffer */ | ||
1113 | if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) { | ||
1114 | ivtvfb_release_buffers(itv); | ||
1115 | return -EINVAL; | ||
1116 | } | ||
1117 | |||
1118 | itv->osd_video_pbase = itv->osd_info->video_pbase; | ||
1119 | |||
1120 | /* Set the card to the requested mode */ | ||
1121 | ivtvfb_set_par(&itv->osd_info->ivtvfb_info); | ||
1122 | |||
1123 | /* Set color 0 to black */ | ||
1124 | write_reg(0, 0x02a30); | ||
1125 | write_reg(0, 0x02a34); | ||
1126 | |||
1127 | /* Enable the osd */ | ||
1128 | ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info); | ||
1129 | |||
1130 | /* Note if we're running in compatibility mode */ | ||
1131 | if (osd_compat) | ||
1132 | IVTVFB_INFO("Running in compatibility mode. Display resize & mode change disabled\n"); | ||
1133 | |||
1134 | /* Allocate DMA */ | ||
1135 | ivtv_udma_alloc(itv); | ||
1136 | return 0; | ||
1137 | |||
1138 | } | ||
1139 | |||
1140 | static int __init ivtvfb_init(void) | ||
1141 | { | ||
1142 | struct ivtv *itv; | ||
1143 | int i, registered = 0; | ||
1144 | |||
1145 | if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) { | ||
1146 | printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n", | ||
1147 | IVTV_MAX_CARDS - 1); | ||
1148 | return -EINVAL; | ||
1149 | } | ||
1150 | |||
1151 | /* Locate & initialise all cards supporting an OSD. */ | ||
1152 | for (i = 0; i < ivtv_cards_active; i++) { | ||
1153 | if (ivtvfb_card_id != -1 && i != ivtvfb_card_id) | ||
1154 | continue; | ||
1155 | itv = ivtv_cards[i]; | ||
1156 | if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { | ||
1157 | if (ivtvfb_init_card(itv) == 0) { | ||
1158 | IVTVFB_INFO("Framebuffer registered on ivtv card id %d\n", i); | ||
1159 | registered++; | ||
1160 | } | ||
1161 | } | ||
1162 | } | ||
1163 | if (!registered) { | ||
1164 | printk(KERN_ERR "ivtvfb: no cards found"); | ||
1165 | return -ENODEV; | ||
1166 | } | ||
1167 | return 0; | ||
1168 | } | ||
1169 | |||
1170 | static void ivtvfb_cleanup(void) | ||
1171 | { | ||
1172 | struct ivtv *itv; | ||
1173 | int i; | ||
1174 | |||
1175 | printk(KERN_INFO "ivtvfb: Unloading framebuffer module\n"); | ||
1176 | |||
1177 | for (i = 0; i < ivtv_cards_active; i++) { | ||
1178 | itv = ivtv_cards[i]; | ||
1179 | if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) && itv->osd_info) { | ||
1180 | IVTVFB_DEBUG_INFO("Unregister framebuffer %d\n", i); | ||
1181 | ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info); | ||
1182 | unregister_framebuffer(&itv->osd_info->ivtvfb_info); | ||
1183 | ivtvfb_release_buffers(itv); | ||
1184 | itv->osd_video_pbase = 0; | ||
1185 | } | ||
1186 | } | ||
1187 | } | ||
1188 | |||
1189 | module_init(ivtvfb_init); | ||
1190 | module_exit(ivtvfb_cleanup); | ||
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 11cfcf18ec34..c0c87e06259b 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c | |||
@@ -244,17 +244,17 @@ int msp_write_dsp(struct i2c_client *client, int addr, int val) | |||
244 | * ----------------------------------------------------------------------- */ | 244 | * ----------------------------------------------------------------------- */ |
245 | 245 | ||
246 | static int scarts[3][9] = { | 246 | static int scarts[3][9] = { |
247 | /* MASK IN1 IN2 IN3 IN4 IN1_DA IN2_DA MONO MUTE */ | 247 | /* MASK IN1 IN2 IN3 IN4 IN1_DA IN2_DA MONO MUTE */ |
248 | /* SCART DSP Input select */ | 248 | /* SCART DSP Input select */ |
249 | { 0x0320, 0x0000, 0x0200, 0x0300, 0x0020, -1, -1, 0x0100, 0x0320 }, | 249 | { 0x0320, 0x0000, 0x0200, 0x0300, 0x0020, -1, -1, 0x0100, 0x0320 }, |
250 | /* SCART1 Output select */ | 250 | /* SCART1 Output select */ |
251 | { 0x0c40, 0x0440, 0x0400, 0x0000, 0x0840, 0x0c00, 0x0040, 0x0800, 0x0c40 }, | 251 | { 0x0c40, 0x0440, 0x0400, 0x0000, 0x0840, 0x0c00, 0x0040, 0x0800, 0x0c40 }, |
252 | /* SCART2 Output select */ | 252 | /* SCART2 Output select */ |
253 | { 0x3080, 0x1000, 0x1080, 0x2080, 0x3080, 0x0000, 0x0080, 0x2000, 0x3000 }, | 253 | { 0x3080, 0x1000, 0x1080, 0x2080, 0x3080, 0x0000, 0x0080, 0x2000, 0x3000 }, |
254 | }; | 254 | }; |
255 | 255 | ||
256 | static char *scart_names[] = { | 256 | static char *scart_names[] = { |
257 | "in1", "in2", "in3", "in4", "in1 da", "in2 da", "mono", "mute" | 257 | "in1", "in2", "in3", "in4", "in1 da", "in2 da", "mono", "mute" |
258 | }; | 258 | }; |
259 | 259 | ||
260 | void msp_set_scart(struct i2c_client *client, int in, int out) | 260 | void msp_set_scart(struct i2c_client *client, int in, int out) |
@@ -813,8 +813,9 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) | |||
813 | int msp_rom; | 813 | int msp_rom; |
814 | 814 | ||
815 | client = kzalloc(sizeof(*client), GFP_KERNEL); | 815 | client = kzalloc(sizeof(*client), GFP_KERNEL); |
816 | if (client == NULL) | 816 | if (!client) |
817 | return -ENOMEM; | 817 | return -ENOMEM; |
818 | |||
818 | client->addr = address; | 819 | client->addr = address; |
819 | client->adapter = adapter; | 820 | client->adapter = adapter; |
820 | client->driver = &i2c_driver; | 821 | client->driver = &i2c_driver; |
@@ -826,14 +827,14 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) | |||
826 | return 0; | 827 | return 0; |
827 | } | 828 | } |
828 | 829 | ||
829 | state = kmalloc(sizeof(*state), GFP_KERNEL); | 830 | state = kzalloc(sizeof(*state), GFP_KERNEL); |
830 | if (state == NULL) { | 831 | if (!state) { |
831 | kfree(client); | 832 | kfree(client); |
832 | return -ENOMEM; | 833 | return -ENOMEM; |
833 | } | 834 | } |
835 | |||
834 | i2c_set_clientdata(client, state); | 836 | i2c_set_clientdata(client, state); |
835 | 837 | ||
836 | memset(state, 0, sizeof(*state)); | ||
837 | state->v4l2_std = V4L2_STD_NTSC; | 838 | state->v4l2_std = V4L2_STD_NTSC; |
838 | state->audmode = V4L2_TUNER_MODE_STEREO; | 839 | state->audmode = V4L2_TUNER_MODE_STEREO; |
839 | state->volume = 58880; /* 0db gain */ | 840 | state->volume = 58880; /* 0db gain */ |
diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index 7549114aaaca..f49d1f4c40db 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c | |||
@@ -1,13 +1,20 @@ | |||
1 | /* | 1 | /* |
2 | * | ||
3 | * i2c tv tuner chip device driver | 2 | * i2c tv tuner chip device driver |
4 | * controls microtune tuners, mt2032 + mt2050 at the moment. | 3 | * controls microtune tuners, mt2032 + mt2050 at the moment. |
4 | * | ||
5 | * This "mt20xx" module was split apart from the original "tuner" module. | ||
5 | */ | 6 | */ |
6 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
7 | #include <linux/i2c.h> | 8 | #include <linux/i2c.h> |
8 | #include <linux/videodev.h> | 9 | #include <linux/videodev.h> |
9 | #include <linux/moduleparam.h> | 10 | #include "tuner-i2c.h" |
10 | #include "tuner-driver.h" | 11 | #include "mt20xx.h" |
12 | |||
13 | static int debug = 0; | ||
14 | module_param(debug, int, 0644); | ||
15 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
16 | |||
17 | #define PREFIX "mt20xx " | ||
11 | 18 | ||
12 | /* ---------------------------------------------------------------------- */ | 19 | /* ---------------------------------------------------------------------- */ |
13 | 20 | ||
@@ -20,9 +27,6 @@ module_param(tv_antenna, int, 0644); | |||
20 | static unsigned int radio_antenna = 0; | 27 | static unsigned int radio_antenna = 0; |
21 | module_param(radio_antenna, int, 0644); | 28 | module_param(radio_antenna, int, 0644); |
22 | 29 | ||
23 | /* from tuner-core.c */ | ||
24 | extern int tuner_debug; | ||
25 | |||
26 | /* ---------------------------------------------------------------------- */ | 30 | /* ---------------------------------------------------------------------- */ |
27 | 31 | ||
28 | #define MT2032 0x04 | 32 | #define MT2032 0x04 |
@@ -38,23 +42,34 @@ static char *microtune_part[] = { | |||
38 | }; | 42 | }; |
39 | 43 | ||
40 | struct microtune_priv { | 44 | struct microtune_priv { |
45 | struct tuner_i2c_props i2c_props; | ||
46 | |||
41 | unsigned int xogc; | 47 | unsigned int xogc; |
42 | unsigned int radio_if2; | 48 | //unsigned int radio_if2; |
49 | |||
50 | u32 frequency; | ||
43 | }; | 51 | }; |
44 | 52 | ||
45 | static void microtune_release(struct i2c_client *c) | 53 | static int microtune_release(struct dvb_frontend *fe) |
46 | { | 54 | { |
47 | struct tuner *t = i2c_get_clientdata(c); | 55 | kfree(fe->tuner_priv); |
56 | fe->tuner_priv = NULL; | ||
48 | 57 | ||
49 | kfree(t->priv); | 58 | return 0; |
50 | t->priv = NULL; | 59 | } |
60 | |||
61 | static int microtune_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
62 | { | ||
63 | struct microtune_priv *priv = fe->tuner_priv; | ||
64 | *frequency = priv->frequency; | ||
65 | return 0; | ||
51 | } | 66 | } |
52 | 67 | ||
53 | // IsSpurInBand()? | 68 | // IsSpurInBand()? |
54 | static int mt2032_spurcheck(struct i2c_client *c, | 69 | static int mt2032_spurcheck(struct dvb_frontend *fe, |
55 | int f1, int f2, int spectrum_from,int spectrum_to) | 70 | int f1, int f2, int spectrum_from,int spectrum_to) |
56 | { | 71 | { |
57 | struct tuner *t = i2c_get_clientdata(c); | 72 | struct microtune_priv *priv = fe->tuner_priv; |
58 | int n1=1,n2,f; | 73 | int n1=1,n2,f; |
59 | 74 | ||
60 | f1=f1/1000; //scale to kHz to avoid 32bit overflows | 75 | f1=f1/1000; //scale to kHz to avoid 32bit overflows |
@@ -82,7 +97,7 @@ static int mt2032_spurcheck(struct i2c_client *c, | |||
82 | return 1; | 97 | return 1; |
83 | } | 98 | } |
84 | 99 | ||
85 | static int mt2032_compute_freq(struct i2c_client *c, | 100 | static int mt2032_compute_freq(struct dvb_frontend *fe, |
86 | unsigned int rfin, | 101 | unsigned int rfin, |
87 | unsigned int if1, unsigned int if2, | 102 | unsigned int if1, unsigned int if2, |
88 | unsigned int spectrum_from, | 103 | unsigned int spectrum_from, |
@@ -91,7 +106,7 @@ static int mt2032_compute_freq(struct i2c_client *c, | |||
91 | int *ret_sel, | 106 | int *ret_sel, |
92 | unsigned int xogc) //all in Hz | 107 | unsigned int xogc) //all in Hz |
93 | { | 108 | { |
94 | struct tuner *t = i2c_get_clientdata(c); | 109 | struct microtune_priv *priv = fe->tuner_priv; |
95 | unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1, | 110 | unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1, |
96 | desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq; | 111 | desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq; |
97 | 112 | ||
@@ -141,7 +156,7 @@ static int mt2032_compute_freq(struct i2c_client *c, | |||
141 | return(-1); | 156 | return(-1); |
142 | } | 157 | } |
143 | 158 | ||
144 | mt2032_spurcheck(c, lo1freq, desired_lo2, spectrum_from, spectrum_to); | 159 | mt2032_spurcheck(fe, lo1freq, desired_lo2, spectrum_from, spectrum_to); |
145 | // should recalculate lo1 (one step up/down) | 160 | // should recalculate lo1 (one step up/down) |
146 | 161 | ||
147 | // set up MT2032 register map for transfer over i2c | 162 | // set up MT2032 register map for transfer over i2c |
@@ -165,16 +180,16 @@ static int mt2032_compute_freq(struct i2c_client *c, | |||
165 | return 0; | 180 | return 0; |
166 | } | 181 | } |
167 | 182 | ||
168 | static int mt2032_check_lo_lock(struct i2c_client *c) | 183 | static int mt2032_check_lo_lock(struct dvb_frontend *fe) |
169 | { | 184 | { |
170 | struct tuner *t = i2c_get_clientdata(c); | 185 | struct microtune_priv *priv = fe->tuner_priv; |
171 | int try,lock=0; | 186 | int try,lock=0; |
172 | unsigned char buf[2]; | 187 | unsigned char buf[2]; |
173 | 188 | ||
174 | for(try=0;try<10;try++) { | 189 | for(try=0;try<10;try++) { |
175 | buf[0]=0x0e; | 190 | buf[0]=0x0e; |
176 | i2c_master_send(c,buf,1); | 191 | tuner_i2c_xfer_send(&priv->i2c_props,buf,1); |
177 | i2c_master_recv(c,buf,1); | 192 | tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); |
178 | tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]); | 193 | tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]); |
179 | lock=buf[0] &0x06; | 194 | lock=buf[0] &0x06; |
180 | 195 | ||
@@ -187,15 +202,15 @@ static int mt2032_check_lo_lock(struct i2c_client *c) | |||
187 | return lock; | 202 | return lock; |
188 | } | 203 | } |
189 | 204 | ||
190 | static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock) | 205 | static int mt2032_optimize_vco(struct dvb_frontend *fe,int sel,int lock) |
191 | { | 206 | { |
192 | struct tuner *t = i2c_get_clientdata(c); | 207 | struct microtune_priv *priv = fe->tuner_priv; |
193 | unsigned char buf[2]; | 208 | unsigned char buf[2]; |
194 | int tad1; | 209 | int tad1; |
195 | 210 | ||
196 | buf[0]=0x0f; | 211 | buf[0]=0x0f; |
197 | i2c_master_send(c,buf,1); | 212 | tuner_i2c_xfer_send(&priv->i2c_props,buf,1); |
198 | i2c_master_recv(c,buf,1); | 213 | tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); |
199 | tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]); | 214 | tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]); |
200 | tad1=buf[0]&0x07; | 215 | tad1=buf[0]&0x07; |
201 | 216 | ||
@@ -218,58 +233,57 @@ static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock) | |||
218 | 233 | ||
219 | buf[0]=0x0f; | 234 | buf[0]=0x0f; |
220 | buf[1]=sel; | 235 | buf[1]=sel; |
221 | i2c_master_send(c,buf,2); | 236 | tuner_i2c_xfer_send(&priv->i2c_props,buf,2); |
222 | lock=mt2032_check_lo_lock(c); | 237 | lock=mt2032_check_lo_lock(fe); |
223 | return lock; | 238 | return lock; |
224 | } | 239 | } |
225 | 240 | ||
226 | 241 | ||
227 | static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, | 242 | static void mt2032_set_if_freq(struct dvb_frontend *fe, unsigned int rfin, |
228 | unsigned int if1, unsigned int if2, | 243 | unsigned int if1, unsigned int if2, |
229 | unsigned int from, unsigned int to) | 244 | unsigned int from, unsigned int to) |
230 | { | 245 | { |
231 | unsigned char buf[21]; | 246 | unsigned char buf[21]; |
232 | int lint_try,ret,sel,lock=0; | 247 | int lint_try,ret,sel,lock=0; |
233 | struct tuner *t = i2c_get_clientdata(c); | 248 | struct microtune_priv *priv = fe->tuner_priv; |
234 | struct microtune_priv *priv = t->priv; | ||
235 | 249 | ||
236 | tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n", | 250 | tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n", |
237 | rfin,if1,if2,from,to); | 251 | rfin,if1,if2,from,to); |
238 | 252 | ||
239 | buf[0]=0; | 253 | buf[0]=0; |
240 | ret=i2c_master_send(c,buf,1); | 254 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1); |
241 | i2c_master_recv(c,buf,21); | 255 | tuner_i2c_xfer_recv(&priv->i2c_props,buf,21); |
242 | 256 | ||
243 | buf[0]=0; | 257 | buf[0]=0; |
244 | ret=mt2032_compute_freq(c,rfin,if1,if2,from,to,&buf[1],&sel,priv->xogc); | 258 | ret=mt2032_compute_freq(fe,rfin,if1,if2,from,to,&buf[1],&sel,priv->xogc); |
245 | if (ret<0) | 259 | if (ret<0) |
246 | return; | 260 | return; |
247 | 261 | ||
248 | // send only the relevant registers per Rev. 1.2 | 262 | // send only the relevant registers per Rev. 1.2 |
249 | buf[0]=0; | 263 | buf[0]=0; |
250 | ret=i2c_master_send(c,buf,4); | 264 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,4); |
251 | buf[5]=5; | 265 | buf[5]=5; |
252 | ret=i2c_master_send(c,buf+5,4); | 266 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,4); |
253 | buf[11]=11; | 267 | buf[11]=11; |
254 | ret=i2c_master_send(c,buf+11,3); | 268 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+11,3); |
255 | if(ret!=3) | 269 | if(ret!=3) |
256 | tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret); | 270 | tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret); |
257 | 271 | ||
258 | // wait for PLLs to lock (per manual), retry LINT if not. | 272 | // wait for PLLs to lock (per manual), retry LINT if not. |
259 | for(lint_try=0; lint_try<2; lint_try++) { | 273 | for(lint_try=0; lint_try<2; lint_try++) { |
260 | lock=mt2032_check_lo_lock(c); | 274 | lock=mt2032_check_lo_lock(fe); |
261 | 275 | ||
262 | if(optimize_vco) | 276 | if(optimize_vco) |
263 | lock=mt2032_optimize_vco(c,sel,lock); | 277 | lock=mt2032_optimize_vco(fe,sel,lock); |
264 | if(lock==6) break; | 278 | if(lock==6) break; |
265 | 279 | ||
266 | tuner_dbg("mt2032: re-init PLLs by LINT\n"); | 280 | tuner_dbg("mt2032: re-init PLLs by LINT\n"); |
267 | buf[0]=7; | 281 | buf[0]=7; |
268 | buf[1]=0x80 +8+priv->xogc; // set LINT to re-init PLLs | 282 | buf[1]=0x80 +8+priv->xogc; // set LINT to re-init PLLs |
269 | i2c_master_send(c,buf,2); | 283 | tuner_i2c_xfer_send(&priv->i2c_props,buf,2); |
270 | mdelay(10); | 284 | mdelay(10); |
271 | buf[1]=8+priv->xogc; | 285 | buf[1]=8+priv->xogc; |
272 | i2c_master_send(c,buf,2); | 286 | tuner_i2c_xfer_send(&priv->i2c_props,buf,2); |
273 | } | 287 | } |
274 | 288 | ||
275 | if (lock!=6) | 289 | if (lock!=6) |
@@ -277,19 +291,19 @@ static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, | |||
277 | 291 | ||
278 | buf[0]=2; | 292 | buf[0]=2; |
279 | buf[1]=0x20; // LOGC for optimal phase noise | 293 | buf[1]=0x20; // LOGC for optimal phase noise |
280 | ret=i2c_master_send(c,buf,2); | 294 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); |
281 | if (ret!=2) | 295 | if (ret!=2) |
282 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); | 296 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); |
283 | } | 297 | } |
284 | 298 | ||
285 | 299 | ||
286 | static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq) | 300 | static int mt2032_set_tv_freq(struct dvb_frontend *fe, |
301 | struct analog_parameters *params) | ||
287 | { | 302 | { |
288 | struct tuner *t = i2c_get_clientdata(c); | ||
289 | int if2,from,to; | 303 | int if2,from,to; |
290 | 304 | ||
291 | // signal bandwidth and picture carrier | 305 | // signal bandwidth and picture carrier |
292 | if (t->std & V4L2_STD_525_60) { | 306 | if (params->std & V4L2_STD_525_60) { |
293 | // NTSC | 307 | // NTSC |
294 | from = 40750*1000; | 308 | from = 40750*1000; |
295 | to = 46750*1000; | 309 | to = 46750*1000; |
@@ -301,32 +315,64 @@ static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
301 | if2 = 38900*1000; | 315 | if2 = 38900*1000; |
302 | } | 316 | } |
303 | 317 | ||
304 | mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, | 318 | mt2032_set_if_freq(fe, params->frequency*62500, |
305 | 1090*1000*1000, if2, from, to); | 319 | 1090*1000*1000, if2, from, to); |
320 | |||
321 | return 0; | ||
306 | } | 322 | } |
307 | 323 | ||
308 | static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq) | 324 | static int mt2032_set_radio_freq(struct dvb_frontend *fe, |
325 | struct analog_parameters *params) | ||
309 | { | 326 | { |
310 | struct tuner *t = i2c_get_clientdata(c); | 327 | struct microtune_priv *priv = fe->tuner_priv; |
311 | struct microtune_priv *priv = t->priv; | 328 | int if2; |
312 | int if2 = priv->radio_if2; | 329 | |
330 | if (params->std & V4L2_STD_525_60) { | ||
331 | tuner_dbg("pinnacle ntsc\n"); | ||
332 | if2 = 41300 * 1000; | ||
333 | } else { | ||
334 | tuner_dbg("pinnacle pal\n"); | ||
335 | if2 = 33300 * 1000; | ||
336 | } | ||
313 | 337 | ||
314 | // per Manual for FM tuning: first if center freq. 1085 MHz | 338 | // per Manual for FM tuning: first if center freq. 1085 MHz |
315 | mt2032_set_if_freq(c, freq * 1000 / 16, | 339 | mt2032_set_if_freq(fe, params->frequency * 125 / 2, |
316 | 1085*1000*1000,if2,if2,if2); | 340 | 1085*1000*1000,if2,if2,if2); |
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int mt2032_set_params(struct dvb_frontend *fe, | ||
346 | struct analog_parameters *params) | ||
347 | { | ||
348 | struct microtune_priv *priv = fe->tuner_priv; | ||
349 | int ret = -EINVAL; | ||
350 | |||
351 | switch (params->mode) { | ||
352 | case V4L2_TUNER_RADIO: | ||
353 | ret = mt2032_set_radio_freq(fe, params); | ||
354 | priv->frequency = params->frequency * 125 / 2; | ||
355 | break; | ||
356 | case V4L2_TUNER_ANALOG_TV: | ||
357 | case V4L2_TUNER_DIGITAL_TV: | ||
358 | ret = mt2032_set_tv_freq(fe, params); | ||
359 | priv->frequency = params->frequency * 62500; | ||
360 | break; | ||
361 | } | ||
362 | |||
363 | return ret; | ||
317 | } | 364 | } |
318 | 365 | ||
319 | static struct tuner_operations mt2032_tuner_ops = { | 366 | static struct dvb_tuner_ops mt2032_tuner_ops = { |
320 | .set_tv_freq = mt2032_set_tv_freq, | 367 | .set_analog_params = mt2032_set_params, |
321 | .set_radio_freq = mt2032_set_radio_freq, | 368 | .release = microtune_release, |
322 | .release = microtune_release, | 369 | .get_frequency = microtune_get_frequency, |
323 | }; | 370 | }; |
324 | 371 | ||
325 | // Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001 | 372 | // Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001 |
326 | static int mt2032_init(struct i2c_client *c) | 373 | static int mt2032_init(struct dvb_frontend *fe) |
327 | { | 374 | { |
328 | struct tuner *t = i2c_get_clientdata(c); | 375 | struct microtune_priv *priv = fe->tuner_priv; |
329 | struct microtune_priv *priv = t->priv; | ||
330 | unsigned char buf[21]; | 376 | unsigned char buf[21]; |
331 | int ret,xogc,xok=0; | 377 | int ret,xogc,xok=0; |
332 | 378 | ||
@@ -335,7 +381,7 @@ static int mt2032_init(struct i2c_client *c) | |||
335 | buf[2]=0xff; | 381 | buf[2]=0xff; |
336 | buf[3]=0x0f; | 382 | buf[3]=0x0f; |
337 | buf[4]=0x1f; | 383 | buf[4]=0x1f; |
338 | ret=i2c_master_send(c,buf+1,4); | 384 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+1,4); |
339 | 385 | ||
340 | buf[5]=6; // Index register 6 | 386 | buf[5]=6; // Index register 6 |
341 | buf[6]=0xe4; | 387 | buf[6]=0xe4; |
@@ -343,11 +389,11 @@ static int mt2032_init(struct i2c_client *c) | |||
343 | buf[8]=0xc3; | 389 | buf[8]=0xc3; |
344 | buf[9]=0x4e; | 390 | buf[9]=0x4e; |
345 | buf[10]=0xec; | 391 | buf[10]=0xec; |
346 | ret=i2c_master_send(c,buf+5,6); | 392 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,6); |
347 | 393 | ||
348 | buf[12]=13; // Index register 13 | 394 | buf[12]=13; // Index register 13 |
349 | buf[13]=0x32; | 395 | buf[13]=0x32; |
350 | ret=i2c_master_send(c,buf+12,2); | 396 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+12,2); |
351 | 397 | ||
352 | // Adjust XOGC (register 7), wait for XOK | 398 | // Adjust XOGC (register 7), wait for XOK |
353 | xogc=7; | 399 | xogc=7; |
@@ -355,8 +401,8 @@ static int mt2032_init(struct i2c_client *c) | |||
355 | tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); | 401 | tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); |
356 | mdelay(10); | 402 | mdelay(10); |
357 | buf[0]=0x0e; | 403 | buf[0]=0x0e; |
358 | i2c_master_send(c,buf,1); | 404 | tuner_i2c_xfer_send(&priv->i2c_props,buf,1); |
359 | i2c_master_recv(c,buf,1); | 405 | tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); |
360 | xok=buf[0]&0x01; | 406 | xok=buf[0]&0x01; |
361 | tuner_dbg("mt2032: xok = 0x%02x\n",xok); | 407 | tuner_dbg("mt2032: xok = 0x%02x\n",xok); |
362 | if (xok == 1) break; | 408 | if (xok == 1) break; |
@@ -369,32 +415,32 @@ static int mt2032_init(struct i2c_client *c) | |||
369 | } | 415 | } |
370 | buf[0]=0x07; | 416 | buf[0]=0x07; |
371 | buf[1]=0x88 + xogc; | 417 | buf[1]=0x88 + xogc; |
372 | ret=i2c_master_send(c,buf,2); | 418 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); |
373 | if (ret!=2) | 419 | if (ret!=2) |
374 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); | 420 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); |
375 | } while (xok != 1 ); | 421 | } while (xok != 1 ); |
376 | priv->xogc=xogc; | 422 | priv->xogc=xogc; |
377 | 423 | ||
378 | memcpy(&t->ops, &mt2032_tuner_ops, sizeof(struct tuner_operations)); | 424 | memcpy(&fe->ops.tuner_ops, &mt2032_tuner_ops, sizeof(struct dvb_tuner_ops)); |
379 | 425 | ||
380 | return(1); | 426 | return(1); |
381 | } | 427 | } |
382 | 428 | ||
383 | static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna) | 429 | static void mt2050_set_antenna(struct dvb_frontend *fe, unsigned char antenna) |
384 | { | 430 | { |
385 | struct tuner *t = i2c_get_clientdata(c); | 431 | struct microtune_priv *priv = fe->tuner_priv; |
386 | unsigned char buf[2]; | 432 | unsigned char buf[2]; |
387 | int ret; | 433 | int ret; |
388 | 434 | ||
389 | buf[0] = 6; | 435 | buf[0] = 6; |
390 | buf[1] = antenna ? 0x11 : 0x10; | 436 | buf[1] = antenna ? 0x11 : 0x10; |
391 | ret=i2c_master_send(c,buf,2); | 437 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); |
392 | tuner_dbg("mt2050: enabled antenna connector %d\n", antenna); | 438 | tuner_dbg("mt2050: enabled antenna connector %d\n", antenna); |
393 | } | 439 | } |
394 | 440 | ||
395 | static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2) | 441 | static void mt2050_set_if_freq(struct dvb_frontend *fe,unsigned int freq, unsigned int if2) |
396 | { | 442 | { |
397 | struct tuner *t = i2c_get_clientdata(c); | 443 | struct microtune_priv *priv = fe->tuner_priv; |
398 | unsigned int if1=1218*1000*1000; | 444 | unsigned int if1=1218*1000*1000; |
399 | unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b; | 445 | unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b; |
400 | int ret; | 446 | int ret; |
@@ -426,7 +472,7 @@ static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned | |||
426 | div2a=(lo2/8)-1; | 472 | div2a=(lo2/8)-1; |
427 | div2b=lo2-(div2a+1)*8; | 473 | div2b=lo2-(div2a+1)*8; |
428 | 474 | ||
429 | if (tuner_debug > 1) { | 475 | if (debug > 1) { |
430 | tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2); | 476 | tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2); |
431 | tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n", | 477 | tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n", |
432 | num1,num2,div1a,div1b,div2a,div2b); | 478 | num1,num2,div1a,div1b,div2a,div2b); |
@@ -442,7 +488,7 @@ static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned | |||
442 | buf[5]=div2a; | 488 | buf[5]=div2a; |
443 | if(num2!=0) buf[5]=buf[5]|0x40; | 489 | if(num2!=0) buf[5]=buf[5]|0x40; |
444 | 490 | ||
445 | if (tuner_debug > 1) { | 491 | if (debug > 1) { |
446 | int i; | 492 | int i; |
447 | tuner_dbg("bufs is: "); | 493 | tuner_dbg("bufs is: "); |
448 | for(i=0;i<6;i++) | 494 | for(i=0;i<6;i++) |
@@ -450,101 +496,131 @@ static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned | |||
450 | printk("\n"); | 496 | printk("\n"); |
451 | } | 497 | } |
452 | 498 | ||
453 | ret=i2c_master_send(c,buf,6); | 499 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,6); |
454 | if (ret!=6) | 500 | if (ret!=6) |
455 | tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret); | 501 | tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret); |
456 | } | 502 | } |
457 | 503 | ||
458 | static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq) | 504 | static int mt2050_set_tv_freq(struct dvb_frontend *fe, |
505 | struct analog_parameters *params) | ||
459 | { | 506 | { |
460 | struct tuner *t = i2c_get_clientdata(c); | ||
461 | unsigned int if2; | 507 | unsigned int if2; |
462 | 508 | ||
463 | if (t->std & V4L2_STD_525_60) { | 509 | if (params->std & V4L2_STD_525_60) { |
464 | // NTSC | 510 | // NTSC |
465 | if2 = 45750*1000; | 511 | if2 = 45750*1000; |
466 | } else { | 512 | } else { |
467 | // PAL | 513 | // PAL |
468 | if2 = 38900*1000; | 514 | if2 = 38900*1000; |
469 | } | 515 | } |
470 | if (V4L2_TUNER_DIGITAL_TV == t->mode) { | 516 | if (V4L2_TUNER_DIGITAL_TV == params->mode) { |
471 | // DVB (pinnacle 300i) | 517 | // DVB (pinnacle 300i) |
472 | if2 = 36150*1000; | 518 | if2 = 36150*1000; |
473 | } | 519 | } |
474 | mt2050_set_if_freq(c, freq*62500, if2); | 520 | mt2050_set_if_freq(fe, params->frequency*62500, if2); |
475 | mt2050_set_antenna(c, tv_antenna); | 521 | mt2050_set_antenna(fe, tv_antenna); |
522 | |||
523 | return 0; | ||
476 | } | 524 | } |
477 | 525 | ||
478 | static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq) | 526 | static int mt2050_set_radio_freq(struct dvb_frontend *fe, |
527 | struct analog_parameters *params) | ||
479 | { | 528 | { |
480 | struct tuner *t = i2c_get_clientdata(c); | 529 | struct microtune_priv *priv = fe->tuner_priv; |
481 | struct microtune_priv *priv = t->priv; | 530 | int if2; |
482 | int if2 = priv->radio_if2; | 531 | |
532 | if (params->std & V4L2_STD_525_60) { | ||
533 | tuner_dbg("pinnacle ntsc\n"); | ||
534 | if2 = 41300 * 1000; | ||
535 | } else { | ||
536 | tuner_dbg("pinnacle pal\n"); | ||
537 | if2 = 33300 * 1000; | ||
538 | } | ||
483 | 539 | ||
484 | mt2050_set_if_freq(c, freq * 1000 / 16, if2); | 540 | mt2050_set_if_freq(fe, params->frequency * 125 / 2, if2); |
485 | mt2050_set_antenna(c, radio_antenna); | 541 | mt2050_set_antenna(fe, radio_antenna); |
542 | |||
543 | return 0; | ||
486 | } | 544 | } |
487 | 545 | ||
488 | static struct tuner_operations mt2050_tuner_ops = { | 546 | static int mt2050_set_params(struct dvb_frontend *fe, |
489 | .set_tv_freq = mt2050_set_tv_freq, | 547 | struct analog_parameters *params) |
490 | .set_radio_freq = mt2050_set_radio_freq, | 548 | { |
491 | .release = microtune_release, | 549 | struct microtune_priv *priv = fe->tuner_priv; |
550 | int ret = -EINVAL; | ||
551 | |||
552 | switch (params->mode) { | ||
553 | case V4L2_TUNER_RADIO: | ||
554 | ret = mt2050_set_radio_freq(fe, params); | ||
555 | priv->frequency = params->frequency * 125 / 2; | ||
556 | break; | ||
557 | case V4L2_TUNER_ANALOG_TV: | ||
558 | case V4L2_TUNER_DIGITAL_TV: | ||
559 | ret = mt2050_set_tv_freq(fe, params); | ||
560 | priv->frequency = params->frequency * 62500; | ||
561 | break; | ||
562 | } | ||
563 | |||
564 | return ret; | ||
565 | } | ||
566 | |||
567 | static struct dvb_tuner_ops mt2050_tuner_ops = { | ||
568 | .set_analog_params = mt2050_set_params, | ||
569 | .release = microtune_release, | ||
570 | .get_frequency = microtune_get_frequency, | ||
492 | }; | 571 | }; |
493 | 572 | ||
494 | static int mt2050_init(struct i2c_client *c) | 573 | static int mt2050_init(struct dvb_frontend *fe) |
495 | { | 574 | { |
496 | struct tuner *t = i2c_get_clientdata(c); | 575 | struct microtune_priv *priv = fe->tuner_priv; |
497 | unsigned char buf[2]; | 576 | unsigned char buf[2]; |
498 | int ret; | 577 | int ret; |
499 | 578 | ||
500 | buf[0]=6; | 579 | buf[0]=6; |
501 | buf[1]=0x10; | 580 | buf[1]=0x10; |
502 | ret=i2c_master_send(c,buf,2); // power | 581 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // power |
503 | 582 | ||
504 | buf[0]=0x0f; | 583 | buf[0]=0x0f; |
505 | buf[1]=0x0f; | 584 | buf[1]=0x0f; |
506 | ret=i2c_master_send(c,buf,2); // m1lo | 585 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // m1lo |
507 | 586 | ||
508 | buf[0]=0x0d; | 587 | buf[0]=0x0d; |
509 | ret=i2c_master_send(c,buf,1); | 588 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1); |
510 | i2c_master_recv(c,buf,1); | 589 | tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); |
511 | 590 | ||
512 | tuner_dbg("mt2050: sro is %x\n",buf[0]); | 591 | tuner_dbg("mt2050: sro is %x\n",buf[0]); |
513 | 592 | ||
514 | memcpy(&t->ops, &mt2050_tuner_ops, sizeof(struct tuner_operations)); | 593 | memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops)); |
515 | 594 | ||
516 | return 0; | 595 | return 0; |
517 | } | 596 | } |
518 | 597 | ||
519 | int microtune_init(struct i2c_client *c) | 598 | struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, |
599 | struct i2c_adapter* i2c_adap, | ||
600 | u8 i2c_addr) | ||
520 | { | 601 | { |
521 | struct microtune_priv *priv = NULL; | 602 | struct microtune_priv *priv = NULL; |
522 | struct tuner *t = i2c_get_clientdata(c); | ||
523 | char *name; | 603 | char *name; |
524 | unsigned char buf[21]; | 604 | unsigned char buf[21]; |
525 | int company_code; | 605 | int company_code; |
526 | 606 | ||
527 | priv = kzalloc(sizeof(struct microtune_priv), GFP_KERNEL); | 607 | priv = kzalloc(sizeof(struct microtune_priv), GFP_KERNEL); |
528 | if (priv == NULL) | 608 | if (priv == NULL) |
529 | return -ENOMEM; | 609 | return NULL; |
530 | t->priv = priv; | 610 | fe->tuner_priv = priv; |
611 | |||
612 | priv->i2c_props.addr = i2c_addr; | ||
613 | priv->i2c_props.adap = i2c_adap; | ||
531 | 614 | ||
532 | priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ | 615 | //priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ |
533 | 616 | ||
534 | memset(buf,0,sizeof(buf)); | 617 | memset(buf,0,sizeof(buf)); |
535 | 618 | ||
536 | if (t->std & V4L2_STD_525_60) { | ||
537 | tuner_dbg("pinnacle ntsc\n"); | ||
538 | priv->radio_if2 = 41300 * 1000; | ||
539 | } else { | ||
540 | tuner_dbg("pinnacle pal\n"); | ||
541 | priv->radio_if2 = 33300 * 1000; | ||
542 | } | ||
543 | name = "unknown"; | 619 | name = "unknown"; |
544 | 620 | ||
545 | i2c_master_send(c,buf,1); | 621 | tuner_i2c_xfer_send(&priv->i2c_props,buf,1); |
546 | i2c_master_recv(c,buf,21); | 622 | tuner_i2c_xfer_recv(&priv->i2c_props,buf,21); |
547 | if (tuner_debug) { | 623 | if (debug) { |
548 | int i; | 624 | int i; |
549 | tuner_dbg("MT20xx hexdump:"); | 625 | tuner_dbg("MT20xx hexdump:"); |
550 | for(i=0;i<21;i++) { | 626 | for(i=0;i<21;i++) { |
@@ -563,10 +639,10 @@ int microtune_init(struct i2c_client *c) | |||
563 | name = microtune_part[buf[0x13]]; | 639 | name = microtune_part[buf[0x13]]; |
564 | switch (buf[0x13]) { | 640 | switch (buf[0x13]) { |
565 | case MT2032: | 641 | case MT2032: |
566 | mt2032_init(c); | 642 | mt2032_init(fe); |
567 | break; | 643 | break; |
568 | case MT2050: | 644 | case MT2050: |
569 | mt2050_init(c); | 645 | mt2050_init(fe); |
570 | break; | 646 | break; |
571 | default: | 647 | default: |
572 | tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n", | 648 | tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n", |
@@ -574,11 +650,18 @@ int microtune_init(struct i2c_client *c) | |||
574 | return 0; | 650 | return 0; |
575 | } | 651 | } |
576 | 652 | ||
577 | strlcpy(c->name, name, sizeof(c->name)); | 653 | strlcpy(fe->ops.tuner_ops.info.name, name, |
654 | sizeof(fe->ops.tuner_ops.info.name)); | ||
578 | tuner_info("microtune %s found, OK\n",name); | 655 | tuner_info("microtune %s found, OK\n",name); |
579 | return 0; | 656 | return fe; |
580 | } | 657 | } |
581 | 658 | ||
659 | EXPORT_SYMBOL_GPL(microtune_attach); | ||
660 | |||
661 | MODULE_DESCRIPTION("Microtune tuner driver"); | ||
662 | MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); | ||
663 | MODULE_LICENSE("GPL"); | ||
664 | |||
582 | /* | 665 | /* |
583 | * Overrides for Emacs so that we follow Linus's tabbing style. | 666 | * Overrides for Emacs so that we follow Linus's tabbing style. |
584 | * --------------------------------------------------------------------------- | 667 | * --------------------------------------------------------------------------- |
diff --git a/drivers/media/video/mt20xx.h b/drivers/media/video/mt20xx.h new file mode 100644 index 000000000000..5e9c825d2e91 --- /dev/null +++ b/drivers/media/video/mt20xx.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | This program is free software; you can redistribute it and/or modify | ||
3 | it under the terms of the GNU General Public License as published by | ||
4 | the Free Software Foundation; either version 2 of the License, or | ||
5 | (at your option) any later version. | ||
6 | |||
7 | This program is distributed in the hope that it will be useful, | ||
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | GNU General Public License for more details. | ||
11 | |||
12 | You should have received a copy of the GNU General Public License | ||
13 | along with this program; if not, write to the Free Software | ||
14 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
15 | */ | ||
16 | |||
17 | #ifndef __MT20XX_H__ | ||
18 | #define __MT20XX_H__ | ||
19 | |||
20 | #include <linux/i2c.h> | ||
21 | #include "dvb_frontend.h" | ||
22 | |||
23 | #if defined(CONFIG_TUNER_MT20XX) || (defined(CONFIG_TUNER_MT20XX_MODULE) && defined(MODULE)) | ||
24 | extern struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, | ||
25 | struct i2c_adapter* i2c_adap, | ||
26 | u8 i2c_addr); | ||
27 | #else | ||
28 | static inline struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, | ||
29 | struct i2c_adapter* i2c_adap, | ||
30 | u8 i2c_addr) | ||
31 | { | ||
32 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | ||
33 | return NULL; | ||
34 | } | ||
35 | #endif | ||
36 | |||
37 | #endif /* __MT20XX_H__ */ | ||
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 152cc6b3e152..98ad3092a079 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c | |||
@@ -153,7 +153,6 @@ static int mxb_probe(struct saa7146_dev* dev) | |||
153 | { | 153 | { |
154 | struct mxb* mxb = NULL; | 154 | struct mxb* mxb = NULL; |
155 | struct i2c_client *client; | 155 | struct i2c_client *client; |
156 | struct list_head *item; | ||
157 | int result; | 156 | int result; |
158 | 157 | ||
159 | if ((result = request_module("saa7111")) < 0) { | 158 | if ((result = request_module("saa7111")) < 0) { |
@@ -196,8 +195,7 @@ static int mxb_probe(struct saa7146_dev* dev) | |||
196 | } | 195 | } |
197 | 196 | ||
198 | /* loop through all i2c-devices on the bus and look who is there */ | 197 | /* loop through all i2c-devices on the bus and look who is there */ |
199 | list_for_each(item,&mxb->i2c_adapter.clients) { | 198 | list_for_each_entry(client, &mxb->i2c_adapter.clients, list) { |
200 | client = list_entry(item, struct i2c_client, list); | ||
201 | if( I2C_ADDR_TEA6420_1 == client->addr ) | 199 | if( I2C_ADDR_TEA6420_1 == client->addr ) |
202 | mxb->tea6420_1 = client; | 200 | mxb->tea6420_1 = client; |
203 | if( I2C_ADDR_TEA6420_2 == client->addr ) | 201 | if( I2C_ADDR_TEA6420_2 == client->addr ) |
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index e5edff1059a2..9eb2562347a8 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c | |||
@@ -5554,41 +5554,46 @@ error: | |||
5554 | * sysfs | 5554 | * sysfs |
5555 | ***************************************************************************/ | 5555 | ***************************************************************************/ |
5556 | 5556 | ||
5557 | static inline struct usb_ov511 *cd_to_ov(struct class_device *cd) | 5557 | static inline struct usb_ov511 *cd_to_ov(struct device *cd) |
5558 | { | 5558 | { |
5559 | struct video_device *vdev = to_video_device(cd); | 5559 | struct video_device *vdev = to_video_device(cd); |
5560 | return video_get_drvdata(vdev); | 5560 | return video_get_drvdata(vdev); |
5561 | } | 5561 | } |
5562 | 5562 | ||
5563 | static ssize_t show_custom_id(struct class_device *cd, char *buf) | 5563 | static ssize_t show_custom_id(struct device *cd, |
5564 | struct device_attribute *attr, char *buf) | ||
5564 | { | 5565 | { |
5565 | struct usb_ov511 *ov = cd_to_ov(cd); | 5566 | struct usb_ov511 *ov = cd_to_ov(cd); |
5566 | return sprintf(buf, "%d\n", ov->customid); | 5567 | return sprintf(buf, "%d\n", ov->customid); |
5567 | } | 5568 | } |
5568 | static CLASS_DEVICE_ATTR(custom_id, S_IRUGO, show_custom_id, NULL); | 5569 | static DEVICE_ATTR(custom_id, S_IRUGO, show_custom_id, NULL); |
5569 | 5570 | ||
5570 | static ssize_t show_model(struct class_device *cd, char *buf) | 5571 | static ssize_t show_model(struct device *cd, |
5572 | struct device_attribute *attr, char *buf) | ||
5571 | { | 5573 | { |
5572 | struct usb_ov511 *ov = cd_to_ov(cd); | 5574 | struct usb_ov511 *ov = cd_to_ov(cd); |
5573 | return sprintf(buf, "%s\n", ov->desc); | 5575 | return sprintf(buf, "%s\n", ov->desc); |
5574 | } | 5576 | } |
5575 | static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL); | 5577 | static DEVICE_ATTR(model, S_IRUGO, show_model, NULL); |
5576 | 5578 | ||
5577 | static ssize_t show_bridge(struct class_device *cd, char *buf) | 5579 | static ssize_t show_bridge(struct device *cd, |
5580 | struct device_attribute *attr, char *buf) | ||
5578 | { | 5581 | { |
5579 | struct usb_ov511 *ov = cd_to_ov(cd); | 5582 | struct usb_ov511 *ov = cd_to_ov(cd); |
5580 | return sprintf(buf, "%s\n", symbolic(brglist, ov->bridge)); | 5583 | return sprintf(buf, "%s\n", symbolic(brglist, ov->bridge)); |
5581 | } | 5584 | } |
5582 | static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_bridge, NULL); | 5585 | static DEVICE_ATTR(bridge, S_IRUGO, show_bridge, NULL); |
5583 | 5586 | ||
5584 | static ssize_t show_sensor(struct class_device *cd, char *buf) | 5587 | static ssize_t show_sensor(struct device *cd, |
5588 | struct device_attribute *attr, char *buf) | ||
5585 | { | 5589 | { |
5586 | struct usb_ov511 *ov = cd_to_ov(cd); | 5590 | struct usb_ov511 *ov = cd_to_ov(cd); |
5587 | return sprintf(buf, "%s\n", symbolic(senlist, ov->sensor)); | 5591 | return sprintf(buf, "%s\n", symbolic(senlist, ov->sensor)); |
5588 | } | 5592 | } |
5589 | static CLASS_DEVICE_ATTR(sensor, S_IRUGO, show_sensor, NULL); | 5593 | static DEVICE_ATTR(sensor, S_IRUGO, show_sensor, NULL); |
5590 | 5594 | ||
5591 | static ssize_t show_brightness(struct class_device *cd, char *buf) | 5595 | static ssize_t show_brightness(struct device *cd, |
5596 | struct device_attribute *attr, char *buf) | ||
5592 | { | 5597 | { |
5593 | struct usb_ov511 *ov = cd_to_ov(cd); | 5598 | struct usb_ov511 *ov = cd_to_ov(cd); |
5594 | unsigned short x; | 5599 | unsigned short x; |
@@ -5598,9 +5603,10 @@ static ssize_t show_brightness(struct class_device *cd, char *buf) | |||
5598 | sensor_get_brightness(ov, &x); | 5603 | sensor_get_brightness(ov, &x); |
5599 | return sprintf(buf, "%d\n", x >> 8); | 5604 | return sprintf(buf, "%d\n", x >> 8); |
5600 | } | 5605 | } |
5601 | static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); | 5606 | static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); |
5602 | 5607 | ||
5603 | static ssize_t show_saturation(struct class_device *cd, char *buf) | 5608 | static ssize_t show_saturation(struct device *cd, |
5609 | struct device_attribute *attr, char *buf) | ||
5604 | { | 5610 | { |
5605 | struct usb_ov511 *ov = cd_to_ov(cd); | 5611 | struct usb_ov511 *ov = cd_to_ov(cd); |
5606 | unsigned short x; | 5612 | unsigned short x; |
@@ -5610,9 +5616,10 @@ static ssize_t show_saturation(struct class_device *cd, char *buf) | |||
5610 | sensor_get_saturation(ov, &x); | 5616 | sensor_get_saturation(ov, &x); |
5611 | return sprintf(buf, "%d\n", x >> 8); | 5617 | return sprintf(buf, "%d\n", x >> 8); |
5612 | } | 5618 | } |
5613 | static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); | 5619 | static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); |
5614 | 5620 | ||
5615 | static ssize_t show_contrast(struct class_device *cd, char *buf) | 5621 | static ssize_t show_contrast(struct device *cd, |
5622 | struct device_attribute *attr, char *buf) | ||
5616 | { | 5623 | { |
5617 | struct usb_ov511 *ov = cd_to_ov(cd); | 5624 | struct usb_ov511 *ov = cd_to_ov(cd); |
5618 | unsigned short x; | 5625 | unsigned short x; |
@@ -5622,9 +5629,10 @@ static ssize_t show_contrast(struct class_device *cd, char *buf) | |||
5622 | sensor_get_contrast(ov, &x); | 5629 | sensor_get_contrast(ov, &x); |
5623 | return sprintf(buf, "%d\n", x >> 8); | 5630 | return sprintf(buf, "%d\n", x >> 8); |
5624 | } | 5631 | } |
5625 | static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); | 5632 | static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); |
5626 | 5633 | ||
5627 | static ssize_t show_hue(struct class_device *cd, char *buf) | 5634 | static ssize_t show_hue(struct device *cd, |
5635 | struct device_attribute *attr, char *buf) | ||
5628 | { | 5636 | { |
5629 | struct usb_ov511 *ov = cd_to_ov(cd); | 5637 | struct usb_ov511 *ov = cd_to_ov(cd); |
5630 | unsigned short x; | 5638 | unsigned short x; |
@@ -5634,9 +5642,10 @@ static ssize_t show_hue(struct class_device *cd, char *buf) | |||
5634 | sensor_get_hue(ov, &x); | 5642 | sensor_get_hue(ov, &x); |
5635 | return sprintf(buf, "%d\n", x >> 8); | 5643 | return sprintf(buf, "%d\n", x >> 8); |
5636 | } | 5644 | } |
5637 | static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); | 5645 | static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); |
5638 | 5646 | ||
5639 | static ssize_t show_exposure(struct class_device *cd, char *buf) | 5647 | static ssize_t show_exposure(struct device *cd, |
5648 | struct device_attribute *attr, char *buf) | ||
5640 | { | 5649 | { |
5641 | struct usb_ov511 *ov = cd_to_ov(cd); | 5650 | struct usb_ov511 *ov = cd_to_ov(cd); |
5642 | unsigned char exp = 0; | 5651 | unsigned char exp = 0; |
@@ -5646,49 +5655,49 @@ static ssize_t show_exposure(struct class_device *cd, char *buf) | |||
5646 | sensor_get_exposure(ov, &exp); | 5655 | sensor_get_exposure(ov, &exp); |
5647 | return sprintf(buf, "%d\n", exp >> 8); | 5656 | return sprintf(buf, "%d\n", exp >> 8); |
5648 | } | 5657 | } |
5649 | static CLASS_DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL); | 5658 | static DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL); |
5650 | 5659 | ||
5651 | static int ov_create_sysfs(struct video_device *vdev) | 5660 | static int ov_create_sysfs(struct video_device *vdev) |
5652 | { | 5661 | { |
5653 | int rc; | 5662 | int rc; |
5654 | 5663 | ||
5655 | rc = video_device_create_file(vdev, &class_device_attr_custom_id); | 5664 | rc = video_device_create_file(vdev, &dev_attr_custom_id); |
5656 | if (rc) goto err; | 5665 | if (rc) goto err; |
5657 | rc = video_device_create_file(vdev, &class_device_attr_model); | 5666 | rc = video_device_create_file(vdev, &dev_attr_model); |
5658 | if (rc) goto err_id; | 5667 | if (rc) goto err_id; |
5659 | rc = video_device_create_file(vdev, &class_device_attr_bridge); | 5668 | rc = video_device_create_file(vdev, &dev_attr_bridge); |
5660 | if (rc) goto err_model; | 5669 | if (rc) goto err_model; |
5661 | rc = video_device_create_file(vdev, &class_device_attr_sensor); | 5670 | rc = video_device_create_file(vdev, &dev_attr_sensor); |
5662 | if (rc) goto err_bridge; | 5671 | if (rc) goto err_bridge; |
5663 | rc = video_device_create_file(vdev, &class_device_attr_brightness); | 5672 | rc = video_device_create_file(vdev, &dev_attr_brightness); |
5664 | if (rc) goto err_sensor; | 5673 | if (rc) goto err_sensor; |
5665 | rc = video_device_create_file(vdev, &class_device_attr_saturation); | 5674 | rc = video_device_create_file(vdev, &dev_attr_saturation); |
5666 | if (rc) goto err_bright; | 5675 | if (rc) goto err_bright; |
5667 | rc = video_device_create_file(vdev, &class_device_attr_contrast); | 5676 | rc = video_device_create_file(vdev, &dev_attr_contrast); |
5668 | if (rc) goto err_sat; | 5677 | if (rc) goto err_sat; |
5669 | rc = video_device_create_file(vdev, &class_device_attr_hue); | 5678 | rc = video_device_create_file(vdev, &dev_attr_hue); |
5670 | if (rc) goto err_contrast; | 5679 | if (rc) goto err_contrast; |
5671 | rc = video_device_create_file(vdev, &class_device_attr_exposure); | 5680 | rc = video_device_create_file(vdev, &dev_attr_exposure); |
5672 | if (rc) goto err_hue; | 5681 | if (rc) goto err_hue; |
5673 | 5682 | ||
5674 | return 0; | 5683 | return 0; |
5675 | 5684 | ||
5676 | err_hue: | 5685 | err_hue: |
5677 | video_device_remove_file(vdev, &class_device_attr_hue); | 5686 | video_device_remove_file(vdev, &dev_attr_hue); |
5678 | err_contrast: | 5687 | err_contrast: |
5679 | video_device_remove_file(vdev, &class_device_attr_contrast); | 5688 | video_device_remove_file(vdev, &dev_attr_contrast); |
5680 | err_sat: | 5689 | err_sat: |
5681 | video_device_remove_file(vdev, &class_device_attr_saturation); | 5690 | video_device_remove_file(vdev, &dev_attr_saturation); |
5682 | err_bright: | 5691 | err_bright: |
5683 | video_device_remove_file(vdev, &class_device_attr_brightness); | 5692 | video_device_remove_file(vdev, &dev_attr_brightness); |
5684 | err_sensor: | 5693 | err_sensor: |
5685 | video_device_remove_file(vdev, &class_device_attr_sensor); | 5694 | video_device_remove_file(vdev, &dev_attr_sensor); |
5686 | err_bridge: | 5695 | err_bridge: |
5687 | video_device_remove_file(vdev, &class_device_attr_bridge); | 5696 | video_device_remove_file(vdev, &dev_attr_bridge); |
5688 | err_model: | 5697 | err_model: |
5689 | video_device_remove_file(vdev, &class_device_attr_model); | 5698 | video_device_remove_file(vdev, &dev_attr_model); |
5690 | err_id: | 5699 | err_id: |
5691 | video_device_remove_file(vdev, &class_device_attr_custom_id); | 5700 | video_device_remove_file(vdev, &dev_attr_custom_id); |
5692 | err: | 5701 | err: |
5693 | return rc; | 5702 | return rc; |
5694 | } | 5703 | } |
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index c4c5bd67f795..2bc6bdc9c1f2 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c | |||
@@ -12,7 +12,6 @@ | |||
12 | */ | 12 | */ |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
17 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
18 | #include <linux/videodev.h> | 17 | #include <linux/videodev.h> |
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c index 3fe9fa04cd84..8063e33f1c85 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_core.c +++ b/drivers/media/video/ovcamchip/ovcamchip_core.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
18 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
19 | #include "ovcamchip_priv.h" | 18 | #include "ovcamchip_priv.h" |
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index 4ab1af74a970..0ef73d9d5848 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c | |||
@@ -844,21 +844,21 @@ cmd_tab_mask_end: | |||
844 | /*********************************/ | 844 | /*********************************/ |
845 | 845 | ||
846 | static int palette2fmt[] = { | 846 | static int palette2fmt[] = { |
847 | 0, | 847 | 0, |
848 | PLANB_GRAY, | 848 | PLANB_GRAY, |
849 | 0, | 849 | 0, |
850 | 0, | 850 | 0, |
851 | 0, | 851 | 0, |
852 | PLANB_COLOUR32, | 852 | PLANB_COLOUR32, |
853 | PLANB_COLOUR15, | 853 | PLANB_COLOUR15, |
854 | 0, | 854 | 0, |
855 | 0, | 855 | 0, |
856 | 0, | 856 | 0, |
857 | 0, | 857 | 0, |
858 | 0, | 858 | 0, |
859 | 0, | 859 | 0, |
860 | 0, | 860 | 0, |
861 | 0, | 861 | 0, |
862 | }; | 862 | }; |
863 | 863 | ||
864 | #define PLANB_PALETTE_MAX 15 | 864 | #define PLANB_PALETTE_MAX 15 |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index 6bbed88d7867..22719ba861ac 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c | |||
@@ -33,8 +33,10 @@ static void pvr2_context_destroy(struct pvr2_context *mp) | |||
33 | { | 33 | { |
34 | if (mp->hdw) pvr2_hdw_destroy(mp->hdw); | 34 | if (mp->hdw) pvr2_hdw_destroy(mp->hdw); |
35 | pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp); | 35 | pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp); |
36 | flush_workqueue(mp->workqueue); | 36 | if (mp->workqueue) { |
37 | destroy_workqueue(mp->workqueue); | 37 | flush_workqueue(mp->workqueue); |
38 | destroy_workqueue(mp->workqueue); | ||
39 | } | ||
38 | kfree(mp); | 40 | kfree(mp); |
39 | } | 41 | } |
40 | 42 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debug.h b/drivers/media/video/pvrusb2/pvrusb2-debug.h index d95a8588e4f8..da6441b88f31 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debug.h +++ b/drivers/media/video/pvrusb2/pvrusb2-debug.h | |||
@@ -26,32 +26,33 @@ extern int pvrusb2_debug; | |||
26 | 26 | ||
27 | /* These are listed in *rough* order of decreasing usefulness and | 27 | /* These are listed in *rough* order of decreasing usefulness and |
28 | increasing noise level. */ | 28 | increasing noise level. */ |
29 | #define PVR2_TRACE_INFO (1 << 0) // Normal messages | 29 | #define PVR2_TRACE_INFO (1 << 0) /* Normal messages */ |
30 | #define PVR2_TRACE_ERROR_LEGS (1 << 1) // error messages | 30 | #define PVR2_TRACE_ERROR_LEGS (1 << 1) /* error messages */ |
31 | #define PVR2_TRACE_TOLERANCE (1 << 2) // track tolerance-affected errors | 31 | #define PVR2_TRACE_TOLERANCE (1 << 2) /* track tolerance-affected errors */ |
32 | #define PVR2_TRACE_TRAP (1 << 3) // Trap & report misbehavior from app | 32 | #define PVR2_TRACE_TRAP (1 << 3) /* Trap & report app misbehavior */ |
33 | #define PVR2_TRACE_INIT (1 << 4) // misc initialization steps | 33 | #define PVR2_TRACE_STD (1 << 4) /* Log video standard stuff */ |
34 | #define PVR2_TRACE_START_STOP (1 << 5) // Streaming start / stop | 34 | #define PVR2_TRACE_INIT (1 << 5) /* misc initialization steps */ |
35 | #define PVR2_TRACE_CTL (1 << 6) // commit of control changes | 35 | #define PVR2_TRACE_START_STOP (1 << 6) /* Streaming start / stop */ |
36 | #define PVR2_TRACE_DEBUG (1 << 7) // Temporary debug code | 36 | #define PVR2_TRACE_CTL (1 << 7) /* commit of control changes */ |
37 | #define PVR2_TRACE_EEPROM (1 << 8) // eeprom parsing / report | 37 | #define PVR2_TRACE_DEBUG (1 << 8) /* Temporary debug code */ |
38 | #define PVR2_TRACE_STRUCT (1 << 9) // internal struct creation | 38 | #define PVR2_TRACE_EEPROM (1 << 9) /* eeprom parsing / report */ |
39 | #define PVR2_TRACE_OPEN_CLOSE (1 << 10) // application open / close | 39 | #define PVR2_TRACE_STRUCT (1 << 10) /* internal struct creation */ |
40 | #define PVR2_TRACE_CREG (1 << 11) // Main critical region entry / exit | 40 | #define PVR2_TRACE_OPEN_CLOSE (1 << 11) /* application open / close */ |
41 | #define PVR2_TRACE_SYSFS (1 << 12) // Sysfs driven I/O | 41 | #define PVR2_TRACE_CREG (1 << 12) /* Main critical region entry / exit */ |
42 | #define PVR2_TRACE_FIRMWARE (1 << 13) // firmware upload actions | 42 | #define PVR2_TRACE_SYSFS (1 << 13) /* Sysfs driven I/O */ |
43 | #define PVR2_TRACE_CHIPS (1 << 14) // chip broadcast operation | 43 | #define PVR2_TRACE_FIRMWARE (1 << 14) /* firmware upload actions */ |
44 | #define PVR2_TRACE_I2C (1 << 15) // I2C related stuff | 44 | #define PVR2_TRACE_CHIPS (1 << 15) /* chip broadcast operation */ |
45 | #define PVR2_TRACE_I2C_CMD (1 << 16) // Software commands to I2C modules | 45 | #define PVR2_TRACE_I2C (1 << 16) /* I2C related stuff */ |
46 | #define PVR2_TRACE_I2C_CORE (1 << 17) // I2C core debugging | 46 | #define PVR2_TRACE_I2C_CMD (1 << 17) /* Software commands to I2C modules */ |
47 | #define PVR2_TRACE_I2C_TRAF (1 << 18) // I2C traffic through the adapter | 47 | #define PVR2_TRACE_I2C_CORE (1 << 18) /* I2C core debugging */ |
48 | #define PVR2_TRACE_V4LIOCTL (1 << 19) // v4l ioctl details | 48 | #define PVR2_TRACE_I2C_TRAF (1 << 19) /* I2C traffic through the adapter */ |
49 | #define PVR2_TRACE_ENCODER (1 << 20) // mpeg2 encoder operation | 49 | #define PVR2_TRACE_V4LIOCTL (1 << 20) /* v4l ioctl details */ |
50 | #define PVR2_TRACE_BUF_POOL (1 << 21) // Track buffer pool management | 50 | #define PVR2_TRACE_ENCODER (1 << 21) /* mpeg2 encoder operation */ |
51 | #define PVR2_TRACE_BUF_FLOW (1 << 22) // Track buffer flow in system | 51 | #define PVR2_TRACE_BUF_POOL (1 << 22) /* Track buffer pool management */ |
52 | #define PVR2_TRACE_DATA_FLOW (1 << 23) // Track data flow | 52 | #define PVR2_TRACE_BUF_FLOW (1 << 23) /* Track buffer flow in system */ |
53 | #define PVR2_TRACE_DEBUGIFC (1 << 24) // Debug interface actions | 53 | #define PVR2_TRACE_DATA_FLOW (1 << 24) /* Track data flow */ |
54 | #define PVR2_TRACE_GPIO (1 << 25) // GPIO state bit changes | 54 | #define PVR2_TRACE_DEBUGIFC (1 << 25) /* Debug interface actions */ |
55 | #define PVR2_TRACE_GPIO (1 << 26) /* GPIO state bit changes */ | ||
55 | 56 | ||
56 | 57 | ||
57 | #endif /* __PVRUSB2_HDW_INTERNAL_H */ | 58 | #endif /* __PVRUSB2_HDW_INTERNAL_H */ |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c index e9da9bb8f8de..6f135f4a2497 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c | |||
@@ -397,10 +397,22 @@ static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf, | |||
397 | count -= scnt; buf += scnt; | 397 | count -= scnt; buf += scnt; |
398 | if (!wptr) return -EINVAL; | 398 | if (!wptr) return -EINVAL; |
399 | if (debugifc_match_keyword(wptr,wlen,"fetch")) { | 399 | if (debugifc_match_keyword(wptr,wlen,"fetch")) { |
400 | pvr2_hdw_cpufw_set_enabled(hdw,!0); | 400 | scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); |
401 | if (scnt && wptr) { | ||
402 | count -= scnt; buf += scnt; | ||
403 | if (debugifc_match_keyword(wptr,wlen,"prom")) { | ||
404 | pvr2_hdw_cpufw_set_enabled(hdw,!0,!0); | ||
405 | } else if (debugifc_match_keyword(wptr,wlen, | ||
406 | "ram")) { | ||
407 | pvr2_hdw_cpufw_set_enabled(hdw,0,!0); | ||
408 | } else { | ||
409 | return -EINVAL; | ||
410 | } | ||
411 | } | ||
412 | pvr2_hdw_cpufw_set_enabled(hdw,0,!0); | ||
401 | return 0; | 413 | return 0; |
402 | } else if (debugifc_match_keyword(wptr,wlen,"done")) { | 414 | } else if (debugifc_match_keyword(wptr,wlen,"done")) { |
403 | pvr2_hdw_cpufw_set_enabled(hdw,0); | 415 | pvr2_hdw_cpufw_set_enabled(hdw,0,0); |
404 | return 0; | 416 | return 0; |
405 | } else { | 417 | } else { |
406 | return -EINVAL; | 418 | return -EINVAL; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index ce66ab8ff2d8..985d9ae7f5ee 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | |||
@@ -238,6 +238,7 @@ struct pvr2_hdw { | |||
238 | // CPU firmware info (used to help find / save firmware data) | 238 | // CPU firmware info (used to help find / save firmware data) |
239 | char *fw_buffer; | 239 | char *fw_buffer; |
240 | unsigned int fw_size; | 240 | unsigned int fw_size; |
241 | int fw_cpu_flag; /* True if we are dealing with the CPU */ | ||
241 | 242 | ||
242 | // Which subsystem pieces have been enabled / configured | 243 | // Which subsystem pieces have been enabled / configured |
243 | unsigned long subsys_enabled_mask; | 244 | unsigned long subsys_enabled_mask; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1311891e7ee3..27b12b4b5c88 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -492,7 +492,7 @@ static int ctrl_cx2341x_get(struct pvr2_ctrl *cptr,int *vp) | |||
492 | cs.controls = &c1; | 492 | cs.controls = &c1; |
493 | cs.count = 1; | 493 | cs.count = 1; |
494 | c1.id = cptr->info->v4l_id; | 494 | c1.id = cptr->info->v4l_id; |
495 | ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs, | 495 | ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state, 0, &cs, |
496 | VIDIOC_G_EXT_CTRLS); | 496 | VIDIOC_G_EXT_CTRLS); |
497 | if (ret) return ret; | 497 | if (ret) return ret; |
498 | *vp = c1.value; | 498 | *vp = c1.value; |
@@ -510,7 +510,7 @@ static int ctrl_cx2341x_set(struct pvr2_ctrl *cptr,int m,int v) | |||
510 | cs.count = 1; | 510 | cs.count = 1; |
511 | c1.id = cptr->info->v4l_id; | 511 | c1.id = cptr->info->v4l_id; |
512 | c1.value = v; | 512 | c1.value = v; |
513 | ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs, | 513 | ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state, 0, &cs, |
514 | VIDIOC_S_EXT_CTRLS); | 514 | VIDIOC_S_EXT_CTRLS); |
515 | if (ret) return ret; | 515 | if (ret) return ret; |
516 | cptr->hdw->enc_stale = !0; | 516 | cptr->hdw->enc_stale = !0; |
@@ -1143,6 +1143,13 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) | |||
1143 | fw_files_24xxx, ARRAY_SIZE(fw_files_24xxx) | 1143 | fw_files_24xxx, ARRAY_SIZE(fw_files_24xxx) |
1144 | }, | 1144 | }, |
1145 | }; | 1145 | }; |
1146 | |||
1147 | if ((hdw->hdw_type >= ARRAY_SIZE(fw_file_defs)) || | ||
1148 | (!fw_file_defs[hdw->hdw_type].lst)) { | ||
1149 | hdw->fw1_state = FW1_STATE_OK; | ||
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1146 | hdw->fw1_state = FW1_STATE_FAILED; // default result | 1153 | hdw->fw1_state = FW1_STATE_FAILED; // default result |
1147 | 1154 | ||
1148 | trace_firmware("pvr2_upload_firmware1"); | 1155 | trace_firmware("pvr2_upload_firmware1"); |
@@ -1224,6 +1231,11 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) | |||
1224 | CX2341X_FIRM_ENC_FILENAME, | 1231 | CX2341X_FIRM_ENC_FILENAME, |
1225 | }; | 1232 | }; |
1226 | 1233 | ||
1234 | if ((hdw->hdw_type != PVR2_HDW_TYPE_29XXX) && | ||
1235 | (hdw->hdw_type != PVR2_HDW_TYPE_24XXX)) { | ||
1236 | return 0; | ||
1237 | } | ||
1238 | |||
1227 | trace_firmware("pvr2_upload_firmware2"); | 1239 | trace_firmware("pvr2_upload_firmware2"); |
1228 | 1240 | ||
1229 | ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder", | 1241 | ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder", |
@@ -1682,6 +1694,44 @@ static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw) | |||
1682 | return result == 0; | 1694 | return result == 0; |
1683 | } | 1695 | } |
1684 | 1696 | ||
1697 | struct pvr2_std_hack { | ||
1698 | v4l2_std_id pat; /* Pattern to match */ | ||
1699 | v4l2_std_id msk; /* Which bits we care about */ | ||
1700 | v4l2_std_id std; /* What additional standards or default to set */ | ||
1701 | }; | ||
1702 | |||
1703 | /* This data structure labels specific combinations of standards from | ||
1704 | tveeprom that we'll try to recognize. If we recognize one, then assume | ||
1705 | a specified default standard to use. This is here because tveeprom only | ||
1706 | tells us about available standards not the intended default standard (if | ||
1707 | any) for the device in question. We guess the default based on what has | ||
1708 | been reported as available. Note that this is only for guessing a | ||
1709 | default - which can always be overridden explicitly - and if the user | ||
1710 | has otherwise named a default then that default will always be used in | ||
1711 | place of this table. */ | ||
1712 | const static struct pvr2_std_hack std_eeprom_maps[] = { | ||
1713 | { /* PAL(B/G) */ | ||
1714 | .pat = V4L2_STD_B|V4L2_STD_GH, | ||
1715 | .std = V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_PAL_G, | ||
1716 | }, | ||
1717 | { /* NTSC(M) */ | ||
1718 | .pat = V4L2_STD_MN, | ||
1719 | .std = V4L2_STD_NTSC_M, | ||
1720 | }, | ||
1721 | { /* PAL(I) */ | ||
1722 | .pat = V4L2_STD_PAL_I, | ||
1723 | .std = V4L2_STD_PAL_I, | ||
1724 | }, | ||
1725 | { /* SECAM(L/L') */ | ||
1726 | .pat = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC, | ||
1727 | .std = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC, | ||
1728 | }, | ||
1729 | { /* PAL(D/D1/K) */ | ||
1730 | .pat = V4L2_STD_DK, | ||
1731 | .std = V4L2_STD_PAL_D/V4L2_STD_PAL_D1|V4L2_STD_PAL_K, | ||
1732 | }, | ||
1733 | }; | ||
1734 | |||
1685 | static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw) | 1735 | static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw) |
1686 | { | 1736 | { |
1687 | char buf[40]; | 1737 | char buf[40]; |
@@ -1691,7 +1741,7 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw) | |||
1691 | std1 = get_default_standard(hdw); | 1741 | std1 = get_default_standard(hdw); |
1692 | 1742 | ||
1693 | bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom); | 1743 | bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom); |
1694 | pvr2_trace(PVR2_TRACE_INIT, | 1744 | pvr2_trace(PVR2_TRACE_STD, |
1695 | "Supported video standard(s) reported by eeprom: %.*s", | 1745 | "Supported video standard(s) reported by eeprom: %.*s", |
1696 | bcnt,buf); | 1746 | bcnt,buf); |
1697 | 1747 | ||
@@ -1700,7 +1750,7 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw) | |||
1700 | std2 = std1 & ~hdw->std_mask_avail; | 1750 | std2 = std1 & ~hdw->std_mask_avail; |
1701 | if (std2) { | 1751 | if (std2) { |
1702 | bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std2); | 1752 | bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std2); |
1703 | pvr2_trace(PVR2_TRACE_INIT, | 1753 | pvr2_trace(PVR2_TRACE_STD, |
1704 | "Expanding supported video standards" | 1754 | "Expanding supported video standards" |
1705 | " to include: %.*s", | 1755 | " to include: %.*s", |
1706 | bcnt,buf); | 1756 | bcnt,buf); |
@@ -1711,7 +1761,7 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw) | |||
1711 | 1761 | ||
1712 | if (std1) { | 1762 | if (std1) { |
1713 | bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std1); | 1763 | bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std1); |
1714 | pvr2_trace(PVR2_TRACE_INIT, | 1764 | pvr2_trace(PVR2_TRACE_STD, |
1715 | "Initial video standard forced to %.*s", | 1765 | "Initial video standard forced to %.*s", |
1716 | bcnt,buf); | 1766 | bcnt,buf); |
1717 | hdw->std_mask_cur = std1; | 1767 | hdw->std_mask_cur = std1; |
@@ -1720,12 +1770,33 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw) | |||
1720 | return; | 1770 | return; |
1721 | } | 1771 | } |
1722 | 1772 | ||
1773 | { | ||
1774 | unsigned int idx; | ||
1775 | for (idx = 0; idx < ARRAY_SIZE(std_eeprom_maps); idx++) { | ||
1776 | if (std_eeprom_maps[idx].msk ? | ||
1777 | ((std_eeprom_maps[idx].pat ^ | ||
1778 | hdw->std_mask_eeprom) & | ||
1779 | std_eeprom_maps[idx].msk) : | ||
1780 | (std_eeprom_maps[idx].pat != | ||
1781 | hdw->std_mask_eeprom)) continue; | ||
1782 | bcnt = pvr2_std_id_to_str(buf,sizeof(buf), | ||
1783 | std_eeprom_maps[idx].std); | ||
1784 | pvr2_trace(PVR2_TRACE_STD, | ||
1785 | "Initial video standard guessed as %.*s", | ||
1786 | bcnt,buf); | ||
1787 | hdw->std_mask_cur = std_eeprom_maps[idx].std; | ||
1788 | hdw->std_dirty = !0; | ||
1789 | pvr2_hdw_internal_find_stdenum(hdw); | ||
1790 | return; | ||
1791 | } | ||
1792 | } | ||
1793 | |||
1723 | if (hdw->std_enum_cnt > 1) { | 1794 | if (hdw->std_enum_cnt > 1) { |
1724 | // Autoselect the first listed standard | 1795 | // Autoselect the first listed standard |
1725 | hdw->std_enum_cur = 1; | 1796 | hdw->std_enum_cur = 1; |
1726 | hdw->std_mask_cur = hdw->std_defs[hdw->std_enum_cur-1].id; | 1797 | hdw->std_mask_cur = hdw->std_defs[hdw->std_enum_cur-1].id; |
1727 | hdw->std_dirty = !0; | 1798 | hdw->std_dirty = !0; |
1728 | pvr2_trace(PVR2_TRACE_INIT, | 1799 | pvr2_trace(PVR2_TRACE_STD, |
1729 | "Initial video standard auto-selected to %s", | 1800 | "Initial video standard auto-selected to %s", |
1730 | hdw->std_defs[hdw->std_enum_cur-1].name); | 1801 | hdw->std_defs[hdw->std_enum_cur-1].name); |
1731 | return; | 1802 | return; |
@@ -1742,29 +1813,35 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) | |||
1742 | unsigned int idx; | 1813 | unsigned int idx; |
1743 | struct pvr2_ctrl *cptr; | 1814 | struct pvr2_ctrl *cptr; |
1744 | int reloadFl = 0; | 1815 | int reloadFl = 0; |
1745 | if (!reloadFl) { | 1816 | if ((hdw->hdw_type == PVR2_HDW_TYPE_29XXX) || |
1746 | reloadFl = (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints | 1817 | (hdw->hdw_type == PVR2_HDW_TYPE_24XXX)) { |
1747 | == 0); | 1818 | if (!reloadFl) { |
1748 | if (reloadFl) { | 1819 | reloadFl = |
1749 | pvr2_trace(PVR2_TRACE_INIT, | 1820 | (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints |
1750 | "USB endpoint config looks strange" | 1821 | == 0); |
1751 | "; possibly firmware needs to be loaded"); | 1822 | if (reloadFl) { |
1823 | pvr2_trace(PVR2_TRACE_INIT, | ||
1824 | "USB endpoint config looks strange" | ||
1825 | "; possibly firmware needs to be" | ||
1826 | " loaded"); | ||
1827 | } | ||
1752 | } | 1828 | } |
1753 | } | 1829 | if (!reloadFl) { |
1754 | if (!reloadFl) { | 1830 | reloadFl = !pvr2_hdw_check_firmware(hdw); |
1755 | reloadFl = !pvr2_hdw_check_firmware(hdw); | 1831 | if (reloadFl) { |
1756 | if (reloadFl) { | 1832 | pvr2_trace(PVR2_TRACE_INIT, |
1757 | pvr2_trace(PVR2_TRACE_INIT, | 1833 | "Check for FX2 firmware failed" |
1758 | "Check for FX2 firmware failed" | 1834 | "; possibly firmware needs to be" |
1759 | "; possibly firmware needs to be loaded"); | 1835 | " loaded"); |
1836 | } | ||
1760 | } | 1837 | } |
1761 | } | 1838 | if (reloadFl) { |
1762 | if (reloadFl) { | 1839 | if (pvr2_upload_firmware1(hdw) != 0) { |
1763 | if (pvr2_upload_firmware1(hdw) != 0) { | 1840 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
1764 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | 1841 | "Failure uploading firmware1"); |
1765 | "Failure uploading firmware1"); | 1842 | } |
1843 | return; | ||
1766 | } | 1844 | } |
1767 | return; | ||
1768 | } | 1845 | } |
1769 | hdw->fw1_state = FW1_STATE_OK; | 1846 | hdw->fw1_state = FW1_STATE_OK; |
1770 | 1847 | ||
@@ -1773,17 +1850,25 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) | |||
1773 | } | 1850 | } |
1774 | if (!pvr2_hdw_dev_ok(hdw)) return; | 1851 | if (!pvr2_hdw_dev_ok(hdw)) return; |
1775 | 1852 | ||
1776 | for (idx = 0; idx < pvr2_client_lists[hdw->hdw_type].cnt; idx++) { | 1853 | if (hdw->hdw_type < ARRAY_SIZE(pvr2_client_lists)) { |
1777 | request_module(pvr2_client_lists[hdw->hdw_type].lst[idx]); | 1854 | for (idx = 0; |
1855 | idx < pvr2_client_lists[hdw->hdw_type].cnt; | ||
1856 | idx++) { | ||
1857 | request_module( | ||
1858 | pvr2_client_lists[hdw->hdw_type].lst[idx]); | ||
1859 | } | ||
1778 | } | 1860 | } |
1779 | 1861 | ||
1780 | pvr2_hdw_cmd_powerup(hdw); | 1862 | if ((hdw->hdw_type == PVR2_HDW_TYPE_29XXX) || |
1781 | if (!pvr2_hdw_dev_ok(hdw)) return; | 1863 | (hdw->hdw_type == PVR2_HDW_TYPE_24XXX)) { |
1864 | pvr2_hdw_cmd_powerup(hdw); | ||
1865 | if (!pvr2_hdw_dev_ok(hdw)) return; | ||
1782 | 1866 | ||
1783 | if (pvr2_upload_firmware2(hdw)){ | 1867 | if (pvr2_upload_firmware2(hdw)){ |
1784 | pvr2_trace(PVR2_TRACE_ERROR_LEGS,"device unstable!!"); | 1868 | pvr2_trace(PVR2_TRACE_ERROR_LEGS,"device unstable!!"); |
1785 | pvr2_hdw_render_useless(hdw); | 1869 | pvr2_hdw_render_useless(hdw); |
1786 | return; | 1870 | return; |
1871 | } | ||
1787 | } | 1872 | } |
1788 | 1873 | ||
1789 | // This step MUST happen after the earlier powerup step. | 1874 | // This step MUST happen after the earlier powerup step. |
@@ -2172,6 +2257,7 @@ static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw) | |||
2172 | /* Destroy hardware interaction structure */ | 2257 | /* Destroy hardware interaction structure */ |
2173 | void pvr2_hdw_destroy(struct pvr2_hdw *hdw) | 2258 | void pvr2_hdw_destroy(struct pvr2_hdw *hdw) |
2174 | { | 2259 | { |
2260 | if (!hdw) return; | ||
2175 | pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw); | 2261 | pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw); |
2176 | if (hdw->fw_buffer) { | 2262 | if (hdw->fw_buffer) { |
2177 | kfree(hdw->fw_buffer); | 2263 | kfree(hdw->fw_buffer); |
@@ -2478,7 +2564,7 @@ static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) | |||
2478 | cs.count = 1; | 2564 | cs.count = 1; |
2479 | c1.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ; | 2565 | c1.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ; |
2480 | c1.value = hdw->srate_val; | 2566 | c1.value = hdw->srate_val; |
2481 | cx2341x_ext_ctrls(&hdw->enc_ctl_state,&cs,VIDIOC_S_EXT_CTRLS); | 2567 | cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,VIDIOC_S_EXT_CTRLS); |
2482 | } | 2568 | } |
2483 | 2569 | ||
2484 | /* Scan i2c core at this point - before we clear all the dirty | 2570 | /* Scan i2c core at this point - before we clear all the dirty |
@@ -2604,7 +2690,85 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) | |||
2604 | } while (0); LOCK_GIVE(hdw->big_lock); | 2690 | } while (0); LOCK_GIVE(hdw->big_lock); |
2605 | } | 2691 | } |
2606 | 2692 | ||
2607 | void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int enable_flag) | 2693 | |
2694 | /* Grab EEPROM contents, needed for direct method. */ | ||
2695 | #define EEPROM_SIZE 8192 | ||
2696 | #define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__) | ||
2697 | static u8 *pvr2_full_eeprom_fetch(struct pvr2_hdw *hdw) | ||
2698 | { | ||
2699 | struct i2c_msg msg[2]; | ||
2700 | u8 *eeprom; | ||
2701 | u8 iadd[2]; | ||
2702 | u8 addr; | ||
2703 | u16 eepromSize; | ||
2704 | unsigned int offs; | ||
2705 | int ret; | ||
2706 | int mode16 = 0; | ||
2707 | unsigned pcnt,tcnt; | ||
2708 | eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL); | ||
2709 | if (!eeprom) { | ||
2710 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
2711 | "Failed to allocate memory" | ||
2712 | " required to read eeprom"); | ||
2713 | return NULL; | ||
2714 | } | ||
2715 | |||
2716 | trace_eeprom("Value for eeprom addr from controller was 0x%x", | ||
2717 | hdw->eeprom_addr); | ||
2718 | addr = hdw->eeprom_addr; | ||
2719 | /* Seems that if the high bit is set, then the *real* eeprom | ||
2720 | address is shifted right now bit position (noticed this in | ||
2721 | newer PVR USB2 hardware) */ | ||
2722 | if (addr & 0x80) addr >>= 1; | ||
2723 | |||
2724 | /* FX2 documentation states that a 16bit-addressed eeprom is | ||
2725 | expected if the I2C address is an odd number (yeah, this is | ||
2726 | strange but it's what they do) */ | ||
2727 | mode16 = (addr & 1); | ||
2728 | eepromSize = (mode16 ? EEPROM_SIZE : 256); | ||
2729 | trace_eeprom("Examining %d byte eeprom at location 0x%x" | ||
2730 | " using %d bit addressing",eepromSize,addr, | ||
2731 | mode16 ? 16 : 8); | ||
2732 | |||
2733 | msg[0].addr = addr; | ||
2734 | msg[0].flags = 0; | ||
2735 | msg[0].len = mode16 ? 2 : 1; | ||
2736 | msg[0].buf = iadd; | ||
2737 | msg[1].addr = addr; | ||
2738 | msg[1].flags = I2C_M_RD; | ||
2739 | |||
2740 | /* We have to do the actual eeprom data fetch ourselves, because | ||
2741 | (1) we're only fetching part of the eeprom, and (2) if we were | ||
2742 | getting the whole thing our I2C driver can't grab it in one | ||
2743 | pass - which is what tveeprom is otherwise going to attempt */ | ||
2744 | memset(eeprom,0,EEPROM_SIZE); | ||
2745 | for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) { | ||
2746 | pcnt = 16; | ||
2747 | if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt; | ||
2748 | offs = tcnt + (eepromSize - EEPROM_SIZE); | ||
2749 | if (mode16) { | ||
2750 | iadd[0] = offs >> 8; | ||
2751 | iadd[1] = offs; | ||
2752 | } else { | ||
2753 | iadd[0] = offs; | ||
2754 | } | ||
2755 | msg[1].len = pcnt; | ||
2756 | msg[1].buf = eeprom+tcnt; | ||
2757 | if ((ret = i2c_transfer(&hdw->i2c_adap, | ||
2758 | msg,ARRAY_SIZE(msg))) != 2) { | ||
2759 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
2760 | "eeprom fetch set offs err=%d",ret); | ||
2761 | kfree(eeprom); | ||
2762 | return NULL; | ||
2763 | } | ||
2764 | } | ||
2765 | return eeprom; | ||
2766 | } | ||
2767 | |||
2768 | |||
2769 | void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, | ||
2770 | int prom_flag, | ||
2771 | int enable_flag) | ||
2608 | { | 2772 | { |
2609 | int ret; | 2773 | int ret; |
2610 | u16 address; | 2774 | u16 address; |
@@ -2618,37 +2782,59 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int enable_flag) | |||
2618 | kfree(hdw->fw_buffer); | 2782 | kfree(hdw->fw_buffer); |
2619 | hdw->fw_buffer = NULL; | 2783 | hdw->fw_buffer = NULL; |
2620 | hdw->fw_size = 0; | 2784 | hdw->fw_size = 0; |
2621 | /* Now release the CPU. It will disconnect and | 2785 | if (hdw->fw_cpu_flag) { |
2622 | reconnect later. */ | 2786 | /* Now release the CPU. It will disconnect |
2623 | pvr2_hdw_cpureset_assert(hdw,0); | 2787 | and reconnect later. */ |
2788 | pvr2_hdw_cpureset_assert(hdw,0); | ||
2789 | } | ||
2624 | break; | 2790 | break; |
2625 | } | 2791 | } |
2626 | 2792 | ||
2627 | pvr2_trace(PVR2_TRACE_FIRMWARE, | 2793 | hdw->fw_cpu_flag = (prom_flag == 0); |
2628 | "Preparing to suck out CPU firmware"); | 2794 | if (hdw->fw_cpu_flag) { |
2629 | hdw->fw_size = 0x2000; | 2795 | pvr2_trace(PVR2_TRACE_FIRMWARE, |
2630 | hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL); | 2796 | "Preparing to suck out CPU firmware"); |
2631 | if (!hdw->fw_buffer) { | 2797 | hdw->fw_size = 0x2000; |
2632 | hdw->fw_size = 0; | 2798 | hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL); |
2633 | break; | 2799 | if (!hdw->fw_buffer) { |
2634 | } | 2800 | hdw->fw_size = 0; |
2801 | break; | ||
2802 | } | ||
2635 | 2803 | ||
2636 | /* We have to hold the CPU during firmware upload. */ | 2804 | /* We have to hold the CPU during firmware upload. */ |
2637 | pvr2_hdw_cpureset_assert(hdw,1); | 2805 | pvr2_hdw_cpureset_assert(hdw,1); |
2638 | 2806 | ||
2639 | /* download the firmware from address 0000-1fff in 2048 | 2807 | /* download the firmware from address 0000-1fff in 2048 |
2640 | (=0x800) bytes chunk. */ | 2808 | (=0x800) bytes chunk. */ |
2641 | 2809 | ||
2642 | pvr2_trace(PVR2_TRACE_FIRMWARE,"Grabbing CPU firmware"); | 2810 | pvr2_trace(PVR2_TRACE_FIRMWARE, |
2643 | pipe = usb_rcvctrlpipe(hdw->usb_dev, 0); | 2811 | "Grabbing CPU firmware"); |
2644 | for(address = 0; address < hdw->fw_size; address += 0x800) { | 2812 | pipe = usb_rcvctrlpipe(hdw->usb_dev, 0); |
2645 | ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0xc0, | 2813 | for(address = 0; address < hdw->fw_size; |
2646 | address,0, | 2814 | address += 0x800) { |
2647 | hdw->fw_buffer+address,0x800,HZ); | 2815 | ret = usb_control_msg(hdw->usb_dev,pipe, |
2648 | if (ret < 0) break; | 2816 | 0xa0,0xc0, |
2649 | } | 2817 | address,0, |
2818 | hdw->fw_buffer+address, | ||
2819 | 0x800,HZ); | ||
2820 | if (ret < 0) break; | ||
2821 | } | ||
2650 | 2822 | ||
2651 | pvr2_trace(PVR2_TRACE_FIRMWARE,"Done grabbing CPU firmware"); | 2823 | pvr2_trace(PVR2_TRACE_FIRMWARE, |
2824 | "Done grabbing CPU firmware"); | ||
2825 | } else { | ||
2826 | pvr2_trace(PVR2_TRACE_FIRMWARE, | ||
2827 | "Sucking down EEPROM contents"); | ||
2828 | hdw->fw_buffer = pvr2_full_eeprom_fetch(hdw); | ||
2829 | if (!hdw->fw_buffer) { | ||
2830 | pvr2_trace(PVR2_TRACE_FIRMWARE, | ||
2831 | "EEPROM content suck failed."); | ||
2832 | break; | ||
2833 | } | ||
2834 | hdw->fw_size = EEPROM_SIZE; | ||
2835 | pvr2_trace(PVR2_TRACE_FIRMWARE, | ||
2836 | "Done sucking down EEPROM contents"); | ||
2837 | } | ||
2652 | 2838 | ||
2653 | } while (0); LOCK_GIVE(hdw->big_lock); | 2839 | } while (0); LOCK_GIVE(hdw->big_lock); |
2654 | } | 2840 | } |
@@ -3272,7 +3458,6 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, | |||
3272 | int setFl,u64 *val_ptr) | 3458 | int setFl,u64 *val_ptr) |
3273 | { | 3459 | { |
3274 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 3460 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
3275 | struct list_head *item; | ||
3276 | struct pvr2_i2c_client *cp; | 3461 | struct pvr2_i2c_client *cp; |
3277 | struct v4l2_register req; | 3462 | struct v4l2_register req; |
3278 | int stat = 0; | 3463 | int stat = 0; |
@@ -3285,8 +3470,7 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, | |||
3285 | req.reg = reg_id; | 3470 | req.reg = reg_id; |
3286 | if (setFl) req.val = *val_ptr; | 3471 | if (setFl) req.val = *val_ptr; |
3287 | mutex_lock(&hdw->i2c_list_lock); do { | 3472 | mutex_lock(&hdw->i2c_list_lock); do { |
3288 | list_for_each(item,&hdw->i2c_clients) { | 3473 | list_for_each_entry(cp, &hdw->i2c_clients, list) { |
3289 | cp = list_entry(item,struct pvr2_i2c_client,list); | ||
3290 | if (!v4l2_chip_match_i2c_client( | 3474 | if (!v4l2_chip_match_i2c_client( |
3291 | cp->client, | 3475 | cp->client, |
3292 | req.match_type, req.match_chip)) { | 3476 | req.match_type, req.match_chip)) { |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 4dba8d006324..e2f9d5e4cb65 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h | |||
@@ -197,11 +197,13 @@ void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw, | |||
197 | unsigned long pvr2_hdw_subsys_stream_get(struct pvr2_hdw *); | 197 | unsigned long pvr2_hdw_subsys_stream_get(struct pvr2_hdw *); |
198 | 198 | ||
199 | 199 | ||
200 | /* Enable / disable retrieval of CPU firmware. This must be enabled before | 200 | /* Enable / disable retrieval of CPU firmware or prom contents. This must |
201 | pvr2_hdw_cpufw_get() will function. Note that doing this may prevent | 201 | be enabled before pvr2_hdw_cpufw_get() will function. Note that doing |
202 | the device from running (and leaving this mode may imply a device | 202 | this may prevent the device from running (and leaving this mode may |
203 | reset). */ | 203 | imply a device reset). */ |
204 | void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *, int enable_flag); | 204 | void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *, |
205 | int prom_flag, | ||
206 | int enable_flag); | ||
205 | 207 | ||
206 | /* Return true if we're in a mode for retrieval CPU firmware */ | 208 | /* Return true if we're in a mode for retrieval CPU firmware */ |
207 | int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *); | 209 | int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *); |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 6786d3c0c98b..898c9d2e4cdf 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | |||
@@ -389,10 +389,6 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
389 | ret = -EINVAL; | 389 | ret = -EINVAL; |
390 | goto done; | 390 | goto done; |
391 | } | 391 | } |
392 | if ((msgs[0].flags & I2C_M_NOSTART)) { | ||
393 | trace_i2c("i2c refusing I2C_M_NOSTART"); | ||
394 | goto done; | ||
395 | } | ||
396 | if (msgs[0].addr < PVR2_I2C_FUNC_CNT) { | 392 | if (msgs[0].addr < PVR2_I2C_FUNC_CNT) { |
397 | funcp = hdw->i2c_func[msgs[0].addr]; | 393 | funcp = hdw->i2c_func[msgs[0].addr]; |
398 | } | 394 | } |
@@ -494,14 +490,12 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
494 | cnt = msgs[idx].len; | 490 | cnt = msgs[idx].len; |
495 | printk(KERN_INFO | 491 | printk(KERN_INFO |
496 | "pvrusb2 i2c xfer %u/%u:" | 492 | "pvrusb2 i2c xfer %u/%u:" |
497 | " addr=0x%x len=%d %s%s", | 493 | " addr=0x%x len=%d %s", |
498 | idx+1,num, | 494 | idx+1,num, |
499 | msgs[idx].addr, | 495 | msgs[idx].addr, |
500 | cnt, | 496 | cnt, |
501 | (msgs[idx].flags & I2C_M_RD ? | 497 | (msgs[idx].flags & I2C_M_RD ? |
502 | "read" : "write"), | 498 | "read" : "write")); |
503 | (msgs[idx].flags & I2C_M_NOSTART ? | ||
504 | " nostart" : "")); | ||
505 | if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) { | 499 | if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) { |
506 | if (cnt > 8) cnt = 8; | 500 | if (cnt > 8) cnt = 8; |
507 | printk(" ["); | 501 | printk(" ["); |
@@ -534,7 +528,7 @@ static int pvr2_i2c_control(struct i2c_adapter *adapter, | |||
534 | 528 | ||
535 | static u32 pvr2_i2c_functionality(struct i2c_adapter *adap) | 529 | static u32 pvr2_i2c_functionality(struct i2c_adapter *adap) |
536 | { | 530 | { |
537 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE_DATA; | 531 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; |
538 | } | 532 | } |
539 | 533 | ||
540 | static int pvr2_i2c_core_singleton(struct i2c_client *cp, | 534 | static int pvr2_i2c_core_singleton(struct i2c_client *cp, |
@@ -576,15 +570,13 @@ int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg) | |||
576 | 570 | ||
577 | int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg) | 571 | int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg) |
578 | { | 572 | { |
579 | struct list_head *item,*nc; | 573 | struct pvr2_i2c_client *cp, *ncp; |
580 | struct pvr2_i2c_client *cp; | ||
581 | int stat = -EINVAL; | 574 | int stat = -EINVAL; |
582 | 575 | ||
583 | if (!hdw) return stat; | 576 | if (!hdw) return stat; |
584 | 577 | ||
585 | mutex_lock(&hdw->i2c_list_lock); | 578 | mutex_lock(&hdw->i2c_list_lock); |
586 | list_for_each_safe(item,nc,&hdw->i2c_clients) { | 579 | list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { |
587 | cp = list_entry(item,struct pvr2_i2c_client,list); | ||
588 | if (!cp->recv_enable) continue; | 580 | if (!cp->recv_enable) continue; |
589 | mutex_unlock(&hdw->i2c_list_lock); | 581 | mutex_unlock(&hdw->i2c_list_lock); |
590 | stat = pvr2_i2c_client_cmd(cp,cmd,arg); | 582 | stat = pvr2_i2c_client_cmd(cp,cmd,arg); |
@@ -608,13 +600,11 @@ static int handler_check(struct pvr2_i2c_client *cp) | |||
608 | 600 | ||
609 | void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) | 601 | void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) |
610 | { | 602 | { |
611 | struct list_head *item; | ||
612 | struct pvr2_i2c_client *cp; | 603 | struct pvr2_i2c_client *cp; |
613 | mutex_lock(&hdw->i2c_list_lock); do { | 604 | mutex_lock(&hdw->i2c_list_lock); do { |
614 | struct v4l2_tuner *vtp = &hdw->tuner_signal_info; | 605 | struct v4l2_tuner *vtp = &hdw->tuner_signal_info; |
615 | memset(vtp,0,sizeof(*vtp)); | 606 | memset(vtp,0,sizeof(*vtp)); |
616 | list_for_each(item,&hdw->i2c_clients) { | 607 | list_for_each_entry(cp, &hdw->i2c_clients, list) { |
617 | cp = list_entry(item,struct pvr2_i2c_client,list); | ||
618 | if (!cp->detected_flag) continue; | 608 | if (!cp->detected_flag) continue; |
619 | if (!cp->status_poll) continue; | 609 | if (!cp->status_poll) continue; |
620 | cp->status_poll(cp); | 610 | cp->status_poll(cp); |
@@ -636,8 +626,7 @@ void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) | |||
636 | { | 626 | { |
637 | unsigned long msk; | 627 | unsigned long msk; |
638 | unsigned int idx; | 628 | unsigned int idx; |
639 | struct list_head *item,*nc; | 629 | struct pvr2_i2c_client *cp, *ncp; |
640 | struct pvr2_i2c_client *cp; | ||
641 | 630 | ||
642 | if (!hdw->i2c_linked) return; | 631 | if (!hdw->i2c_linked) return; |
643 | if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) { | 632 | if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) { |
@@ -655,9 +644,7 @@ void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) | |||
655 | buf = kmalloc(BUFSIZE,GFP_KERNEL); | 644 | buf = kmalloc(BUFSIZE,GFP_KERNEL); |
656 | pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT"); | 645 | pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT"); |
657 | hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT; | 646 | hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT; |
658 | list_for_each(item,&hdw->i2c_clients) { | 647 | list_for_each_entry(cp, &hdw->i2c_clients, list) { |
659 | cp = list_entry(item,struct pvr2_i2c_client, | ||
660 | list); | ||
661 | if (!cp->detected_flag) { | 648 | if (!cp->detected_flag) { |
662 | cp->ctl_mask = 0; | 649 | cp->ctl_mask = 0; |
663 | pvr2_i2c_probe(hdw,cp); | 650 | pvr2_i2c_probe(hdw,cp); |
@@ -693,9 +680,7 @@ void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) | |||
693 | "i2c: PEND_STALE (0x%lx)", | 680 | "i2c: PEND_STALE (0x%lx)", |
694 | hdw->i2c_stale_mask); | 681 | hdw->i2c_stale_mask); |
695 | hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE; | 682 | hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE; |
696 | list_for_each(item,&hdw->i2c_clients) { | 683 | list_for_each_entry(cp, &hdw->i2c_clients, list) { |
697 | cp = list_entry(item,struct pvr2_i2c_client, | ||
698 | list); | ||
699 | m2 = hdw->i2c_stale_mask; | 684 | m2 = hdw->i2c_stale_mask; |
700 | m2 &= cp->ctl_mask; | 685 | m2 &= cp->ctl_mask; |
701 | m2 &= ~cp->pend_mask; | 686 | m2 &= ~cp->pend_mask; |
@@ -716,9 +701,8 @@ void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) | |||
716 | and update each one. */ | 701 | and update each one. */ |
717 | pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT"); | 702 | pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT"); |
718 | hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT; | 703 | hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT; |
719 | list_for_each_safe(item,nc,&hdw->i2c_clients) { | 704 | list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, |
720 | cp = list_entry(item,struct pvr2_i2c_client, | 705 | list) { |
721 | list); | ||
722 | if (!cp->handler) continue; | 706 | if (!cp->handler) continue; |
723 | if (!cp->handler->func_table->update) continue; | 707 | if (!cp->handler->func_table->update) continue; |
724 | pvr2_trace(PVR2_TRACE_I2C_CORE, | 708 | pvr2_trace(PVR2_TRACE_I2C_CORE, |
@@ -750,10 +734,8 @@ void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) | |||
750 | for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { | 734 | for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { |
751 | if (!(pm & msk)) continue; | 735 | if (!(pm & msk)) continue; |
752 | pm &= ~msk; | 736 | pm &= ~msk; |
753 | list_for_each(item,&hdw->i2c_clients) { | 737 | list_for_each_entry(cp, &hdw->i2c_clients, |
754 | cp = list_entry(item, | 738 | list) { |
755 | struct pvr2_i2c_client, | ||
756 | list); | ||
757 | if (cp->pend_mask & msk) { | 739 | if (cp->pend_mask & msk) { |
758 | cp->pend_mask &= ~msk; | 740 | cp->pend_mask &= ~msk; |
759 | cp->recv_enable = !0; | 741 | cp->recv_enable = !0; |
@@ -777,7 +759,6 @@ int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw) | |||
777 | unsigned long msk,sm,pm; | 759 | unsigned long msk,sm,pm; |
778 | unsigned int idx; | 760 | unsigned int idx; |
779 | const struct pvr2_i2c_op *opf; | 761 | const struct pvr2_i2c_op *opf; |
780 | struct list_head *item; | ||
781 | struct pvr2_i2c_client *cp; | 762 | struct pvr2_i2c_client *cp; |
782 | unsigned int pt = 0; | 763 | unsigned int pt = 0; |
783 | 764 | ||
@@ -796,11 +777,9 @@ int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw) | |||
796 | } | 777 | } |
797 | if (sm) pt |= PVR2_I2C_PEND_STALE; | 778 | if (sm) pt |= PVR2_I2C_PEND_STALE; |
798 | 779 | ||
799 | list_for_each(item,&hdw->i2c_clients) { | 780 | list_for_each_entry(cp, &hdw->i2c_clients, list) |
800 | cp = list_entry(item,struct pvr2_i2c_client,list); | 781 | if (handler_check(cp)) |
801 | if (!handler_check(cp)) continue; | 782 | pt |= PVR2_I2C_PEND_CLIENT; |
802 | pt |= PVR2_I2C_PEND_CLIENT; | ||
803 | } | ||
804 | 783 | ||
805 | if (pt) { | 784 | if (pt) { |
806 | mutex_lock(&hdw->i2c_list_lock); do { | 785 | mutex_lock(&hdw->i2c_list_lock); do { |
@@ -888,12 +867,10 @@ unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw, | |||
888 | char *buf,unsigned int maxlen) | 867 | char *buf,unsigned int maxlen) |
889 | { | 868 | { |
890 | unsigned int ccnt,bcnt; | 869 | unsigned int ccnt,bcnt; |
891 | struct list_head *item; | ||
892 | struct pvr2_i2c_client *cp; | 870 | struct pvr2_i2c_client *cp; |
893 | ccnt = 0; | 871 | ccnt = 0; |
894 | mutex_lock(&hdw->i2c_list_lock); do { | 872 | mutex_lock(&hdw->i2c_list_lock); do { |
895 | list_for_each(item,&hdw->i2c_clients) { | 873 | list_for_each_entry(cp, &hdw->i2c_clients, list) { |
896 | cp = list_entry(item,struct pvr2_i2c_client,list); | ||
897 | bcnt = pvr2_i2c_client_describe( | 874 | bcnt = pvr2_i2c_client_describe( |
898 | cp, | 875 | cp, |
899 | (PVR2_I2C_DETAIL_HANDLER| | 876 | (PVR2_I2C_DETAIL_HANDLER| |
@@ -931,13 +908,11 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client) | |||
931 | static int pvr2_i2c_detach_inform(struct i2c_client *client) | 908 | static int pvr2_i2c_detach_inform(struct i2c_client *client) |
932 | { | 909 | { |
933 | struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); | 910 | struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); |
934 | struct pvr2_i2c_client *cp; | 911 | struct pvr2_i2c_client *cp, *ncp; |
935 | struct list_head *item,*nc; | ||
936 | unsigned long amask = 0; | 912 | unsigned long amask = 0; |
937 | int foundfl = 0; | 913 | int foundfl = 0; |
938 | mutex_lock(&hdw->i2c_list_lock); do { | 914 | mutex_lock(&hdw->i2c_list_lock); do { |
939 | list_for_each_safe(item,nc,&hdw->i2c_clients) { | 915 | list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { |
940 | cp = list_entry(item,struct pvr2_i2c_client,list); | ||
941 | if (cp->client == client) { | 916 | if (cp->client == client) { |
942 | trace_i2c("pvr2_i2c_detach" | 917 | trace_i2c("pvr2_i2c_detach" |
943 | " [client=%s @ 0x%x ctxt=%p]", | 918 | " [client=%s @ 0x%x ctxt=%p]", |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c index 9ea41c6699bb..ca9e2789c8ca 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/moduleparam.h> | ||
28 | #include <linux/usb.h> | 27 | #include <linux/usb.h> |
29 | #include <linux/videodev2.h> | 28 | #include <linux/videodev2.h> |
30 | 29 | ||
@@ -42,6 +41,7 @@ | |||
42 | 41 | ||
43 | #define DEFAULT_DEBUG_MASK (PVR2_TRACE_ERROR_LEGS| \ | 42 | #define DEFAULT_DEBUG_MASK (PVR2_TRACE_ERROR_LEGS| \ |
44 | PVR2_TRACE_INFO| \ | 43 | PVR2_TRACE_INFO| \ |
44 | PVR2_TRACE_STD| \ | ||
45 | PVR2_TRACE_TOLERANCE| \ | 45 | PVR2_TRACE_TOLERANCE| \ |
46 | PVR2_TRACE_TRAP| \ | 46 | PVR2_TRACE_TRAP| \ |
47 | 0) | 47 | 0) |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c index 81de26ba41d9..63e55bb59fcb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-std.c +++ b/drivers/media/video/pvrusb2/pvrusb2-std.c | |||
@@ -298,7 +298,7 @@ static int pvr2_std_fill(struct v4l2_standard *std,v4l2_std_id id) | |||
298 | std->id = id; | 298 | std->id = id; |
299 | bcnt = pvr2_std_id_to_str(std->name,sizeof(std->name)-1,id); | 299 | bcnt = pvr2_std_id_to_str(std->name,sizeof(std->name)-1,id); |
300 | std->name[bcnt] = 0; | 300 | std->name[bcnt] = 0; |
301 | pvr2_trace(PVR2_TRACE_INIT,"Set up standard idx=%u name=%s", | 301 | pvr2_trace(PVR2_TRACE_STD,"Set up standard idx=%u name=%s", |
302 | std->index,std->name); | 302 | std->index,std->name); |
303 | return !0; | 303 | return !0; |
304 | } | 304 | } |
@@ -320,11 +320,11 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, | |||
320 | v4l2_std_id idmsk,cmsk,fmsk; | 320 | v4l2_std_id idmsk,cmsk,fmsk; |
321 | struct v4l2_standard *stddefs; | 321 | struct v4l2_standard *stddefs; |
322 | 322 | ||
323 | if (pvrusb2_debug & PVR2_TRACE_INIT) { | 323 | if (pvrusb2_debug & PVR2_TRACE_STD) { |
324 | char buf[50]; | 324 | char buf[50]; |
325 | bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id); | 325 | bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id); |
326 | pvr2_trace( | 326 | pvr2_trace( |
327 | PVR2_TRACE_INIT,"Mapping standards mask=0x%x (%.*s)", | 327 | PVR2_TRACE_STD,"Mapping standards mask=0x%x (%.*s)", |
328 | (int)id,bcnt,buf); | 328 | (int)id,bcnt,buf); |
329 | } | 329 | } |
330 | 330 | ||
@@ -355,7 +355,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, | |||
355 | bcnt,buf); | 355 | bcnt,buf); |
356 | } | 356 | } |
357 | 357 | ||
358 | pvr2_trace(PVR2_TRACE_INIT,"Setting up %u unique standard(s)", | 358 | pvr2_trace(PVR2_TRACE_STD,"Setting up %u unique standard(s)", |
359 | std_cnt); | 359 | std_cnt); |
360 | if (!std_cnt) return NULL; // paranoia | 360 | if (!std_cnt) return NULL; // paranoia |
361 | 361 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 7ab79baa1c8c..7a78d6b34738 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | |||
@@ -33,16 +33,16 @@ | |||
33 | 33 | ||
34 | struct pvr2_sysfs { | 34 | struct pvr2_sysfs { |
35 | struct pvr2_channel channel; | 35 | struct pvr2_channel channel; |
36 | struct class_device *class_dev; | 36 | struct device *class_dev; |
37 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC | 37 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC |
38 | struct pvr2_sysfs_debugifc *debugifc; | 38 | struct pvr2_sysfs_debugifc *debugifc; |
39 | #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ | 39 | #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ |
40 | struct pvr2_sysfs_ctl_item *item_first; | 40 | struct pvr2_sysfs_ctl_item *item_first; |
41 | struct pvr2_sysfs_ctl_item *item_last; | 41 | struct pvr2_sysfs_ctl_item *item_last; |
42 | struct class_device_attribute attr_v4l_minor_number; | 42 | struct device_attribute attr_v4l_minor_number; |
43 | struct class_device_attribute attr_v4l_radio_minor_number; | 43 | struct device_attribute attr_v4l_radio_minor_number; |
44 | struct class_device_attribute attr_unit_number; | 44 | struct device_attribute attr_unit_number; |
45 | struct class_device_attribute attr_bus_info; | 45 | struct device_attribute attr_bus_info; |
46 | int v4l_minor_number_created_ok; | 46 | int v4l_minor_number_created_ok; |
47 | int v4l_radio_minor_number_created_ok; | 47 | int v4l_radio_minor_number_created_ok; |
48 | int unit_number_created_ok; | 48 | int unit_number_created_ok; |
@@ -51,22 +51,22 @@ struct pvr2_sysfs { | |||
51 | 51 | ||
52 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC | 52 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC |
53 | struct pvr2_sysfs_debugifc { | 53 | struct pvr2_sysfs_debugifc { |
54 | struct class_device_attribute attr_debugcmd; | 54 | struct device_attribute attr_debugcmd; |
55 | struct class_device_attribute attr_debuginfo; | 55 | struct device_attribute attr_debuginfo; |
56 | int debugcmd_created_ok; | 56 | int debugcmd_created_ok; |
57 | int debuginfo_created_ok; | 57 | int debuginfo_created_ok; |
58 | }; | 58 | }; |
59 | #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ | 59 | #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ |
60 | 60 | ||
61 | struct pvr2_sysfs_ctl_item { | 61 | struct pvr2_sysfs_ctl_item { |
62 | struct class_device_attribute attr_name; | 62 | struct device_attribute attr_name; |
63 | struct class_device_attribute attr_type; | 63 | struct device_attribute attr_type; |
64 | struct class_device_attribute attr_min; | 64 | struct device_attribute attr_min; |
65 | struct class_device_attribute attr_max; | 65 | struct device_attribute attr_max; |
66 | struct class_device_attribute attr_enum; | 66 | struct device_attribute attr_enum; |
67 | struct class_device_attribute attr_bits; | 67 | struct device_attribute attr_bits; |
68 | struct class_device_attribute attr_val; | 68 | struct device_attribute attr_val; |
69 | struct class_device_attribute attr_custom; | 69 | struct device_attribute attr_custom; |
70 | struct pvr2_ctrl *cptr; | 70 | struct pvr2_ctrl *cptr; |
71 | struct pvr2_sysfs *chptr; | 71 | struct pvr2_sysfs *chptr; |
72 | struct pvr2_sysfs_ctl_item *item_next; | 72 | struct pvr2_sysfs_ctl_item *item_next; |
@@ -80,13 +80,13 @@ struct pvr2_sysfs_class { | |||
80 | struct class class; | 80 | struct class class; |
81 | }; | 81 | }; |
82 | 82 | ||
83 | static ssize_t show_name(int id,struct class_device *class_dev,char *buf) | 83 | static ssize_t show_name(int id,struct device *class_dev,char *buf) |
84 | { | 84 | { |
85 | struct pvr2_ctrl *cptr; | 85 | struct pvr2_ctrl *cptr; |
86 | struct pvr2_sysfs *sfp; | 86 | struct pvr2_sysfs *sfp; |
87 | const char *name; | 87 | const char *name; |
88 | 88 | ||
89 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 89 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
90 | if (!sfp) return -EINVAL; | 90 | if (!sfp) return -EINVAL; |
91 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); | 91 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); |
92 | if (!cptr) return -EINVAL; | 92 | if (!cptr) return -EINVAL; |
@@ -99,14 +99,14 @@ static ssize_t show_name(int id,struct class_device *class_dev,char *buf) | |||
99 | return scnprintf(buf,PAGE_SIZE,"%s\n",name); | 99 | return scnprintf(buf,PAGE_SIZE,"%s\n",name); |
100 | } | 100 | } |
101 | 101 | ||
102 | static ssize_t show_type(int id,struct class_device *class_dev,char *buf) | 102 | static ssize_t show_type(int id,struct device *class_dev,char *buf) |
103 | { | 103 | { |
104 | struct pvr2_ctrl *cptr; | 104 | struct pvr2_ctrl *cptr; |
105 | struct pvr2_sysfs *sfp; | 105 | struct pvr2_sysfs *sfp; |
106 | const char *name; | 106 | const char *name; |
107 | enum pvr2_ctl_type tp; | 107 | enum pvr2_ctl_type tp; |
108 | 108 | ||
109 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 109 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
110 | if (!sfp) return -EINVAL; | 110 | if (!sfp) return -EINVAL; |
111 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); | 111 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); |
112 | if (!cptr) return -EINVAL; | 112 | if (!cptr) return -EINVAL; |
@@ -126,13 +126,13 @@ static ssize_t show_type(int id,struct class_device *class_dev,char *buf) | |||
126 | return scnprintf(buf,PAGE_SIZE,"%s\n",name); | 126 | return scnprintf(buf,PAGE_SIZE,"%s\n",name); |
127 | } | 127 | } |
128 | 128 | ||
129 | static ssize_t show_min(int id,struct class_device *class_dev,char *buf) | 129 | static ssize_t show_min(int id,struct device *class_dev,char *buf) |
130 | { | 130 | { |
131 | struct pvr2_ctrl *cptr; | 131 | struct pvr2_ctrl *cptr; |
132 | struct pvr2_sysfs *sfp; | 132 | struct pvr2_sysfs *sfp; |
133 | long val; | 133 | long val; |
134 | 134 | ||
135 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 135 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
136 | if (!sfp) return -EINVAL; | 136 | if (!sfp) return -EINVAL; |
137 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); | 137 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); |
138 | if (!cptr) return -EINVAL; | 138 | if (!cptr) return -EINVAL; |
@@ -143,13 +143,13 @@ static ssize_t show_min(int id,struct class_device *class_dev,char *buf) | |||
143 | return scnprintf(buf,PAGE_SIZE,"%ld\n",val); | 143 | return scnprintf(buf,PAGE_SIZE,"%ld\n",val); |
144 | } | 144 | } |
145 | 145 | ||
146 | static ssize_t show_max(int id,struct class_device *class_dev,char *buf) | 146 | static ssize_t show_max(int id,struct device *class_dev,char *buf) |
147 | { | 147 | { |
148 | struct pvr2_ctrl *cptr; | 148 | struct pvr2_ctrl *cptr; |
149 | struct pvr2_sysfs *sfp; | 149 | struct pvr2_sysfs *sfp; |
150 | long val; | 150 | long val; |
151 | 151 | ||
152 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 152 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
153 | if (!sfp) return -EINVAL; | 153 | if (!sfp) return -EINVAL; |
154 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); | 154 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); |
155 | if (!cptr) return -EINVAL; | 155 | if (!cptr) return -EINVAL; |
@@ -160,14 +160,14 @@ static ssize_t show_max(int id,struct class_device *class_dev,char *buf) | |||
160 | return scnprintf(buf,PAGE_SIZE,"%ld\n",val); | 160 | return scnprintf(buf,PAGE_SIZE,"%ld\n",val); |
161 | } | 161 | } |
162 | 162 | ||
163 | static ssize_t show_val_norm(int id,struct class_device *class_dev,char *buf) | 163 | static ssize_t show_val_norm(int id,struct device *class_dev,char *buf) |
164 | { | 164 | { |
165 | struct pvr2_ctrl *cptr; | 165 | struct pvr2_ctrl *cptr; |
166 | struct pvr2_sysfs *sfp; | 166 | struct pvr2_sysfs *sfp; |
167 | int val,ret; | 167 | int val,ret; |
168 | unsigned int cnt = 0; | 168 | unsigned int cnt = 0; |
169 | 169 | ||
170 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 170 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
171 | if (!sfp) return -EINVAL; | 171 | if (!sfp) return -EINVAL; |
172 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); | 172 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); |
173 | if (!cptr) return -EINVAL; | 173 | if (!cptr) return -EINVAL; |
@@ -184,14 +184,14 @@ static ssize_t show_val_norm(int id,struct class_device *class_dev,char *buf) | |||
184 | return cnt+1; | 184 | return cnt+1; |
185 | } | 185 | } |
186 | 186 | ||
187 | static ssize_t show_val_custom(int id,struct class_device *class_dev,char *buf) | 187 | static ssize_t show_val_custom(int id,struct device *class_dev,char *buf) |
188 | { | 188 | { |
189 | struct pvr2_ctrl *cptr; | 189 | struct pvr2_ctrl *cptr; |
190 | struct pvr2_sysfs *sfp; | 190 | struct pvr2_sysfs *sfp; |
191 | int val,ret; | 191 | int val,ret; |
192 | unsigned int cnt = 0; | 192 | unsigned int cnt = 0; |
193 | 193 | ||
194 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 194 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
195 | if (!sfp) return -EINVAL; | 195 | if (!sfp) return -EINVAL; |
196 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); | 196 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); |
197 | if (!cptr) return -EINVAL; | 197 | if (!cptr) return -EINVAL; |
@@ -208,14 +208,14 @@ static ssize_t show_val_custom(int id,struct class_device *class_dev,char *buf) | |||
208 | return cnt+1; | 208 | return cnt+1; |
209 | } | 209 | } |
210 | 210 | ||
211 | static ssize_t show_enum(int id,struct class_device *class_dev,char *buf) | 211 | static ssize_t show_enum(int id,struct device *class_dev,char *buf) |
212 | { | 212 | { |
213 | struct pvr2_ctrl *cptr; | 213 | struct pvr2_ctrl *cptr; |
214 | struct pvr2_sysfs *sfp; | 214 | struct pvr2_sysfs *sfp; |
215 | long val; | 215 | long val; |
216 | unsigned int bcnt,ccnt,ecnt; | 216 | unsigned int bcnt,ccnt,ecnt; |
217 | 217 | ||
218 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 218 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
219 | if (!sfp) return -EINVAL; | 219 | if (!sfp) return -EINVAL; |
220 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); | 220 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); |
221 | if (!cptr) return -EINVAL; | 221 | if (!cptr) return -EINVAL; |
@@ -233,14 +233,14 @@ static ssize_t show_enum(int id,struct class_device *class_dev,char *buf) | |||
233 | return bcnt; | 233 | return bcnt; |
234 | } | 234 | } |
235 | 235 | ||
236 | static ssize_t show_bits(int id,struct class_device *class_dev,char *buf) | 236 | static ssize_t show_bits(int id,struct device *class_dev,char *buf) |
237 | { | 237 | { |
238 | struct pvr2_ctrl *cptr; | 238 | struct pvr2_ctrl *cptr; |
239 | struct pvr2_sysfs *sfp; | 239 | struct pvr2_sysfs *sfp; |
240 | int valid_bits,msk; | 240 | int valid_bits,msk; |
241 | unsigned int bcnt,ccnt; | 241 | unsigned int bcnt,ccnt; |
242 | 242 | ||
243 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 243 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
244 | if (!sfp) return -EINVAL; | 244 | if (!sfp) return -EINVAL; |
245 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); | 245 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); |
246 | if (!cptr) return -EINVAL; | 246 | if (!cptr) return -EINVAL; |
@@ -278,23 +278,23 @@ static int store_val_any(int id,int customfl,struct pvr2_sysfs *sfp, | |||
278 | return ret; | 278 | return ret; |
279 | } | 279 | } |
280 | 280 | ||
281 | static ssize_t store_val_norm(int id,struct class_device *class_dev, | 281 | static ssize_t store_val_norm(int id,struct device *class_dev, |
282 | const char *buf,size_t count) | 282 | const char *buf,size_t count) |
283 | { | 283 | { |
284 | struct pvr2_sysfs *sfp; | 284 | struct pvr2_sysfs *sfp; |
285 | int ret; | 285 | int ret; |
286 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 286 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
287 | ret = store_val_any(id,0,sfp,buf,count); | 287 | ret = store_val_any(id,0,sfp,buf,count); |
288 | if (!ret) ret = count; | 288 | if (!ret) ret = count; |
289 | return ret; | 289 | return ret; |
290 | } | 290 | } |
291 | 291 | ||
292 | static ssize_t store_val_custom(int id,struct class_device *class_dev, | 292 | static ssize_t store_val_custom(int id,struct device *class_dev, |
293 | const char *buf,size_t count) | 293 | const char *buf,size_t count) |
294 | { | 294 | { |
295 | struct pvr2_sysfs *sfp; | 295 | struct pvr2_sysfs *sfp; |
296 | int ret; | 296 | int ret; |
297 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 297 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
298 | ret = store_val_any(id,1,sfp,buf,count); | 298 | ret = store_val_any(id,1,sfp,buf,count); |
299 | if (!ret) ret = count; | 299 | if (!ret) ret = count; |
300 | return ret; | 300 | return ret; |
@@ -304,7 +304,7 @@ static ssize_t store_val_custom(int id,struct class_device *class_dev, | |||
304 | Mike Isely <isely@pobox.com> 30-April-2005 | 304 | Mike Isely <isely@pobox.com> 30-April-2005 |
305 | 305 | ||
306 | This next batch of horrible preprocessor hackery is needed because the | 306 | This next batch of horrible preprocessor hackery is needed because the |
307 | kernel's class_device_attribute mechanism fails to pass the actual | 307 | kernel's device_attribute mechanism fails to pass the actual |
308 | attribute through to the show / store functions, which means we have no | 308 | attribute through to the show / store functions, which means we have no |
309 | way to package up any attribute-specific parameters, like for example the | 309 | way to package up any attribute-specific parameters, like for example the |
310 | control id. So we work around this brain-damage by encoding the control | 310 | control id. So we work around this brain-damage by encoding the control |
@@ -314,11 +314,13 @@ static ssize_t store_val_custom(int id,struct class_device *class_dev, | |||
314 | */ | 314 | */ |
315 | 315 | ||
316 | #define CREATE_SHOW_INSTANCE(sf_name,ctl_id) \ | 316 | #define CREATE_SHOW_INSTANCE(sf_name,ctl_id) \ |
317 | static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,char *buf) \ | 317 | static ssize_t sf_name##_##ctl_id(struct device *class_dev, \ |
318 | struct device_attribute *attr, char *buf) \ | ||
318 | { return sf_name(ctl_id,class_dev,buf); } | 319 | { return sf_name(ctl_id,class_dev,buf); } |
319 | 320 | ||
320 | #define CREATE_STORE_INSTANCE(sf_name,ctl_id) \ | 321 | #define CREATE_STORE_INSTANCE(sf_name,ctl_id) \ |
321 | static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,const char *buf,size_t count) \ | 322 | static ssize_t sf_name##_##ctl_id(struct device *class_dev, \ |
323 | struct device_attribute *attr, const char *buf, size_t count) \ | ||
322 | { return sf_name(ctl_id,class_dev,buf,count); } | 324 | { return sf_name(ctl_id,class_dev,buf,count); } |
323 | 325 | ||
324 | #define CREATE_BATCH(ctl_id) \ | 326 | #define CREATE_BATCH(ctl_id) \ |
@@ -395,17 +397,27 @@ CREATE_BATCH(58) | |||
395 | CREATE_BATCH(59) | 397 | CREATE_BATCH(59) |
396 | 398 | ||
397 | struct pvr2_sysfs_func_set { | 399 | struct pvr2_sysfs_func_set { |
398 | ssize_t (*show_name)(struct class_device *,char *); | 400 | ssize_t (*show_name)(struct device *, |
399 | ssize_t (*show_type)(struct class_device *,char *); | 401 | struct device_attribute *attr, char *); |
400 | ssize_t (*show_min)(struct class_device *,char *); | 402 | ssize_t (*show_type)(struct device *, |
401 | ssize_t (*show_max)(struct class_device *,char *); | 403 | struct device_attribute *attr, char *); |
402 | ssize_t (*show_enum)(struct class_device *,char *); | 404 | ssize_t (*show_min)(struct device *, |
403 | ssize_t (*show_bits)(struct class_device *,char *); | 405 | struct device_attribute *attr, char *); |
404 | ssize_t (*show_val_norm)(struct class_device *,char *); | 406 | ssize_t (*show_max)(struct device *, |
405 | ssize_t (*store_val_norm)(struct class_device *, | 407 | struct device_attribute *attr, char *); |
408 | ssize_t (*show_enum)(struct device *, | ||
409 | struct device_attribute *attr, char *); | ||
410 | ssize_t (*show_bits)(struct device *, | ||
411 | struct device_attribute *attr, char *); | ||
412 | ssize_t (*show_val_norm)(struct device *, | ||
413 | struct device_attribute *attr, char *); | ||
414 | ssize_t (*store_val_norm)(struct device *, | ||
415 | struct device_attribute *attr, | ||
406 | const char *,size_t); | 416 | const char *,size_t); |
407 | ssize_t (*show_val_custom)(struct class_device *,char *); | 417 | ssize_t (*show_val_custom)(struct device *, |
408 | ssize_t (*store_val_custom)(struct class_device *, | 418 | struct device_attribute *attr, char *); |
419 | ssize_t (*store_val_custom)(struct device *, | ||
420 | struct device_attribute *attr, | ||
409 | const char *,size_t); | 421 | const char *,size_t); |
410 | }; | 422 | }; |
411 | 423 | ||
@@ -597,9 +609,12 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) | |||
597 | } | 609 | } |
598 | 610 | ||
599 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC | 611 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC |
600 | static ssize_t debuginfo_show(struct class_device *,char *); | 612 | static ssize_t debuginfo_show(struct device *, struct device_attribute *, |
601 | static ssize_t debugcmd_show(struct class_device *,char *); | 613 | char *); |
602 | static ssize_t debugcmd_store(struct class_device *,const char *,size_t count); | 614 | static ssize_t debugcmd_show(struct device *, struct device_attribute *, |
615 | char *); | ||
616 | static ssize_t debugcmd_store(struct device *, struct device_attribute *, | ||
617 | const char *, size_t count); | ||
603 | 618 | ||
604 | static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) | 619 | static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) |
605 | { | 620 | { |
@@ -616,16 +631,16 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) | |||
616 | dip->attr_debuginfo.attr.mode = S_IRUGO; | 631 | dip->attr_debuginfo.attr.mode = S_IRUGO; |
617 | dip->attr_debuginfo.show = debuginfo_show; | 632 | dip->attr_debuginfo.show = debuginfo_show; |
618 | sfp->debugifc = dip; | 633 | sfp->debugifc = dip; |
619 | ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd); | 634 | ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd); |
620 | if (ret < 0) { | 635 | if (ret < 0) { |
621 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", | 636 | printk(KERN_WARNING "%s: device_create_file error: %d\n", |
622 | __FUNCTION__, ret); | 637 | __FUNCTION__, ret); |
623 | } else { | 638 | } else { |
624 | dip->debugcmd_created_ok = !0; | 639 | dip->debugcmd_created_ok = !0; |
625 | } | 640 | } |
626 | ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo); | 641 | ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo); |
627 | if (ret < 0) { | 642 | if (ret < 0) { |
628 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", | 643 | printk(KERN_WARNING "%s: device_create_file error: %d\n", |
629 | __FUNCTION__, ret); | 644 | __FUNCTION__, ret); |
630 | } else { | 645 | } else { |
631 | dip->debuginfo_created_ok = !0; | 646 | dip->debuginfo_created_ok = !0; |
@@ -637,11 +652,11 @@ static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp) | |||
637 | { | 652 | { |
638 | if (!sfp->debugifc) return; | 653 | if (!sfp->debugifc) return; |
639 | if (sfp->debugifc->debuginfo_created_ok) { | 654 | if (sfp->debugifc->debuginfo_created_ok) { |
640 | class_device_remove_file(sfp->class_dev, | 655 | device_remove_file(sfp->class_dev, |
641 | &sfp->debugifc->attr_debuginfo); | 656 | &sfp->debugifc->attr_debuginfo); |
642 | } | 657 | } |
643 | if (sfp->debugifc->debugcmd_created_ok) { | 658 | if (sfp->debugifc->debugcmd_created_ok) { |
644 | class_device_remove_file(sfp->class_dev, | 659 | device_remove_file(sfp->class_dev, |
645 | &sfp->debugifc->attr_debugcmd); | 660 | &sfp->debugifc->attr_debugcmd); |
646 | } | 661 | } |
647 | kfree(sfp->debugifc); | 662 | kfree(sfp->debugifc); |
@@ -683,7 +698,7 @@ static void pvr2_sysfs_class_release(struct class *class) | |||
683 | } | 698 | } |
684 | 699 | ||
685 | 700 | ||
686 | static void pvr2_sysfs_release(struct class_device *class_dev) | 701 | static void pvr2_sysfs_release(struct device *class_dev) |
687 | { | 702 | { |
688 | pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev); | 703 | pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev); |
689 | kfree(class_dev); | 704 | kfree(class_dev); |
@@ -698,32 +713,33 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp) | |||
698 | #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ | 713 | #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ |
699 | pvr2_sysfs_tear_down_controls(sfp); | 714 | pvr2_sysfs_tear_down_controls(sfp); |
700 | if (sfp->bus_info_created_ok) { | 715 | if (sfp->bus_info_created_ok) { |
701 | class_device_remove_file(sfp->class_dev, | 716 | device_remove_file(sfp->class_dev, |
702 | &sfp->attr_bus_info); | 717 | &sfp->attr_bus_info); |
703 | } | 718 | } |
704 | if (sfp->v4l_minor_number_created_ok) { | 719 | if (sfp->v4l_minor_number_created_ok) { |
705 | class_device_remove_file(sfp->class_dev, | 720 | device_remove_file(sfp->class_dev, |
706 | &sfp->attr_v4l_minor_number); | 721 | &sfp->attr_v4l_minor_number); |
707 | } | 722 | } |
708 | if (sfp->v4l_radio_minor_number_created_ok) { | 723 | if (sfp->v4l_radio_minor_number_created_ok) { |
709 | class_device_remove_file(sfp->class_dev, | 724 | device_remove_file(sfp->class_dev, |
710 | &sfp->attr_v4l_radio_minor_number); | 725 | &sfp->attr_v4l_radio_minor_number); |
711 | } | 726 | } |
712 | if (sfp->unit_number_created_ok) { | 727 | if (sfp->unit_number_created_ok) { |
713 | class_device_remove_file(sfp->class_dev, | 728 | device_remove_file(sfp->class_dev, |
714 | &sfp->attr_unit_number); | 729 | &sfp->attr_unit_number); |
715 | } | 730 | } |
716 | pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); | 731 | pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); |
717 | sfp->class_dev->class_data = NULL; | 732 | sfp->class_dev->driver_data = NULL; |
718 | class_device_unregister(sfp->class_dev); | 733 | device_unregister(sfp->class_dev); |
719 | sfp->class_dev = NULL; | 734 | sfp->class_dev = NULL; |
720 | } | 735 | } |
721 | 736 | ||
722 | 737 | ||
723 | static ssize_t v4l_minor_number_show(struct class_device *class_dev,char *buf) | 738 | static ssize_t v4l_minor_number_show(struct device *class_dev, |
739 | struct device_attribute *attr, char *buf) | ||
724 | { | 740 | { |
725 | struct pvr2_sysfs *sfp; | 741 | struct pvr2_sysfs *sfp; |
726 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 742 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
727 | if (!sfp) return -EINVAL; | 743 | if (!sfp) return -EINVAL; |
728 | return scnprintf(buf,PAGE_SIZE,"%d\n", | 744 | return scnprintf(buf,PAGE_SIZE,"%d\n", |
729 | pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, | 745 | pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, |
@@ -731,21 +747,23 @@ static ssize_t v4l_minor_number_show(struct class_device *class_dev,char *buf) | |||
731 | } | 747 | } |
732 | 748 | ||
733 | 749 | ||
734 | static ssize_t bus_info_show(struct class_device *class_dev,char *buf) | 750 | static ssize_t bus_info_show(struct device *class_dev, |
751 | struct device_attribute *attr, char *buf) | ||
735 | { | 752 | { |
736 | struct pvr2_sysfs *sfp; | 753 | struct pvr2_sysfs *sfp; |
737 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 754 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
738 | if (!sfp) return -EINVAL; | 755 | if (!sfp) return -EINVAL; |
739 | return scnprintf(buf,PAGE_SIZE,"%s\n", | 756 | return scnprintf(buf,PAGE_SIZE,"%s\n", |
740 | pvr2_hdw_get_bus_info(sfp->channel.hdw)); | 757 | pvr2_hdw_get_bus_info(sfp->channel.hdw)); |
741 | } | 758 | } |
742 | 759 | ||
743 | 760 | ||
744 | static ssize_t v4l_radio_minor_number_show(struct class_device *class_dev, | 761 | static ssize_t v4l_radio_minor_number_show(struct device *class_dev, |
762 | struct device_attribute *attr, | ||
745 | char *buf) | 763 | char *buf) |
746 | { | 764 | { |
747 | struct pvr2_sysfs *sfp; | 765 | struct pvr2_sysfs *sfp; |
748 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 766 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
749 | if (!sfp) return -EINVAL; | 767 | if (!sfp) return -EINVAL; |
750 | return scnprintf(buf,PAGE_SIZE,"%d\n", | 768 | return scnprintf(buf,PAGE_SIZE,"%d\n", |
751 | pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, | 769 | pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, |
@@ -753,10 +771,11 @@ static ssize_t v4l_radio_minor_number_show(struct class_device *class_dev, | |||
753 | } | 771 | } |
754 | 772 | ||
755 | 773 | ||
756 | static ssize_t unit_number_show(struct class_device *class_dev,char *buf) | 774 | static ssize_t unit_number_show(struct device *class_dev, |
775 | struct device_attribute *attr, char *buf) | ||
757 | { | 776 | { |
758 | struct pvr2_sysfs *sfp; | 777 | struct pvr2_sysfs *sfp; |
759 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 778 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
760 | if (!sfp) return -EINVAL; | 779 | if (!sfp) return -EINVAL; |
761 | return scnprintf(buf,PAGE_SIZE,"%d\n", | 780 | return scnprintf(buf,PAGE_SIZE,"%d\n", |
762 | pvr2_hdw_get_unit_number(sfp->channel.hdw)); | 781 | pvr2_hdw_get_unit_number(sfp->channel.hdw)); |
@@ -767,7 +786,7 @@ static void class_dev_create(struct pvr2_sysfs *sfp, | |||
767 | struct pvr2_sysfs_class *class_ptr) | 786 | struct pvr2_sysfs_class *class_ptr) |
768 | { | 787 | { |
769 | struct usb_device *usb_dev; | 788 | struct usb_device *usb_dev; |
770 | struct class_device *class_dev; | 789 | struct device *class_dev; |
771 | int ret; | 790 | int ret; |
772 | 791 | ||
773 | usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw); | 792 | usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw); |
@@ -779,23 +798,23 @@ static void class_dev_create(struct pvr2_sysfs *sfp, | |||
779 | 798 | ||
780 | class_dev->class = &class_ptr->class; | 799 | class_dev->class = &class_ptr->class; |
781 | if (pvr2_hdw_get_sn(sfp->channel.hdw)) { | 800 | if (pvr2_hdw_get_sn(sfp->channel.hdw)) { |
782 | snprintf(class_dev->class_id,BUS_ID_SIZE,"sn-%lu", | 801 | snprintf(class_dev->bus_id, BUS_ID_SIZE, "sn-%lu", |
783 | pvr2_hdw_get_sn(sfp->channel.hdw)); | 802 | pvr2_hdw_get_sn(sfp->channel.hdw)); |
784 | } else if (pvr2_hdw_get_unit_number(sfp->channel.hdw) >= 0) { | 803 | } else if (pvr2_hdw_get_unit_number(sfp->channel.hdw) >= 0) { |
785 | snprintf(class_dev->class_id,BUS_ID_SIZE,"unit-%c", | 804 | snprintf(class_dev->bus_id, BUS_ID_SIZE, "unit-%c", |
786 | pvr2_hdw_get_unit_number(sfp->channel.hdw) + 'a'); | 805 | pvr2_hdw_get_unit_number(sfp->channel.hdw) + 'a'); |
787 | } else { | 806 | } else { |
788 | kfree(class_dev); | 807 | kfree(class_dev); |
789 | return; | 808 | return; |
790 | } | 809 | } |
791 | 810 | ||
792 | class_dev->dev = &usb_dev->dev; | 811 | class_dev->parent = &usb_dev->dev; |
793 | 812 | ||
794 | sfp->class_dev = class_dev; | 813 | sfp->class_dev = class_dev; |
795 | class_dev->class_data = sfp; | 814 | class_dev->driver_data = sfp; |
796 | ret = class_device_register(class_dev); | 815 | ret = device_register(class_dev); |
797 | if (ret) { | 816 | if (ret) { |
798 | printk(KERN_ERR "%s: class_device_register failed\n", | 817 | printk(KERN_ERR "%s: device_register failed\n", |
799 | __FUNCTION__); | 818 | __FUNCTION__); |
800 | kfree(class_dev); | 819 | kfree(class_dev); |
801 | return; | 820 | return; |
@@ -805,10 +824,10 @@ static void class_dev_create(struct pvr2_sysfs *sfp, | |||
805 | sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; | 824 | sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; |
806 | sfp->attr_v4l_minor_number.show = v4l_minor_number_show; | 825 | sfp->attr_v4l_minor_number.show = v4l_minor_number_show; |
807 | sfp->attr_v4l_minor_number.store = NULL; | 826 | sfp->attr_v4l_minor_number.store = NULL; |
808 | ret = class_device_create_file(sfp->class_dev, | 827 | ret = device_create_file(sfp->class_dev, |
809 | &sfp->attr_v4l_minor_number); | 828 | &sfp->attr_v4l_minor_number); |
810 | if (ret < 0) { | 829 | if (ret < 0) { |
811 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", | 830 | printk(KERN_WARNING "%s: device_create_file error: %d\n", |
812 | __FUNCTION__, ret); | 831 | __FUNCTION__, ret); |
813 | } else { | 832 | } else { |
814 | sfp->v4l_minor_number_created_ok = !0; | 833 | sfp->v4l_minor_number_created_ok = !0; |
@@ -818,10 +837,10 @@ static void class_dev_create(struct pvr2_sysfs *sfp, | |||
818 | sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO; | 837 | sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO; |
819 | sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show; | 838 | sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show; |
820 | sfp->attr_v4l_radio_minor_number.store = NULL; | 839 | sfp->attr_v4l_radio_minor_number.store = NULL; |
821 | ret = class_device_create_file(sfp->class_dev, | 840 | ret = device_create_file(sfp->class_dev, |
822 | &sfp->attr_v4l_radio_minor_number); | 841 | &sfp->attr_v4l_radio_minor_number); |
823 | if (ret < 0) { | 842 | if (ret < 0) { |
824 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", | 843 | printk(KERN_WARNING "%s: device_create_file error: %d\n", |
825 | __FUNCTION__, ret); | 844 | __FUNCTION__, ret); |
826 | } else { | 845 | } else { |
827 | sfp->v4l_radio_minor_number_created_ok = !0; | 846 | sfp->v4l_radio_minor_number_created_ok = !0; |
@@ -831,9 +850,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp, | |||
831 | sfp->attr_unit_number.attr.mode = S_IRUGO; | 850 | sfp->attr_unit_number.attr.mode = S_IRUGO; |
832 | sfp->attr_unit_number.show = unit_number_show; | 851 | sfp->attr_unit_number.show = unit_number_show; |
833 | sfp->attr_unit_number.store = NULL; | 852 | sfp->attr_unit_number.store = NULL; |
834 | ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number); | 853 | ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number); |
835 | if (ret < 0) { | 854 | if (ret < 0) { |
836 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", | 855 | printk(KERN_WARNING "%s: device_create_file error: %d\n", |
837 | __FUNCTION__, ret); | 856 | __FUNCTION__, ret); |
838 | } else { | 857 | } else { |
839 | sfp->unit_number_created_ok = !0; | 858 | sfp->unit_number_created_ok = !0; |
@@ -843,10 +862,10 @@ static void class_dev_create(struct pvr2_sysfs *sfp, | |||
843 | sfp->attr_bus_info.attr.mode = S_IRUGO; | 862 | sfp->attr_bus_info.attr.mode = S_IRUGO; |
844 | sfp->attr_bus_info.show = bus_info_show; | 863 | sfp->attr_bus_info.show = bus_info_show; |
845 | sfp->attr_bus_info.store = NULL; | 864 | sfp->attr_bus_info.store = NULL; |
846 | ret = class_device_create_file(sfp->class_dev, | 865 | ret = device_create_file(sfp->class_dev, |
847 | &sfp->attr_bus_info); | 866 | &sfp->attr_bus_info); |
848 | if (ret < 0) { | 867 | if (ret < 0) { |
849 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", | 868 | printk(KERN_WARNING "%s: device_create_file error: %d\n", |
850 | __FUNCTION__, ret); | 869 | __FUNCTION__, ret); |
851 | } else { | 870 | } else { |
852 | sfp->bus_info_created_ok = !0; | 871 | sfp->bus_info_created_ok = !0; |
@@ -886,7 +905,7 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp, | |||
886 | } | 905 | } |
887 | 906 | ||
888 | 907 | ||
889 | static int pvr2_sysfs_hotplug(struct class_device *cd,char **envp, | 908 | static int pvr2_sysfs_hotplug(struct device *cd,char **envp, |
890 | int numenvp,char *buf,int size) | 909 | int numenvp,char *buf,int size) |
891 | { | 910 | { |
892 | /* Even though we don't do anything here, we still need this function | 911 | /* Even though we don't do anything here, we still need this function |
@@ -902,8 +921,8 @@ struct pvr2_sysfs_class *pvr2_sysfs_class_create(void) | |||
902 | pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp); | 921 | pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp); |
903 | clp->class.name = "pvrusb2"; | 922 | clp->class.name = "pvrusb2"; |
904 | clp->class.class_release = pvr2_sysfs_class_release; | 923 | clp->class.class_release = pvr2_sysfs_class_release; |
905 | clp->class.release = pvr2_sysfs_release; | 924 | clp->class.dev_release = pvr2_sysfs_release; |
906 | clp->class.uevent = pvr2_sysfs_hotplug; | 925 | clp->class.dev_uevent = pvr2_sysfs_hotplug; |
907 | if (class_register(&clp->class)) { | 926 | if (class_register(&clp->class)) { |
908 | pvr2_sysfs_trace( | 927 | pvr2_sysfs_trace( |
909 | "Registration failed for pvr2_sysfs_class id=%p",clp); | 928 | "Registration failed for pvr2_sysfs_class id=%p",clp); |
@@ -921,32 +940,35 @@ void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp) | |||
921 | 940 | ||
922 | 941 | ||
923 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC | 942 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC |
924 | static ssize_t debuginfo_show(struct class_device *class_dev,char *buf) | 943 | static ssize_t debuginfo_show(struct device *class_dev, |
944 | struct device_attribute *attr, char *buf) | ||
925 | { | 945 | { |
926 | struct pvr2_sysfs *sfp; | 946 | struct pvr2_sysfs *sfp; |
927 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 947 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
928 | if (!sfp) return -EINVAL; | 948 | if (!sfp) return -EINVAL; |
929 | pvr2_hdw_trigger_module_log(sfp->channel.hdw); | 949 | pvr2_hdw_trigger_module_log(sfp->channel.hdw); |
930 | return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE); | 950 | return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE); |
931 | } | 951 | } |
932 | 952 | ||
933 | 953 | ||
934 | static ssize_t debugcmd_show(struct class_device *class_dev,char *buf) | 954 | static ssize_t debugcmd_show(struct device *class_dev, |
955 | struct device_attribute *attr, char *buf) | ||
935 | { | 956 | { |
936 | struct pvr2_sysfs *sfp; | 957 | struct pvr2_sysfs *sfp; |
937 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 958 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
938 | if (!sfp) return -EINVAL; | 959 | if (!sfp) return -EINVAL; |
939 | return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE); | 960 | return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE); |
940 | } | 961 | } |
941 | 962 | ||
942 | 963 | ||
943 | static ssize_t debugcmd_store(struct class_device *class_dev, | 964 | static ssize_t debugcmd_store(struct device *class_dev, |
944 | const char *buf,size_t count) | 965 | struct device_attribute *attr, |
966 | const char *buf, size_t count) | ||
945 | { | 967 | { |
946 | struct pvr2_sysfs *sfp; | 968 | struct pvr2_sysfs *sfp; |
947 | int ret; | 969 | int ret; |
948 | 970 | ||
949 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 971 | sfp = (struct pvr2_sysfs *)class_dev->driver_data; |
950 | if (!sfp) return -EINVAL; | 972 | if (!sfp) return -EINVAL; |
951 | 973 | ||
952 | ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count); | 974 | ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count); |
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index 338ced7188f2..ea53316d2111 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c | |||
@@ -1648,7 +1648,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) | |||
1648 | ARG_OUT(cmd) | 1648 | ARG_OUT(cmd) |
1649 | break; | 1649 | break; |
1650 | } | 1650 | } |
1651 | /* | 1651 | /* |
1652 | case VIDIOCPWCGVIDTABLE: | 1652 | case VIDIOCPWCGVIDTABLE: |
1653 | { | 1653 | { |
1654 | ARG_DEF(struct pwc_table_init_buffer, table); | 1654 | ARG_DEF(struct pwc_table_init_buffer, table); |
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 931b274bffca..0b67d4ec0318 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
@@ -64,7 +64,6 @@ | |||
64 | #include <linux/vmalloc.h> | 64 | #include <linux/vmalloc.h> |
65 | #include <linux/version.h> | 65 | #include <linux/version.h> |
66 | #include <asm/io.h> | 66 | #include <asm/io.h> |
67 | #include <linux/moduleparam.h> | ||
68 | 67 | ||
69 | #include "pwc.h" | 68 | #include "pwc.h" |
70 | #include "pwc-kiara.h" | 69 | #include "pwc-kiara.h" |
@@ -127,9 +126,9 @@ static struct usb_driver pwc_driver = { | |||
127 | static int default_size = PSZ_QCIF; | 126 | static int default_size = PSZ_QCIF; |
128 | static int default_fps = 10; | 127 | static int default_fps = 10; |
129 | static int default_fbufs = 3; /* Default number of frame buffers */ | 128 | static int default_fbufs = 3; /* Default number of frame buffers */ |
130 | int pwc_mbufs = 2; /* Default number of mmap() buffers */ | 129 | int pwc_mbufs = 2; /* Default number of mmap() buffers */ |
131 | #ifdef CONFIG_USB_PWC_DEBUG | 130 | #ifdef CONFIG_USB_PWC_DEBUG |
132 | int pwc_trace = PWC_DEBUG_LEVEL; | 131 | int pwc_trace = PWC_DEBUG_LEVEL; |
133 | #endif | 132 | #endif |
134 | static int power_save = 0; | 133 | static int power_save = 0; |
135 | static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */ | 134 | static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */ |
@@ -908,31 +907,49 @@ int pwc_isoc_init(struct pwc_device *pdev) | |||
908 | return 0; | 907 | return 0; |
909 | } | 908 | } |
910 | 909 | ||
911 | void pwc_isoc_cleanup(struct pwc_device *pdev) | 910 | static void pwc_iso_stop(struct pwc_device *pdev) |
912 | { | 911 | { |
913 | int i; | 912 | int i; |
914 | 913 | ||
915 | PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n"); | ||
916 | if (pdev == NULL) | ||
917 | return; | ||
918 | if (pdev->iso_init == 0) | ||
919 | return; | ||
920 | |||
921 | /* Unlinking ISOC buffers one by one */ | 914 | /* Unlinking ISOC buffers one by one */ |
922 | for (i = 0; i < MAX_ISO_BUFS; i++) { | 915 | for (i = 0; i < MAX_ISO_BUFS; i++) { |
923 | struct urb *urb; | 916 | struct urb *urb; |
924 | 917 | ||
925 | urb = pdev->sbuf[i].urb; | 918 | urb = pdev->sbuf[i].urb; |
926 | if (urb != 0) { | 919 | if (urb != 0) { |
927 | if (pdev->iso_init) { | 920 | PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb); |
928 | PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb); | 921 | usb_kill_urb(urb); |
929 | usb_kill_urb(urb); | 922 | } |
930 | } | 923 | } |
924 | } | ||
925 | |||
926 | static void pwc_iso_free(struct pwc_device *pdev) | ||
927 | { | ||
928 | int i; | ||
929 | |||
930 | /* Freeing ISOC buffers one by one */ | ||
931 | for (i = 0; i < MAX_ISO_BUFS; i++) { | ||
932 | struct urb *urb; | ||
933 | |||
934 | urb = pdev->sbuf[i].urb; | ||
935 | if (urb != 0) { | ||
931 | PWC_DEBUG_MEMORY("Freeing URB\n"); | 936 | PWC_DEBUG_MEMORY("Freeing URB\n"); |
932 | usb_free_urb(urb); | 937 | usb_free_urb(urb); |
933 | pdev->sbuf[i].urb = NULL; | 938 | pdev->sbuf[i].urb = NULL; |
934 | } | 939 | } |
935 | } | 940 | } |
941 | } | ||
942 | |||
943 | void pwc_isoc_cleanup(struct pwc_device *pdev) | ||
944 | { | ||
945 | PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n"); | ||
946 | if (pdev == NULL) | ||
947 | return; | ||
948 | if (pdev->iso_init == 0) | ||
949 | return; | ||
950 | |||
951 | pwc_iso_stop(pdev); | ||
952 | pwc_iso_free(pdev); | ||
936 | 953 | ||
937 | /* Stop camera, but only if we are sure the camera is still there (unplug | 954 | /* Stop camera, but only if we are sure the camera is still there (unplug |
938 | is signalled by EPIPE) | 955 | is signalled by EPIPE) |
@@ -979,20 +996,22 @@ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_f | |||
979 | /********* | 996 | /********* |
980 | * sysfs | 997 | * sysfs |
981 | *********/ | 998 | *********/ |
982 | static struct pwc_device *cd_to_pwc(struct class_device *cd) | 999 | static struct pwc_device *cd_to_pwc(struct device *cd) |
983 | { | 1000 | { |
984 | struct video_device *vdev = to_video_device(cd); | 1001 | struct video_device *vdev = to_video_device(cd); |
985 | return video_get_drvdata(vdev); | 1002 | return video_get_drvdata(vdev); |
986 | } | 1003 | } |
987 | 1004 | ||
988 | static ssize_t show_pan_tilt(struct class_device *class_dev, char *buf) | 1005 | static ssize_t show_pan_tilt(struct device *class_dev, |
1006 | struct device_attribute *attr, char *buf) | ||
989 | { | 1007 | { |
990 | struct pwc_device *pdev = cd_to_pwc(class_dev); | 1008 | struct pwc_device *pdev = cd_to_pwc(class_dev); |
991 | return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle); | 1009 | return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle); |
992 | } | 1010 | } |
993 | 1011 | ||
994 | static ssize_t store_pan_tilt(struct class_device *class_dev, const char *buf, | 1012 | static ssize_t store_pan_tilt(struct device *class_dev, |
995 | size_t count) | 1013 | struct device_attribute *attr, |
1014 | const char *buf, size_t count) | ||
996 | { | 1015 | { |
997 | struct pwc_device *pdev = cd_to_pwc(class_dev); | 1016 | struct pwc_device *pdev = cd_to_pwc(class_dev); |
998 | int pan, tilt; | 1017 | int pan, tilt; |
@@ -1008,10 +1027,11 @@ static ssize_t store_pan_tilt(struct class_device *class_dev, const char *buf, | |||
1008 | return ret; | 1027 | return ret; |
1009 | return strlen(buf); | 1028 | return strlen(buf); |
1010 | } | 1029 | } |
1011 | static CLASS_DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt, | 1030 | static DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt, |
1012 | store_pan_tilt); | 1031 | store_pan_tilt); |
1013 | 1032 | ||
1014 | static ssize_t show_snapshot_button_status(struct class_device *class_dev, char *buf) | 1033 | static ssize_t show_snapshot_button_status(struct device *class_dev, |
1034 | struct device_attribute *attr, char *buf) | ||
1015 | { | 1035 | { |
1016 | struct pwc_device *pdev = cd_to_pwc(class_dev); | 1036 | struct pwc_device *pdev = cd_to_pwc(class_dev); |
1017 | int status = pdev->snapshot_button_status; | 1037 | int status = pdev->snapshot_button_status; |
@@ -1019,26 +1039,26 @@ static ssize_t show_snapshot_button_status(struct class_device *class_dev, char | |||
1019 | return sprintf(buf, "%d\n", status); | 1039 | return sprintf(buf, "%d\n", status); |
1020 | } | 1040 | } |
1021 | 1041 | ||
1022 | static CLASS_DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status, | 1042 | static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status, |
1023 | NULL); | 1043 | NULL); |
1024 | 1044 | ||
1025 | static int pwc_create_sysfs_files(struct video_device *vdev) | 1045 | static int pwc_create_sysfs_files(struct video_device *vdev) |
1026 | { | 1046 | { |
1027 | struct pwc_device *pdev = video_get_drvdata(vdev); | 1047 | struct pwc_device *pdev = video_get_drvdata(vdev); |
1028 | int rc; | 1048 | int rc; |
1029 | 1049 | ||
1030 | rc = video_device_create_file(vdev, &class_device_attr_button); | 1050 | rc = video_device_create_file(vdev, &dev_attr_button); |
1031 | if (rc) | 1051 | if (rc) |
1032 | goto err; | 1052 | goto err; |
1033 | if (pdev->features & FEATURE_MOTOR_PANTILT) { | 1053 | if (pdev->features & FEATURE_MOTOR_PANTILT) { |
1034 | rc = video_device_create_file(vdev,&class_device_attr_pan_tilt); | 1054 | rc = video_device_create_file(vdev, &dev_attr_pan_tilt); |
1035 | if (rc) goto err_button; | 1055 | if (rc) goto err_button; |
1036 | } | 1056 | } |
1037 | 1057 | ||
1038 | return 0; | 1058 | return 0; |
1039 | 1059 | ||
1040 | err_button: | 1060 | err_button: |
1041 | video_device_remove_file(vdev, &class_device_attr_button); | 1061 | video_device_remove_file(vdev, &dev_attr_button); |
1042 | err: | 1062 | err: |
1043 | return rc; | 1063 | return rc; |
1044 | } | 1064 | } |
@@ -1047,8 +1067,8 @@ static void pwc_remove_sysfs_files(struct video_device *vdev) | |||
1047 | { | 1067 | { |
1048 | struct pwc_device *pdev = video_get_drvdata(vdev); | 1068 | struct pwc_device *pdev = video_get_drvdata(vdev); |
1049 | if (pdev->features & FEATURE_MOTOR_PANTILT) | 1069 | if (pdev->features & FEATURE_MOTOR_PANTILT) |
1050 | video_device_remove_file(vdev, &class_device_attr_pan_tilt); | 1070 | video_device_remove_file(vdev, &dev_attr_pan_tilt); |
1051 | video_device_remove_file(vdev, &class_device_attr_button); | 1071 | video_device_remove_file(vdev, &dev_attr_button); |
1052 | } | 1072 | } |
1053 | 1073 | ||
1054 | #ifdef CONFIG_USB_PWC_DEBUG | 1074 | #ifdef CONFIG_USB_PWC_DEBUG |
@@ -1212,6 +1232,7 @@ static int pwc_video_close(struct inode *inode, struct file *file) | |||
1212 | 1232 | ||
1213 | PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); | 1233 | PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); |
1214 | 1234 | ||
1235 | lock_kernel(); | ||
1215 | pdev = (struct pwc_device *)vdev->priv; | 1236 | pdev = (struct pwc_device *)vdev->priv; |
1216 | if (pdev->vopen == 0) | 1237 | if (pdev->vopen == 0) |
1217 | PWC_DEBUG_MODULE("video_close() called on closed device?\n"); | 1238 | PWC_DEBUG_MODULE("video_close() called on closed device?\n"); |
@@ -1231,7 +1252,6 @@ static int pwc_video_close(struct inode *inode, struct file *file) | |||
1231 | pwc_isoc_cleanup(pdev); | 1252 | pwc_isoc_cleanup(pdev); |
1232 | pwc_free_buffers(pdev); | 1253 | pwc_free_buffers(pdev); |
1233 | 1254 | ||
1234 | lock_kernel(); | ||
1235 | /* Turn off LEDS and power down camera, but only when not unplugged */ | 1255 | /* Turn off LEDS and power down camera, but only when not unplugged */ |
1236 | if (!pdev->unplugged) { | 1256 | if (!pdev->unplugged) { |
1237 | /* Turn LEDs off */ | 1257 | /* Turn LEDs off */ |
@@ -1277,7 +1297,7 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf, | |||
1277 | struct pwc_device *pdev; | 1297 | struct pwc_device *pdev; |
1278 | int noblock = file->f_flags & O_NONBLOCK; | 1298 | int noblock = file->f_flags & O_NONBLOCK; |
1279 | DECLARE_WAITQUEUE(wait, current); | 1299 | DECLARE_WAITQUEUE(wait, current); |
1280 | int bytes_to_read; | 1300 | int bytes_to_read, rv = 0; |
1281 | void *image_buffer_addr; | 1301 | void *image_buffer_addr; |
1282 | 1302 | ||
1283 | PWC_DEBUG_READ("pwc_video_read(vdev=0x%p, buf=%p, count=%zd) called.\n", | 1303 | PWC_DEBUG_READ("pwc_video_read(vdev=0x%p, buf=%p, count=%zd) called.\n", |
@@ -1287,8 +1307,12 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf, | |||
1287 | pdev = vdev->priv; | 1307 | pdev = vdev->priv; |
1288 | if (pdev == NULL) | 1308 | if (pdev == NULL) |
1289 | return -EFAULT; | 1309 | return -EFAULT; |
1290 | if (pdev->error_status) | 1310 | |
1291 | return -pdev->error_status; /* Something happened, report what. */ | 1311 | mutex_lock(&pdev->modlock); |
1312 | if (pdev->error_status) { | ||
1313 | rv = -pdev->error_status; /* Something happened, report what. */ | ||
1314 | goto err_out; | ||
1315 | } | ||
1292 | 1316 | ||
1293 | /* In case we're doing partial reads, we don't have to wait for a frame */ | 1317 | /* In case we're doing partial reads, we don't have to wait for a frame */ |
1294 | if (pdev->image_read_pos == 0) { | 1318 | if (pdev->image_read_pos == 0) { |
@@ -1299,17 +1323,20 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf, | |||
1299 | if (pdev->error_status) { | 1323 | if (pdev->error_status) { |
1300 | remove_wait_queue(&pdev->frameq, &wait); | 1324 | remove_wait_queue(&pdev->frameq, &wait); |
1301 | set_current_state(TASK_RUNNING); | 1325 | set_current_state(TASK_RUNNING); |
1302 | return -pdev->error_status ; | 1326 | rv = -pdev->error_status ; |
1327 | goto err_out; | ||
1303 | } | 1328 | } |
1304 | if (noblock) { | 1329 | if (noblock) { |
1305 | remove_wait_queue(&pdev->frameq, &wait); | 1330 | remove_wait_queue(&pdev->frameq, &wait); |
1306 | set_current_state(TASK_RUNNING); | 1331 | set_current_state(TASK_RUNNING); |
1307 | return -EWOULDBLOCK; | 1332 | rv = -EWOULDBLOCK; |
1333 | goto err_out; | ||
1308 | } | 1334 | } |
1309 | if (signal_pending(current)) { | 1335 | if (signal_pending(current)) { |
1310 | remove_wait_queue(&pdev->frameq, &wait); | 1336 | remove_wait_queue(&pdev->frameq, &wait); |
1311 | set_current_state(TASK_RUNNING); | 1337 | set_current_state(TASK_RUNNING); |
1312 | return -ERESTARTSYS; | 1338 | rv = -ERESTARTSYS; |
1339 | goto err_out; | ||
1313 | } | 1340 | } |
1314 | schedule(); | 1341 | schedule(); |
1315 | set_current_state(TASK_INTERRUPTIBLE); | 1342 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -1318,8 +1345,10 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf, | |||
1318 | set_current_state(TASK_RUNNING); | 1345 | set_current_state(TASK_RUNNING); |
1319 | 1346 | ||
1320 | /* Decompress and release frame */ | 1347 | /* Decompress and release frame */ |
1321 | if (pwc_handle_frame(pdev)) | 1348 | if (pwc_handle_frame(pdev)) { |
1322 | return -EFAULT; | 1349 | rv = -EFAULT; |
1350 | goto err_out; | ||
1351 | } | ||
1323 | } | 1352 | } |
1324 | 1353 | ||
1325 | PWC_DEBUG_READ("Copying data to user space.\n"); | 1354 | PWC_DEBUG_READ("Copying data to user space.\n"); |
@@ -1334,14 +1363,20 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf, | |||
1334 | image_buffer_addr = pdev->image_data; | 1363 | image_buffer_addr = pdev->image_data; |
1335 | image_buffer_addr += pdev->images[pdev->fill_image].offset; | 1364 | image_buffer_addr += pdev->images[pdev->fill_image].offset; |
1336 | image_buffer_addr += pdev->image_read_pos; | 1365 | image_buffer_addr += pdev->image_read_pos; |
1337 | if (copy_to_user(buf, image_buffer_addr, count)) | 1366 | if (copy_to_user(buf, image_buffer_addr, count)) { |
1338 | return -EFAULT; | 1367 | rv = -EFAULT; |
1368 | goto err_out; | ||
1369 | } | ||
1339 | pdev->image_read_pos += count; | 1370 | pdev->image_read_pos += count; |
1340 | if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */ | 1371 | if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */ |
1341 | pdev->image_read_pos = 0; | 1372 | pdev->image_read_pos = 0; |
1342 | pwc_next_image(pdev); | 1373 | pwc_next_image(pdev); |
1343 | } | 1374 | } |
1375 | mutex_unlock(&pdev->modlock); | ||
1344 | return count; | 1376 | return count; |
1377 | err_out: | ||
1378 | mutex_unlock(&pdev->modlock); | ||
1379 | return rv; | ||
1345 | } | 1380 | } |
1346 | 1381 | ||
1347 | static unsigned int pwc_video_poll(struct file *file, poll_table *wait) | 1382 | static unsigned int pwc_video_poll(struct file *file, poll_table *wait) |
@@ -1367,7 +1402,20 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait) | |||
1367 | static int pwc_video_ioctl(struct inode *inode, struct file *file, | 1402 | static int pwc_video_ioctl(struct inode *inode, struct file *file, |
1368 | unsigned int cmd, unsigned long arg) | 1403 | unsigned int cmd, unsigned long arg) |
1369 | { | 1404 | { |
1370 | return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl); | 1405 | struct video_device *vdev = file->private_data; |
1406 | struct pwc_device *pdev; | ||
1407 | int r = -ENODEV; | ||
1408 | |||
1409 | if (!vdev) | ||
1410 | goto out; | ||
1411 | pdev = vdev->priv; | ||
1412 | |||
1413 | mutex_lock(&pdev->modlock); | ||
1414 | if (!pdev->unplugged) | ||
1415 | r = video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl); | ||
1416 | mutex_unlock(&pdev->modlock); | ||
1417 | out: | ||
1418 | return r; | ||
1371 | } | 1419 | } |
1372 | 1420 | ||
1373 | static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) | 1421 | static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) |
@@ -1810,7 +1858,10 @@ static void usb_pwc_disconnect(struct usb_interface *intf) | |||
1810 | wake_up_interruptible(&pdev->frameq); | 1858 | wake_up_interruptible(&pdev->frameq); |
1811 | /* Wait until device is closed */ | 1859 | /* Wait until device is closed */ |
1812 | if(pdev->vopen) { | 1860 | if(pdev->vopen) { |
1861 | mutex_lock(&pdev->modlock); | ||
1813 | pdev->unplugged = 1; | 1862 | pdev->unplugged = 1; |
1863 | mutex_unlock(&pdev->modlock); | ||
1864 | pwc_iso_stop(pdev); | ||
1814 | } else { | 1865 | } else { |
1815 | /* Device is closed, so we can safely unregister it */ | 1866 | /* Device is closed, so we can safely unregister it */ |
1816 | PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); | 1867 | PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); |
@@ -1828,7 +1879,6 @@ disconnect_out: | |||
1828 | unlock_kernel(); | 1879 | unlock_kernel(); |
1829 | } | 1880 | } |
1830 | 1881 | ||
1831 | |||
1832 | /* *grunt* We have to do atoi ourselves :-( */ | 1882 | /* *grunt* We have to do atoi ourselves :-( */ |
1833 | static int pwc_atoi(const char *s) | 1883 | static int pwc_atoi(const char *s) |
1834 | { | 1884 | { |
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 92eabf88a09b..72e344a12c79 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c | |||
@@ -406,6 +406,7 @@ static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind) | |||
406 | kfree(s); | 406 | kfree(s); |
407 | return -ENOMEM; | 407 | return -ENOMEM; |
408 | } | 408 | } |
409 | spin_lock_init(&s->lock); | ||
409 | s->client = client_template; | 410 | s->client = client_template; |
410 | s->block_count = 0; | 411 | s->block_count = 0; |
411 | s->wr_index = 0; | 412 | s->wr_index = 0; |
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 9f986930490f..e35ef321ec71 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c | |||
@@ -332,11 +332,11 @@ static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_dat | |||
332 | if (!enable) | 332 | if (!enable) |
333 | return 0; | 333 | return 0; |
334 | 334 | ||
335 | state->vps_data[0] = data->data[4]; | 335 | state->vps_data[0] = data->data[2]; |
336 | state->vps_data[1] = data->data[10]; | 336 | state->vps_data[1] = data->data[8]; |
337 | state->vps_data[2] = data->data[11]; | 337 | state->vps_data[2] = data->data[9]; |
338 | state->vps_data[3] = data->data[12]; | 338 | state->vps_data[3] = data->data[10]; |
339 | state->vps_data[4] = data->data[13]; | 339 | state->vps_data[4] = data->data[11]; |
340 | v4l_dbg(1, debug, client, "Set VPS data %02x %02x %02x %02x %02x\n", | 340 | v4l_dbg(1, debug, client, "Set VPS data %02x %02x %02x %02x %02x\n", |
341 | state->vps_data[0], state->vps_data[1], | 341 | state->vps_data[0], state->vps_data[1], |
342 | state->vps_data[2], state->vps_data[3], | 342 | state->vps_data[2], state->vps_data[3], |
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 9f1417a4f7d2..d6d8d660196d 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | config VIDEO_SAA7134 | 1 | config VIDEO_SAA7134 |
2 | tristate "Philips SAA7134 support" | 2 | tristate "Philips SAA7134 support" |
3 | depends on VIDEO_DEV && PCI && I2C | 3 | depends on VIDEO_DEV && PCI && I2C |
4 | select VIDEO_BUF | 4 | select VIDEOBUF_DMA_SG |
5 | select VIDEO_IR | 5 | select VIDEO_IR |
6 | select VIDEO_TUNER | 6 | select VIDEO_TUNER |
7 | select CRC32 | 7 | select CRC32 |
@@ -38,7 +38,7 @@ config VIDEO_SAA7134_OSS | |||
38 | config VIDEO_SAA7134_DVB | 38 | config VIDEO_SAA7134_DVB |
39 | tristate "DVB/ATSC Support for saa7134 based TV cards" | 39 | tristate "DVB/ATSC Support for saa7134 based TV cards" |
40 | depends on VIDEO_SAA7134 && DVB_CORE | 40 | depends on VIDEO_SAA7134 && DVB_CORE |
41 | select VIDEO_BUF_DVB | 41 | select VIDEOBUF_DVB |
42 | select FW_LOADER | 42 | select FW_LOADER |
43 | select DVB_PLL if !DVB_FE_CUSTOMISE | 43 | select DVB_PLL if !DVB_FE_CUSTOMISE |
44 | select DVB_MT352 if !DVB_FE_CUSTOMISE | 44 | select DVB_MT352 if !DVB_FE_CUSTOMISE |
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 3c0fc9027ad0..c6f7279669c1 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/time.h> | 21 | #include <linux/time.h> |
22 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
23 | #include <linux/moduleparam.h> | ||
24 | #include <linux/module.h> | 23 | #include <linux/module.h> |
25 | #include <sound/driver.h> | 24 | #include <sound/driver.h> |
26 | #include <sound/core.h> | 25 | #include <sound/core.h> |
@@ -313,7 +312,7 @@ static int dsp_buffer_free(struct saa7134_dev *dev) | |||
313 | dev->dmasound.blksize = 0; | 312 | dev->dmasound.blksize = 0; |
314 | dev->dmasound.bufsize = 0; | 313 | dev->dmasound.bufsize = 0; |
315 | 314 | ||
316 | return 0; | 315 | return 0; |
317 | } | 316 | } |
318 | 317 | ||
319 | 318 | ||
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 25ec16810818..a4c192fb4e41 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -32,6 +32,7 @@ static char name_mute[] = "mute"; | |||
32 | static char name_radio[] = "Radio"; | 32 | static char name_radio[] = "Radio"; |
33 | static char name_tv[] = "Television"; | 33 | static char name_tv[] = "Television"; |
34 | static char name_tv_mono[] = "TV (mono only)"; | 34 | static char name_tv_mono[] = "TV (mono only)"; |
35 | static char name_comp[] = "Composite"; | ||
35 | static char name_comp1[] = "Composite1"; | 36 | static char name_comp1[] = "Composite1"; |
36 | static char name_comp2[] = "Composite2"; | 37 | static char name_comp2[] = "Composite2"; |
37 | static char name_comp3[] = "Composite3"; | 38 | static char name_comp3[] = "Composite3"; |
@@ -1535,12 +1536,7 @@ struct saa7134_board saa7134_boards[] = { | |||
1535 | .tv = 1, | 1536 | .tv = 1, |
1536 | .gpio = 0x00, | 1537 | .gpio = 0x00, |
1537 | },{ | 1538 | },{ |
1538 | .name = name_comp1, | 1539 | .name = name_comp, |
1539 | .vmux = 0, | ||
1540 | .amux = LINE1, | ||
1541 | .gpio = 0x02, | ||
1542 | },{ | ||
1543 | .name = name_comp2, | ||
1544 | .vmux = 3, | 1540 | .vmux = 3, |
1545 | .amux = LINE1, | 1541 | .amux = LINE1, |
1546 | .gpio = 0x02, | 1542 | .gpio = 0x02, |
@@ -2771,6 +2767,7 @@ struct saa7134_board saa7134_boards[] = { | |||
2771 | .tuner_addr = ADDR_UNSET, | 2767 | .tuner_addr = ADDR_UNSET, |
2772 | .radio_addr = ADDR_UNSET, | 2768 | .radio_addr = ADDR_UNSET, |
2773 | .mpeg = SAA7134_MPEG_DVB, | 2769 | .mpeg = SAA7134_MPEG_DVB, |
2770 | .gpiomask = 1 << 21, | ||
2774 | .inputs = {{ | 2771 | .inputs = {{ |
2775 | .name = name_tv, | 2772 | .name = name_tv, |
2776 | .vmux = 1, | 2773 | .vmux = 1, |
@@ -2781,13 +2778,18 @@ struct saa7134_board saa7134_boards[] = { | |||
2781 | .vmux = 3, | 2778 | .vmux = 3, |
2782 | .amux = LINE1, | 2779 | .amux = LINE1, |
2783 | },{ | 2780 | },{ |
2784 | .name = name_svideo, | 2781 | .name = name_comp2, |
2785 | .vmux = 0, | 2782 | .vmux = 0, |
2786 | .amux = LINE1, | 2783 | .amux = LINE1, |
2784 | },{ | ||
2785 | .name = name_svideo, | ||
2786 | .vmux = 8, | ||
2787 | .amux = LINE1, | ||
2787 | }}, | 2788 | }}, |
2788 | .radio = { | 2789 | .radio = { |
2789 | .name = name_radio, | 2790 | .name = name_radio, |
2790 | .amux = LINE1, | 2791 | .amux = TV, |
2792 | .gpio = 0x0200000, | ||
2791 | }, | 2793 | }, |
2792 | }, | 2794 | }, |
2793 | [SAA7134_BOARD_KWORLD_DVBT_210] = { | 2795 | [SAA7134_BOARD_KWORLD_DVBT_210] = { |
@@ -2820,7 +2822,7 @@ struct saa7134_board saa7134_boards[] = { | |||
2820 | }, | 2822 | }, |
2821 | }, | 2823 | }, |
2822 | [SAA7134_BOARD_KWORLD_ATSC110] = { | 2824 | [SAA7134_BOARD_KWORLD_ATSC110] = { |
2823 | .name = "Kworld ATSC110", | 2825 | .name = "Kworld ATSC110/115", |
2824 | .audio_clock = 0x00187de7, | 2826 | .audio_clock = 0x00187de7, |
2825 | .tuner_type = TUNER_PHILIPS_TUV1236D, | 2827 | .tuner_type = TUNER_PHILIPS_TUV1236D, |
2826 | .radio_type = UNSET, | 2828 | .radio_type = UNSET, |
@@ -2896,7 +2898,7 @@ struct saa7134_board saa7134_boards[] = { | |||
2896 | .radio_addr = ADDR_UNSET, | 2898 | .radio_addr = ADDR_UNSET, |
2897 | }, | 2899 | }, |
2898 | [SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS] = { | 2900 | [SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS] = { |
2899 | .name = "LifeView FlyDVB-T Hybrid Cardbus", | 2901 | .name = "LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB", |
2900 | .audio_clock = 0x00200000, | 2902 | .audio_clock = 0x00200000, |
2901 | .tuner_type = TUNER_PHILIPS_TDA8290, | 2903 | .tuner_type = TUNER_PHILIPS_TDA8290, |
2902 | .radio_type = UNSET, | 2904 | .radio_type = UNSET, |
@@ -3534,6 +3536,22 @@ struct saa7134_board saa7134_boards[] = { | |||
3534 | .gpio = 0x3000, | 3536 | .gpio = 0x3000, |
3535 | }, | 3537 | }, |
3536 | }, | 3538 | }, |
3539 | [SAA7134_BOARD_AVERMEDIA_SUPER_007] = { | ||
3540 | .name = "Avermedia Super 007", | ||
3541 | .audio_clock = 0x00187de7, | ||
3542 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
3543 | .radio_type = UNSET, | ||
3544 | .tuner_addr = ADDR_UNSET, | ||
3545 | .radio_addr = ADDR_UNSET, | ||
3546 | .tuner_config = 0, | ||
3547 | .mpeg = SAA7134_MPEG_DVB, | ||
3548 | .inputs = {{ | ||
3549 | .name = name_tv, /* FIXME: analog tv untested */ | ||
3550 | .vmux = 1, | ||
3551 | .amux = TV, | ||
3552 | .tv = 1, | ||
3553 | }}, | ||
3554 | }, | ||
3537 | }; | 3555 | }; |
3538 | 3556 | ||
3539 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); | 3557 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); |
@@ -4066,6 +4084,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
4066 | .driver_data = SAA7134_BOARD_KWORLD_ATSC110, | 4084 | .driver_data = SAA7134_BOARD_KWORLD_ATSC110, |
4067 | },{ | 4085 | },{ |
4068 | .vendor = PCI_VENDOR_ID_PHILIPS, | 4086 | .vendor = PCI_VENDOR_ID_PHILIPS, |
4087 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ | ||
4088 | .subvendor = 0x17de, | ||
4089 | .subdevice = 0x7352, | ||
4090 | .driver_data = SAA7134_BOARD_KWORLD_ATSC110, /* ATSC 115 */ | ||
4091 | },{ | ||
4092 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
4069 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 4093 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
4070 | .subvendor = 0x1461, | 4094 | .subvendor = 0x1461, |
4071 | .subdevice = 0x7360, | 4095 | .subdevice = 0x7360, |
@@ -4257,6 +4281,18 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
4257 | .subdevice = 0x2304, | 4281 | .subdevice = 0x2304, |
4258 | .driver_data = SAA7134_BOARD_10MOONSTVMASTER3, | 4282 | .driver_data = SAA7134_BOARD_10MOONSTVMASTER3, |
4259 | },{ | 4283 | },{ |
4284 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
4285 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
4286 | .subvendor = 0x1461, /* Avermedia Technologies Inc */ | ||
4287 | .subdevice = 0xf01d, /* AVerTV DVB-T Super 007 */ | ||
4288 | .driver_data = SAA7134_BOARD_AVERMEDIA_SUPER_007, | ||
4289 | },{ | ||
4290 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
4291 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
4292 | .subvendor = 0x4e42, | ||
4293 | .subdevice = 0x3502, | ||
4294 | .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS | ||
4295 | },{ | ||
4260 | /* --- boards without eeprom + subsystem ID --- */ | 4296 | /* --- boards without eeprom + subsystem ID --- */ |
4261 | .vendor = PCI_VENDOR_ID_PHILIPS, | 4297 | .vendor = PCI_VENDOR_ID_PHILIPS, |
4262 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 4298 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
@@ -4564,6 +4600,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
4564 | break; | 4600 | break; |
4565 | case SAA7134_BOARD_PHILIPS_TIGER: | 4601 | case SAA7134_BOARD_PHILIPS_TIGER: |
4566 | case SAA7134_BOARD_PHILIPS_TIGER_S: | 4602 | case SAA7134_BOARD_PHILIPS_TIGER_S: |
4603 | case SAA7134_BOARD_AVERMEDIA_SUPER_007: | ||
4567 | { | 4604 | { |
4568 | u8 data[] = { 0x3c, 0x33, 0x60}; | 4605 | u8 data[] = { 0x3c, 0x33, 0x60}; |
4569 | struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; | 4606 | struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 25f84701a8e8..1a4a24471f20 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
28 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
29 | #include <linux/kmod.h> | 28 | #include <linux/kmod.h> |
@@ -32,6 +31,7 @@ | |||
32 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
33 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
34 | #include <linux/dma-mapping.h> | 33 | #include <linux/dma-mapping.h> |
34 | #include <linux/pm.h> | ||
35 | 35 | ||
36 | #include "saa7134-reg.h" | 36 | #include "saa7134-reg.h" |
37 | #include "saa7134.h" | 37 | #include "saa7134.h" |
@@ -237,9 +237,10 @@ int saa7134_buffer_startpage(struct saa7134_buf *buf) | |||
237 | unsigned long saa7134_buffer_base(struct saa7134_buf *buf) | 237 | unsigned long saa7134_buffer_base(struct saa7134_buf *buf) |
238 | { | 238 | { |
239 | unsigned long base; | 239 | unsigned long base; |
240 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
240 | 241 | ||
241 | base = saa7134_buffer_startpage(buf) * 4096; | 242 | base = saa7134_buffer_startpage(buf) * 4096; |
242 | base += buf->vb.dma.sglist[0].offset; | 243 | base += dma->sglist[0].offset; |
243 | return base; | 244 | return base; |
244 | } | 245 | } |
245 | 246 | ||
@@ -287,11 +288,12 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt) | |||
287 | 288 | ||
288 | void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf) | 289 | void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf) |
289 | { | 290 | { |
291 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
290 | BUG_ON(in_interrupt()); | 292 | BUG_ON(in_interrupt()); |
291 | 293 | ||
292 | videobuf_waiton(&buf->vb,0,0); | 294 | videobuf_waiton(&buf->vb,0,0); |
293 | videobuf_dma_unmap(q, &buf->vb.dma); | 295 | videobuf_dma_unmap(q, dma); |
294 | videobuf_dma_free(&buf->vb.dma); | 296 | videobuf_dma_free(dma); |
295 | buf->vb.state = STATE_NEEDS_INIT; | 297 | buf->vb.state = STATE_NEEDS_INIT; |
296 | } | 298 | } |
297 | 299 | ||
@@ -391,6 +393,32 @@ void saa7134_buffer_timeout(unsigned long data) | |||
391 | spin_unlock_irqrestore(&dev->slock,flags); | 393 | spin_unlock_irqrestore(&dev->slock,flags); |
392 | } | 394 | } |
393 | 395 | ||
396 | /* resends a current buffer in queue after resume */ | ||
397 | |||
398 | int saa7134_buffer_requeue(struct saa7134_dev *dev, | ||
399 | struct saa7134_dmaqueue *q) | ||
400 | { | ||
401 | struct saa7134_buf *buf, *next; | ||
402 | |||
403 | assert_spin_locked(&dev->slock); | ||
404 | |||
405 | buf = q->curr; | ||
406 | next = buf; | ||
407 | dprintk("buffer_requeue\n"); | ||
408 | |||
409 | if (!buf) | ||
410 | return 0; | ||
411 | |||
412 | dprintk("buffer_requeue : resending active buffers \n"); | ||
413 | |||
414 | if (!list_empty(&q->queue)) | ||
415 | next = list_entry(q->queue.next, struct saa7134_buf, | ||
416 | vb.queue); | ||
417 | buf->activate(dev, buf, next); | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
394 | /* ------------------------------------------------------------------ */ | 422 | /* ------------------------------------------------------------------ */ |
395 | 423 | ||
396 | int saa7134_set_dmabits(struct saa7134_dev *dev) | 424 | int saa7134_set_dmabits(struct saa7134_dev *dev) |
@@ -401,6 +429,9 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) | |||
401 | 429 | ||
402 | assert_spin_locked(&dev->slock); | 430 | assert_spin_locked(&dev->slock); |
403 | 431 | ||
432 | if (dev->inresume) | ||
433 | return 0; | ||
434 | |||
404 | /* video capture -- dma 0 + video task A */ | 435 | /* video capture -- dma 0 + video task A */ |
405 | if (dev->video_q.curr) { | 436 | if (dev->video_q.curr) { |
406 | task |= 0x01; | 437 | task |= 0x01; |
@@ -560,8 +591,10 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id) | |||
560 | print_irqstatus(dev,loop,report,status); | 591 | print_irqstatus(dev,loop,report,status); |
561 | 592 | ||
562 | 593 | ||
563 | if (report & SAA7134_IRQ_REPORT_RDCAP /* _INTL */) | 594 | if ((report & SAA7134_IRQ_REPORT_RDCAP) || |
564 | saa7134_irq_video_intl(dev); | 595 | (report & SAA7134_IRQ_REPORT_INTL)) |
596 | saa7134_irq_video_signalchange(dev); | ||
597 | |||
565 | 598 | ||
566 | if ((report & SAA7134_IRQ_REPORT_DONE_RA0) && | 599 | if ((report & SAA7134_IRQ_REPORT_DONE_RA0) && |
567 | (status & 0x60) == 0) | 600 | (status & 0x60) == 0) |
@@ -646,6 +679,39 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id) | |||
646 | /* ------------------------------------------------------------------ */ | 679 | /* ------------------------------------------------------------------ */ |
647 | 680 | ||
648 | /* early init (no i2c, no irq) */ | 681 | /* early init (no i2c, no irq) */ |
682 | |||
683 | static int saa7134_hw_enable1(struct saa7134_dev *dev) | ||
684 | { | ||
685 | /* RAM FIFO config */ | ||
686 | saa_writel(SAA7134_FIFO_SIZE, 0x08070503); | ||
687 | saa_writel(SAA7134_THRESHOULD, 0x02020202); | ||
688 | |||
689 | /* enable audio + video processing */ | ||
690 | saa_writel(SAA7134_MAIN_CTRL, | ||
691 | SAA7134_MAIN_CTRL_VPLLE | | ||
692 | SAA7134_MAIN_CTRL_APLLE | | ||
693 | SAA7134_MAIN_CTRL_EXOSC | | ||
694 | SAA7134_MAIN_CTRL_EVFE1 | | ||
695 | SAA7134_MAIN_CTRL_EVFE2 | | ||
696 | SAA7134_MAIN_CTRL_ESFE | | ||
697 | SAA7134_MAIN_CTRL_EBDAC); | ||
698 | |||
699 | /* | ||
700 | * Initialize OSS _after_ enabling audio clock PLL and audio processing. | ||
701 | * OSS initialization writes to registers via the audio DSP; these | ||
702 | * writes will fail unless the audio clock has been started. At worst, | ||
703 | * audio will not work. | ||
704 | */ | ||
705 | |||
706 | /* enable peripheral devices */ | ||
707 | saa_writeb(SAA7134_SPECIAL_MODE, 0x01); | ||
708 | |||
709 | /* set vertical line numbering start (vbi needs this) */ | ||
710 | saa_writeb(SAA7134_SOURCE_TIMING2, 0x20); | ||
711 | |||
712 | return 0; | ||
713 | } | ||
714 | |||
649 | static int saa7134_hwinit1(struct saa7134_dev *dev) | 715 | static int saa7134_hwinit1(struct saa7134_dev *dev) |
650 | { | 716 | { |
651 | dprintk("hwinit1\n"); | 717 | dprintk("hwinit1\n"); |
@@ -662,44 +728,16 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) | |||
662 | saa7134_ts_init1(dev); | 728 | saa7134_ts_init1(dev); |
663 | saa7134_input_init1(dev); | 729 | saa7134_input_init1(dev); |
664 | 730 | ||
665 | /* RAM FIFO config */ | 731 | saa7134_hw_enable1(dev); |
666 | saa_writel(SAA7134_FIFO_SIZE, 0x08070503); | ||
667 | saa_writel(SAA7134_THRESHOULD,0x02020202); | ||
668 | |||
669 | /* enable audio + video processing */ | ||
670 | saa_writel(SAA7134_MAIN_CTRL, | ||
671 | SAA7134_MAIN_CTRL_VPLLE | | ||
672 | SAA7134_MAIN_CTRL_APLLE | | ||
673 | SAA7134_MAIN_CTRL_EXOSC | | ||
674 | SAA7134_MAIN_CTRL_EVFE1 | | ||
675 | SAA7134_MAIN_CTRL_EVFE2 | | ||
676 | SAA7134_MAIN_CTRL_ESFE | | ||
677 | SAA7134_MAIN_CTRL_EBDAC); | ||
678 | |||
679 | /* | ||
680 | * Initialize OSS _after_ enabling audio clock PLL and audio processing. | ||
681 | * OSS initialization writes to registers via the audio DSP; these | ||
682 | * writes will fail unless the audio clock has been started. At worst, | ||
683 | * audio will not work. | ||
684 | */ | ||
685 | |||
686 | /* enable peripheral devices */ | ||
687 | saa_writeb(SAA7134_SPECIAL_MODE, 0x01); | ||
688 | |||
689 | /* set vertical line numbering start (vbi needs this) */ | ||
690 | saa_writeb(SAA7134_SOURCE_TIMING2, 0x20); | ||
691 | 732 | ||
692 | return 0; | 733 | return 0; |
693 | } | 734 | } |
694 | 735 | ||
695 | /* late init (with i2c + irq) */ | 736 | /* late init (with i2c + irq) */ |
696 | static int saa7134_hwinit2(struct saa7134_dev *dev) | 737 | static int saa7134_hw_enable2(struct saa7134_dev *dev) |
697 | { | 738 | { |
698 | unsigned int irq2_mask; | ||
699 | dprintk("hwinit2\n"); | ||
700 | 739 | ||
701 | saa7134_video_init2(dev); | 740 | unsigned int irq2_mask; |
702 | saa7134_tvaudio_init2(dev); | ||
703 | 741 | ||
704 | /* enable IRQ's */ | 742 | /* enable IRQ's */ |
705 | irq2_mask = | 743 | irq2_mask = |
@@ -725,6 +763,20 @@ static int saa7134_hwinit2(struct saa7134_dev *dev) | |||
725 | return 0; | 763 | return 0; |
726 | } | 764 | } |
727 | 765 | ||
766 | static int saa7134_hwinit2(struct saa7134_dev *dev) | ||
767 | { | ||
768 | |||
769 | dprintk("hwinit2\n"); | ||
770 | |||
771 | saa7134_video_init2(dev); | ||
772 | saa7134_tvaudio_init2(dev); | ||
773 | |||
774 | saa7134_hw_enable2(dev); | ||
775 | |||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | |||
728 | /* shutdown */ | 780 | /* shutdown */ |
729 | static int saa7134_hwfini(struct saa7134_dev *dev) | 781 | static int saa7134_hwfini(struct saa7134_dev *dev) |
730 | { | 782 | { |
@@ -838,7 +890,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
838 | const struct pci_device_id *pci_id) | 890 | const struct pci_device_id *pci_id) |
839 | { | 891 | { |
840 | struct saa7134_dev *dev; | 892 | struct saa7134_dev *dev; |
841 | struct list_head *item; | ||
842 | struct saa7134_mpeg_ops *mops; | 893 | struct saa7134_mpeg_ops *mops; |
843 | int err; | 894 | int err; |
844 | 895 | ||
@@ -1020,15 +1071,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
1020 | saa7134_devcount++; | 1071 | saa7134_devcount++; |
1021 | 1072 | ||
1022 | mutex_lock(&devlist_lock); | 1073 | mutex_lock(&devlist_lock); |
1023 | list_for_each(item,&mops_list) { | 1074 | list_for_each_entry(mops, &mops_list, next) |
1024 | mops = list_entry(item, struct saa7134_mpeg_ops, next); | ||
1025 | mpeg_ops_attach(mops, dev); | 1075 | mpeg_ops_attach(mops, dev); |
1026 | } | ||
1027 | list_add_tail(&dev->devlist,&saa7134_devlist); | 1076 | list_add_tail(&dev->devlist,&saa7134_devlist); |
1028 | mutex_unlock(&devlist_lock); | 1077 | mutex_unlock(&devlist_lock); |
1029 | 1078 | ||
1030 | /* check for signal */ | 1079 | /* check for signal */ |
1031 | saa7134_irq_video_intl(dev); | 1080 | saa7134_irq_video_signalchange(dev); |
1032 | 1081 | ||
1033 | if (saa7134_dmasound_init && !dev->dmasound.priv_data) { | 1082 | if (saa7134_dmasound_init && !dev->dmasound.priv_data) { |
1034 | saa7134_dmasound_init(dev); | 1083 | saa7134_dmasound_init(dev); |
@@ -1057,7 +1106,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
1057 | static void __devexit saa7134_finidev(struct pci_dev *pci_dev) | 1106 | static void __devexit saa7134_finidev(struct pci_dev *pci_dev) |
1058 | { | 1107 | { |
1059 | struct saa7134_dev *dev = pci_get_drvdata(pci_dev); | 1108 | struct saa7134_dev *dev = pci_get_drvdata(pci_dev); |
1060 | struct list_head *item; | ||
1061 | struct saa7134_mpeg_ops *mops; | 1109 | struct saa7134_mpeg_ops *mops; |
1062 | 1110 | ||
1063 | /* Release DMA sound modules if present */ | 1111 | /* Release DMA sound modules if present */ |
@@ -1086,10 +1134,8 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) | |||
1086 | /* unregister */ | 1134 | /* unregister */ |
1087 | mutex_lock(&devlist_lock); | 1135 | mutex_lock(&devlist_lock); |
1088 | list_del(&dev->devlist); | 1136 | list_del(&dev->devlist); |
1089 | list_for_each(item,&mops_list) { | 1137 | list_for_each_entry(mops, &mops_list, next) |
1090 | mops = list_entry(item, struct saa7134_mpeg_ops, next); | ||
1091 | mpeg_ops_detach(mops, dev); | 1138 | mpeg_ops_detach(mops, dev); |
1092 | } | ||
1093 | mutex_unlock(&devlist_lock); | 1139 | mutex_unlock(&devlist_lock); |
1094 | saa7134_devcount--; | 1140 | saa7134_devcount--; |
1095 | 1141 | ||
@@ -1117,18 +1163,79 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) | |||
1117 | kfree(dev); | 1163 | kfree(dev); |
1118 | } | 1164 | } |
1119 | 1165 | ||
1166 | static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state) | ||
1167 | { | ||
1168 | |||
1169 | struct saa7134_dev *dev = pci_get_drvdata(pci_dev); | ||
1170 | |||
1171 | /* disable overlay - apps should enable it explicitly on resume*/ | ||
1172 | dev->ovenable = 0; | ||
1173 | |||
1174 | /* Disable interrupts, DMA, and rest of the chip*/ | ||
1175 | saa_writel(SAA7134_IRQ1, 0); | ||
1176 | saa_writel(SAA7134_IRQ2, 0); | ||
1177 | saa_writel(SAA7134_MAIN_CTRL, 0); | ||
1178 | |||
1179 | pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); | ||
1180 | pci_save_state(pci_dev); | ||
1181 | |||
1182 | return 0; | ||
1183 | } | ||
1184 | |||
1185 | static int saa7134_resume(struct pci_dev *pci_dev) | ||
1186 | { | ||
1187 | |||
1188 | struct saa7134_dev *dev = pci_get_drvdata(pci_dev); | ||
1189 | unsigned int flags; | ||
1190 | |||
1191 | pci_restore_state(pci_dev); | ||
1192 | pci_set_power_state(pci_dev, PCI_D0); | ||
1193 | |||
1194 | /* Do things that are done in saa7134_initdev , | ||
1195 | except of initializing memory structures.*/ | ||
1196 | |||
1197 | dev->inresume = 1; | ||
1198 | saa7134_board_init1(dev); | ||
1199 | |||
1200 | if (saa7134_boards[dev->board].video_out) | ||
1201 | saa7134_videoport_init(dev); | ||
1202 | |||
1203 | if (card_has_mpeg(dev)) | ||
1204 | saa7134_ts_init_hw(dev); | ||
1205 | |||
1206 | saa7134_hw_enable1(dev); | ||
1207 | saa7134_set_decoder(dev); | ||
1208 | saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); | ||
1209 | saa7134_board_init2(dev); | ||
1210 | saa7134_hw_enable2(dev); | ||
1211 | |||
1212 | saa7134_tvaudio_setmute(dev); | ||
1213 | saa7134_tvaudio_setvolume(dev, dev->ctl_volume); | ||
1214 | saa7134_enable_i2s(dev); | ||
1215 | |||
1216 | /*resume unfinished buffer(s)*/ | ||
1217 | spin_lock_irqsave(&dev->slock, flags); | ||
1218 | saa7134_buffer_requeue(dev, &dev->video_q); | ||
1219 | saa7134_buffer_requeue(dev, &dev->vbi_q); | ||
1220 | saa7134_buffer_requeue(dev, &dev->ts_q); | ||
1221 | |||
1222 | /* start DMA now*/ | ||
1223 | dev->inresume = 0; | ||
1224 | saa7134_set_dmabits(dev); | ||
1225 | spin_unlock_irqrestore(&dev->slock, flags); | ||
1226 | |||
1227 | return 0; | ||
1228 | } | ||
1229 | |||
1120 | /* ----------------------------------------------------------- */ | 1230 | /* ----------------------------------------------------------- */ |
1121 | 1231 | ||
1122 | int saa7134_ts_register(struct saa7134_mpeg_ops *ops) | 1232 | int saa7134_ts_register(struct saa7134_mpeg_ops *ops) |
1123 | { | 1233 | { |
1124 | struct list_head *item; | ||
1125 | struct saa7134_dev *dev; | 1234 | struct saa7134_dev *dev; |
1126 | 1235 | ||
1127 | mutex_lock(&devlist_lock); | 1236 | mutex_lock(&devlist_lock); |
1128 | list_for_each(item,&saa7134_devlist) { | 1237 | list_for_each_entry(dev, &saa7134_devlist, devlist) |
1129 | dev = list_entry(item, struct saa7134_dev, devlist); | ||
1130 | mpeg_ops_attach(ops, dev); | 1238 | mpeg_ops_attach(ops, dev); |
1131 | } | ||
1132 | list_add_tail(&ops->next,&mops_list); | 1239 | list_add_tail(&ops->next,&mops_list); |
1133 | mutex_unlock(&devlist_lock); | 1240 | mutex_unlock(&devlist_lock); |
1134 | return 0; | 1241 | return 0; |
@@ -1136,15 +1243,12 @@ int saa7134_ts_register(struct saa7134_mpeg_ops *ops) | |||
1136 | 1243 | ||
1137 | void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops) | 1244 | void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops) |
1138 | { | 1245 | { |
1139 | struct list_head *item; | ||
1140 | struct saa7134_dev *dev; | 1246 | struct saa7134_dev *dev; |
1141 | 1247 | ||
1142 | mutex_lock(&devlist_lock); | 1248 | mutex_lock(&devlist_lock); |
1143 | list_del(&ops->next); | 1249 | list_del(&ops->next); |
1144 | list_for_each(item,&saa7134_devlist) { | 1250 | list_for_each_entry(dev, &saa7134_devlist, devlist) |
1145 | dev = list_entry(item, struct saa7134_dev, devlist); | ||
1146 | mpeg_ops_detach(ops, dev); | 1251 | mpeg_ops_detach(ops, dev); |
1147 | } | ||
1148 | mutex_unlock(&devlist_lock); | 1252 | mutex_unlock(&devlist_lock); |
1149 | } | 1253 | } |
1150 | 1254 | ||
@@ -1158,6 +1262,8 @@ static struct pci_driver saa7134_pci_driver = { | |||
1158 | .id_table = saa7134_pci_tbl, | 1262 | .id_table = saa7134_pci_tbl, |
1159 | .probe = saa7134_initdev, | 1263 | .probe = saa7134_initdev, |
1160 | .remove = __devexit_p(saa7134_finidev), | 1264 | .remove = __devexit_p(saa7134_finidev), |
1265 | .suspend = saa7134_suspend, | ||
1266 | .resume = saa7134_resume | ||
1161 | }; | 1267 | }; |
1162 | 1268 | ||
1163 | static int saa7134_init(void) | 1269 | static int saa7134_init(void) |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 1f6bd3300715..38d87332cc5d 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -567,6 +567,7 @@ static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config | |||
567 | } | 567 | } |
568 | 568 | ||
569 | /* ------------------------------------------------------------------ */ | 569 | /* ------------------------------------------------------------------ */ |
570 | |||
570 | static struct tda1004x_config tda827x_lifeview_config = { | 571 | static struct tda1004x_config tda827x_lifeview_config = { |
571 | .demod_address = 0x08, | 572 | .demod_address = 0x08, |
572 | .invert = 1, | 573 | .invert = 1, |
@@ -746,6 +747,7 @@ static struct tda1004x_config asus_p7131_hybrid_lna_config = { | |||
746 | .antenna_switch= 2, | 747 | .antenna_switch= 2, |
747 | .request_firmware = philips_tda1004x_request_firmware | 748 | .request_firmware = philips_tda1004x_request_firmware |
748 | }; | 749 | }; |
750 | |||
749 | static struct tda1004x_config kworld_dvb_t_210_config = { | 751 | static struct tda1004x_config kworld_dvb_t_210_config = { |
750 | .demod_address = 0x08, | 752 | .demod_address = 0x08, |
751 | .invert = 1, | 753 | .invert = 1, |
@@ -760,6 +762,22 @@ static struct tda1004x_config kworld_dvb_t_210_config = { | |||
760 | .antenna_switch= 1, | 762 | .antenna_switch= 1, |
761 | .request_firmware = philips_tda1004x_request_firmware | 763 | .request_firmware = philips_tda1004x_request_firmware |
762 | }; | 764 | }; |
765 | |||
766 | static struct tda1004x_config avermedia_super_007_config = { | ||
767 | .demod_address = 0x08, | ||
768 | .invert = 1, | ||
769 | .invert_oclk = 0, | ||
770 | .xtal_freq = TDA10046_XTAL_16M, | ||
771 | .agc_config = TDA10046_AGC_TDA827X, | ||
772 | .gpio_config = TDA10046_GP01_I, | ||
773 | .if_freq = TDA10046_FREQ_045, | ||
774 | .i2c_gate = 0x4b, | ||
775 | .tuner_address = 0x60, | ||
776 | .tuner_config = 0, | ||
777 | .antenna_switch= 1, | ||
778 | .request_firmware = philips_tda1004x_request_firmware | ||
779 | }; | ||
780 | |||
763 | /* ------------------------------------------------------------------ | 781 | /* ------------------------------------------------------------------ |
764 | * special case: this card uses saa713x GPIO22 for the mode switch | 782 | * special case: this card uses saa713x GPIO22 for the mode switch |
765 | */ | 783 | */ |
@@ -832,7 +850,7 @@ static int dvb_init(struct saa7134_dev *dev) | |||
832 | dev->ts.nr_bufs = 32; | 850 | dev->ts.nr_bufs = 32; |
833 | dev->ts.nr_packets = 32*4; | 851 | dev->ts.nr_packets = 32*4; |
834 | dev->dvb.name = dev->name; | 852 | dev->dvb.name = dev->name; |
835 | videobuf_queue_init(&dev->dvb.dvbq, &saa7134_ts_qops, | 853 | videobuf_queue_pci_init(&dev->dvb.dvbq, &saa7134_ts_qops, |
836 | dev->pci, &dev->slock, | 854 | dev->pci, &dev->slock, |
837 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 855 | V4L2_BUF_TYPE_VIDEO_CAPTURE, |
838 | V4L2_FIELD_ALTERNATE, | 856 | V4L2_FIELD_ALTERNATE, |
@@ -1022,6 +1040,9 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1022 | case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: | 1040 | case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: |
1023 | configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config); | 1041 | configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config); |
1024 | break; | 1042 | break; |
1043 | case SAA7134_BOARD_AVERMEDIA_SUPER_007: | ||
1044 | configure_tda827x_fe(dev, &avermedia_super_007_config); | ||
1045 | break; | ||
1025 | default: | 1046 | default: |
1026 | wprintk("Huh? unknown DVB card?\n"); | 1047 | wprintk("Huh? unknown DVB card?\n"); |
1027 | break; | 1048 | break; |
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index fc260ec8fdc2..34ca874dd7fe 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/moduleparam.h> | ||
24 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
@@ -77,17 +76,14 @@ static int ts_init_encoder(struct saa7134_dev* dev) | |||
77 | static int ts_open(struct inode *inode, struct file *file) | 76 | static int ts_open(struct inode *inode, struct file *file) |
78 | { | 77 | { |
79 | int minor = iminor(inode); | 78 | int minor = iminor(inode); |
80 | struct saa7134_dev *h,*dev = NULL; | 79 | struct saa7134_dev *dev; |
81 | struct list_head *list; | ||
82 | int err; | 80 | int err; |
83 | 81 | ||
84 | list_for_each(list,&saa7134_devlist) { | 82 | list_for_each_entry(dev, &saa7134_devlist, devlist) |
85 | h = list_entry(list, struct saa7134_dev, devlist); | 83 | if (dev->empress_dev && dev->empress_dev->minor == minor) |
86 | if (h->empress_dev && h->empress_dev->minor == minor) | 84 | goto found; |
87 | dev = h; | 85 | return -ENODEV; |
88 | } | 86 | found: |
89 | if (NULL == dev) | ||
90 | return -ENODEV; | ||
91 | 87 | ||
92 | dprintk("open minor=%d\n",minor); | 88 | dprintk("open minor=%d\n",minor); |
93 | err = -EBUSY; | 89 | err = -EBUSY; |
@@ -401,7 +397,7 @@ static int empress_init(struct saa7134_dev *dev) | |||
401 | printk(KERN_INFO "%s: registered device video%d [mpeg]\n", | 397 | printk(KERN_INFO "%s: registered device video%d [mpeg]\n", |
402 | dev->name,dev->empress_dev->minor & 0x1f); | 398 | dev->name,dev->empress_dev->minor & 0x1f); |
403 | 399 | ||
404 | videobuf_queue_init(&dev->empress_tsq, &saa7134_ts_qops, | 400 | videobuf_queue_pci_init(&dev->empress_tsq, &saa7134_ts_qops, |
405 | dev->pci, &dev->slock, | 401 | dev->pci, &dev->slock, |
406 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 402 | V4L2_BUF_TYPE_VIDEO_CAPTURE, |
407 | V4L2_FIELD_ALTERNATE, | 403 | V4L2_FIELD_ALTERNATE, |
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 1cb8c709ca90..cc87f5855a21 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
28 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
29 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 1b6dfd801cc1..80d2644f765a 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -19,7 +19,6 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/init.h> | 22 | #include <linux/init.h> |
24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
25 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index 72444f039e3d..aedf04653e0e 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/list.h> | 26 | #include <linux/list.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | ||
29 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
30 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
31 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
@@ -240,17 +239,14 @@ static int dsp_rec_stop(struct saa7134_dev *dev) | |||
240 | static int dsp_open(struct inode *inode, struct file *file) | 239 | static int dsp_open(struct inode *inode, struct file *file) |
241 | { | 240 | { |
242 | int minor = iminor(inode); | 241 | int minor = iminor(inode); |
243 | struct saa7134_dev *h,*dev = NULL; | 242 | struct saa7134_dev *dev; |
244 | struct list_head *list; | ||
245 | int err; | 243 | int err; |
246 | 244 | ||
247 | list_for_each(list,&saa7134_devlist) { | 245 | list_for_each_entry(dev, &saa7134_devlist, devlist) |
248 | h = list_entry(list, struct saa7134_dev, devlist); | 246 | if (dev->dmasound.minor_dsp == minor) |
249 | if (h->dmasound.minor_dsp == minor) | 247 | goto found; |
250 | dev = h; | 248 | return -ENODEV; |
251 | } | 249 | found: |
252 | if (NULL == dev) | ||
253 | return -ENODEV; | ||
254 | 250 | ||
255 | mutex_lock(&dev->dmasound.lock); | 251 | mutex_lock(&dev->dmasound.lock); |
256 | err = -EBUSY; | 252 | err = -EBUSY; |
@@ -681,19 +677,14 @@ mixer_level(struct saa7134_dev *dev, enum saa7134_audio_in src, int level) | |||
681 | static int mixer_open(struct inode *inode, struct file *file) | 677 | static int mixer_open(struct inode *inode, struct file *file) |
682 | { | 678 | { |
683 | int minor = iminor(inode); | 679 | int minor = iminor(inode); |
684 | struct saa7134_dev *h,*dev = NULL; | 680 | struct saa7134_dev *dev; |
685 | struct list_head *list; | ||
686 | 681 | ||
687 | list_for_each(list,&saa7134_devlist) { | 682 | list_for_each_entry(dev, &saa7134_devlist, devlist) |
688 | h = list_entry(list, struct saa7134_dev, devlist); | 683 | if (dev->dmasound.minor_mixer == minor) { |
689 | if (h->dmasound.minor_mixer == minor) | 684 | file->private_data = dev; |
690 | dev = h; | 685 | return 0; |
691 | } | 686 | } |
692 | if (NULL == dev) | 687 | return -ENODEV; |
693 | return -ENODEV; | ||
694 | |||
695 | file->private_data = dev; | ||
696 | return 0; | ||
697 | } | 688 | } |
698 | 689 | ||
699 | static int mixer_release(struct inode *inode, struct file *file) | 690 | static int mixer_release(struct inode *inode, struct file *file) |
@@ -1023,18 +1014,14 @@ static int saa7134_oss_init(void) | |||
1023 | 1014 | ||
1024 | static void saa7134_oss_exit(void) | 1015 | static void saa7134_oss_exit(void) |
1025 | { | 1016 | { |
1026 | struct saa7134_dev *dev = NULL; | 1017 | struct saa7134_dev *dev; |
1027 | struct list_head *list; | ||
1028 | |||
1029 | list_for_each(list,&saa7134_devlist) { | ||
1030 | dev = list_entry(list, struct saa7134_dev, devlist); | ||
1031 | 1018 | ||
1019 | list_for_each_entry(dev, &saa7134_devlist, devlist) { | ||
1032 | /* Device isn't registered by OSS, probably ALSA's */ | 1020 | /* Device isn't registered by OSS, probably ALSA's */ |
1033 | if (!dev->dmasound.minor_dsp) | 1021 | if (!dev->dmasound.minor_dsp) |
1034 | continue; | 1022 | continue; |
1035 | 1023 | ||
1036 | oss_device_exit(dev); | 1024 | oss_device_exit(dev); |
1037 | |||
1038 | } | 1025 | } |
1039 | 1026 | ||
1040 | saa7134_dmasound_init = NULL; | 1027 | saa7134_dmasound_init = NULL; |
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index 60a90a2617ae..4b63ad3e8466 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
28 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
29 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
@@ -93,6 +92,8 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
93 | } | 92 | } |
94 | 93 | ||
95 | if (STATE_NEEDS_INIT == buf->vb.state) { | 94 | if (STATE_NEEDS_INIT == buf->vb.state) { |
95 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
96 | |||
96 | buf->vb.width = llength; | 97 | buf->vb.width = llength; |
97 | buf->vb.height = lines; | 98 | buf->vb.height = lines; |
98 | buf->vb.size = size; | 99 | buf->vb.size = size; |
@@ -102,8 +103,8 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
102 | if (err) | 103 | if (err) |
103 | goto oops; | 104 | goto oops; |
104 | err = saa7134_pgtable_build(dev->pci,buf->pt, | 105 | err = saa7134_pgtable_build(dev->pci,buf->pt, |
105 | buf->vb.dma.sglist, | 106 | dma->sglist, |
106 | buf->vb.dma.sglen, | 107 | dma->sglen, |
107 | saa7134_buffer_startpage(buf)); | 108 | saa7134_buffer_startpage(buf)); |
108 | if (err) | 109 | if (err) |
109 | goto oops; | 110 | goto oops; |
@@ -176,6 +177,22 @@ static unsigned int ts_nr_packets = 64; | |||
176 | module_param(ts_nr_packets, int, 0444); | 177 | module_param(ts_nr_packets, int, 0444); |
177 | MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)"); | 178 | MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)"); |
178 | 179 | ||
180 | int saa7134_ts_init_hw(struct saa7134_dev *dev) | ||
181 | { | ||
182 | /* deactivate TS softreset */ | ||
183 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); | ||
184 | /* TSSOP high active, TSVAL high active, TSLOCK ignored */ | ||
185 | saa_writeb(SAA7134_TS_PARALLEL, 0xec); | ||
186 | saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); | ||
187 | saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff)); | ||
188 | saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff)); | ||
189 | /* TSNOPIT=0, TSCOLAP=0 */ | ||
190 | saa_writeb(SAA7134_TS_DMA2, | ||
191 | ((((dev->ts.nr_packets-1)>>16)&0x3f) | 0x00)); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
179 | int saa7134_ts_init1(struct saa7134_dev *dev) | 196 | int saa7134_ts_init1(struct saa7134_dev *dev) |
180 | { | 197 | { |
181 | /* sanitycheck insmod options */ | 198 | /* sanitycheck insmod options */ |
@@ -199,12 +216,7 @@ int saa7134_ts_init1(struct saa7134_dev *dev) | |||
199 | saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts); | 216 | saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts); |
200 | 217 | ||
201 | /* init TS hw */ | 218 | /* init TS hw */ |
202 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); /* deactivate TS softreset */ | 219 | saa7134_ts_init_hw(dev); |
203 | saa_writeb(SAA7134_TS_PARALLEL, 0xec); /* TSSOP high active, TSVAL high active, TSLOCK ignored */ | ||
204 | saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); | ||
205 | saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff)); | ||
206 | saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff)); | ||
207 | saa_writeb(SAA7134_TS_DMA2, ((((dev->ts.nr_packets-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */ | ||
208 | 220 | ||
209 | return 0; | 221 | return 0; |
210 | } | 222 | } |
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 18b4817b4aac..1b9e39a5ea47 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
28 | #include <linux/kthread.h> | 27 | #include <linux/kthread.h> |
29 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
@@ -232,7 +231,7 @@ static void mute_input_7134(struct saa7134_dev *dev) | |||
232 | } | 231 | } |
233 | 232 | ||
234 | if (dev->hw_mute == mute && | 233 | if (dev->hw_mute == mute && |
235 | dev->hw_input == in) { | 234 | dev->hw_input == in && !dev->inresume) { |
236 | dprintk("mute/input: nothing to do [mute=%d,input=%s]\n", | 235 | dprintk("mute/input: nothing to do [mute=%d,input=%s]\n", |
237 | mute,in->name); | 236 | mute,in->name); |
238 | return; | 237 | return; |
@@ -877,7 +876,7 @@ static int tvaudio_thread_ddep(void *data) | |||
877 | /* ------------------------------------------------------------------ */ | 876 | /* ------------------------------------------------------------------ */ |
878 | /* common stuff + external entry points */ | 877 | /* common stuff + external entry points */ |
879 | 878 | ||
880 | static void saa7134_enable_i2s(struct saa7134_dev *dev) | 879 | void saa7134_enable_i2s(struct saa7134_dev *dev) |
881 | { | 880 | { |
882 | int i2s_format; | 881 | int i2s_format; |
883 | 882 | ||
diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c index f38366a470fa..81a2aedeff5c 100644 --- a/drivers/media/video/saa7134/saa7134-vbi.c +++ b/drivers/media/video/saa7134/saa7134-vbi.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
28 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
29 | 28 | ||
@@ -138,6 +137,8 @@ static int buffer_prepare(struct videobuf_queue *q, | |||
138 | saa7134_dma_free(q,buf); | 137 | saa7134_dma_free(q,buf); |
139 | 138 | ||
140 | if (STATE_NEEDS_INIT == buf->vb.state) { | 139 | if (STATE_NEEDS_INIT == buf->vb.state) { |
140 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
141 | |||
141 | buf->vb.width = llength; | 142 | buf->vb.width = llength; |
142 | buf->vb.height = lines; | 143 | buf->vb.height = lines; |
143 | buf->vb.size = size; | 144 | buf->vb.size = size; |
@@ -147,8 +148,8 @@ static int buffer_prepare(struct videobuf_queue *q, | |||
147 | if (err) | 148 | if (err) |
148 | goto oops; | 149 | goto oops; |
149 | err = saa7134_pgtable_build(dev->pci,buf->pt, | 150 | err = saa7134_pgtable_build(dev->pci,buf->pt, |
150 | buf->vb.dma.sglist, | 151 | dma->sglist, |
151 | buf->vb.dma.sglen, | 152 | dma->sglen, |
152 | saa7134_buffer_startpage(buf)); | 153 | saa7134_buffer_startpage(buf)); |
153 | if (err) | 154 | if (err) |
154 | goto oops; | 155 | goto oops; |
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 9985ded20950..471b92793c12 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
28 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
29 | #include <linux/sort.h> | 28 | #include <linux/sort.h> |
@@ -41,7 +40,7 @@ | |||
41 | 40 | ||
42 | static unsigned int video_debug = 0; | 41 | static unsigned int video_debug = 0; |
43 | static unsigned int gbuffers = 8; | 42 | static unsigned int gbuffers = 8; |
44 | static unsigned int noninterlaced = 1; | 43 | static unsigned int noninterlaced = 0; |
45 | static unsigned int gbufsize = 720*576*4; | 44 | static unsigned int gbufsize = 720*576*4; |
46 | static unsigned int gbufsize_max = 720*576*4; | 45 | static unsigned int gbufsize_max = 720*576*4; |
47 | static char secam[] = "--"; | 46 | static char secam[] = "--"; |
@@ -541,22 +540,12 @@ void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits) | |||
541 | 540 | ||
542 | /* ------------------------------------------------------------------ */ | 541 | /* ------------------------------------------------------------------ */ |
543 | 542 | ||
544 | static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) | 543 | void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) |
545 | { | 544 | { |
546 | int luma_control,sync_control,mux; | ||
547 | 545 | ||
548 | dprintk("set tv norm = %s\n",norm->name); | 546 | dprintk("set tv norm = %s\n",norm->name); |
549 | dev->tvnorm = norm; | 547 | dev->tvnorm = norm; |
550 | 548 | ||
551 | mux = card_in(dev,dev->ctl_input).vmux; | ||
552 | luma_control = norm->luma_control; | ||
553 | sync_control = norm->sync_control; | ||
554 | |||
555 | if (mux > 5) | ||
556 | luma_control |= 0x80; /* svideo */ | ||
557 | if (noninterlaced || dev->nosignal) | ||
558 | sync_control |= 0x20; | ||
559 | |||
560 | /* setup cropping */ | 549 | /* setup cropping */ |
561 | dev->crop_bounds.left = norm->h_start; | 550 | dev->crop_bounds.left = norm->h_start; |
562 | dev->crop_defrect.left = norm->h_start; | 551 | dev->crop_defrect.left = norm->h_start; |
@@ -571,6 +560,40 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) | |||
571 | 560 | ||
572 | dev->crop_current = dev->crop_defrect; | 561 | dev->crop_current = dev->crop_defrect; |
573 | 562 | ||
563 | saa7134_set_decoder(dev); | ||
564 | |||
565 | if (card_in(dev, dev->ctl_input).tv) { | ||
566 | if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290) | ||
567 | && ((card(dev).tuner_config == 1) | ||
568 | || (card(dev).tuner_config == 2))) | ||
569 | saa7134_set_gpio(dev, 22, 5); | ||
570 | saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &norm->id); | ||
571 | } | ||
572 | } | ||
573 | |||
574 | static void video_mux(struct saa7134_dev *dev, int input) | ||
575 | { | ||
576 | dprintk("video input = %d [%s]\n", input, card_in(dev, input).name); | ||
577 | dev->ctl_input = input; | ||
578 | set_tvnorm(dev, dev->tvnorm); | ||
579 | saa7134_tvaudio_setinput(dev, &card_in(dev, input)); | ||
580 | } | ||
581 | |||
582 | void saa7134_set_decoder(struct saa7134_dev *dev) | ||
583 | { | ||
584 | int luma_control, sync_control, mux; | ||
585 | |||
586 | struct saa7134_tvnorm *norm = dev->tvnorm; | ||
587 | mux = card_in(dev, dev->ctl_input).vmux; | ||
588 | |||
589 | luma_control = norm->luma_control; | ||
590 | sync_control = norm->sync_control; | ||
591 | |||
592 | if (mux > 5) | ||
593 | luma_control |= 0x80; /* svideo */ | ||
594 | if (noninterlaced || dev->nosignal) | ||
595 | sync_control |= 0x20; | ||
596 | |||
574 | /* setup video decoder */ | 597 | /* setup video decoder */ |
575 | saa_writeb(SAA7134_INCR_DELAY, 0x08); | 598 | saa_writeb(SAA7134_INCR_DELAY, 0x08); |
576 | saa_writeb(SAA7134_ANALOG_IN_CTRL1, 0xc0 | mux); | 599 | saa_writeb(SAA7134_ANALOG_IN_CTRL1, 0xc0 | mux); |
@@ -585,9 +608,13 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) | |||
585 | saa_writeb(SAA7134_SYNC_CTRL, sync_control); | 608 | saa_writeb(SAA7134_SYNC_CTRL, sync_control); |
586 | saa_writeb(SAA7134_LUMA_CTRL, luma_control); | 609 | saa_writeb(SAA7134_LUMA_CTRL, luma_control); |
587 | saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright); | 610 | saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright); |
588 | saa_writeb(SAA7134_DEC_LUMA_CONTRAST, dev->ctl_contrast); | ||
589 | 611 | ||
590 | saa_writeb(SAA7134_DEC_CHROMA_SATURATION, dev->ctl_saturation); | 612 | saa_writeb(SAA7134_DEC_LUMA_CONTRAST, |
613 | dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast); | ||
614 | |||
615 | saa_writeb(SAA7134_DEC_CHROMA_SATURATION, | ||
616 | dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation); | ||
617 | |||
591 | saa_writeb(SAA7134_DEC_CHROMA_HUE, dev->ctl_hue); | 618 | saa_writeb(SAA7134_DEC_CHROMA_HUE, dev->ctl_hue); |
592 | saa_writeb(SAA7134_CHROMA_CTRL1, norm->chroma_ctrl1); | 619 | saa_writeb(SAA7134_CHROMA_CTRL1, norm->chroma_ctrl1); |
593 | saa_writeb(SAA7134_CHROMA_GAIN, norm->chroma_gain); | 620 | saa_writeb(SAA7134_CHROMA_GAIN, norm->chroma_gain); |
@@ -601,23 +628,6 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) | |||
601 | saa_writeb(SAA7134_MISC_VGATE_MSB, norm->vgate_misc); | 628 | saa_writeb(SAA7134_MISC_VGATE_MSB, norm->vgate_misc); |
602 | saa_writeb(SAA7134_RAW_DATA_GAIN, 0x40); | 629 | saa_writeb(SAA7134_RAW_DATA_GAIN, 0x40); |
603 | saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80); | 630 | saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80); |
604 | |||
605 | /* only tell the tuner if this is a tv input */ | ||
606 | if (card_in(dev,dev->ctl_input).tv) { | ||
607 | if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290) | ||
608 | && ((card(dev).tuner_config == 1) | ||
609 | || (card(dev).tuner_config == 2))) | ||
610 | saa7134_set_gpio(dev, 22, 5); | ||
611 | saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id); | ||
612 | } | ||
613 | } | ||
614 | |||
615 | static void video_mux(struct saa7134_dev *dev, int input) | ||
616 | { | ||
617 | dprintk("video input = %d [%s]\n",input,card_in(dev,input).name); | ||
618 | dev->ctl_input = input; | ||
619 | set_tvnorm(dev,dev->tvnorm); | ||
620 | saa7134_tvaudio_setinput(dev,&card_in(dev,input)); | ||
621 | } | 631 | } |
622 | 632 | ||
623 | static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) | 633 | static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) |
@@ -1038,6 +1048,8 @@ static int buffer_prepare(struct videobuf_queue *q, | |||
1038 | } | 1048 | } |
1039 | 1049 | ||
1040 | if (STATE_NEEDS_INIT == buf->vb.state) { | 1050 | if (STATE_NEEDS_INIT == buf->vb.state) { |
1051 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
1052 | |||
1041 | buf->vb.width = fh->width; | 1053 | buf->vb.width = fh->width; |
1042 | buf->vb.height = fh->height; | 1054 | buf->vb.height = fh->height; |
1043 | buf->vb.size = size; | 1055 | buf->vb.size = size; |
@@ -1049,8 +1061,8 @@ static int buffer_prepare(struct videobuf_queue *q, | |||
1049 | if (err) | 1061 | if (err) |
1050 | goto oops; | 1062 | goto oops; |
1051 | err = saa7134_pgtable_build(dev->pci,buf->pt, | 1063 | err = saa7134_pgtable_build(dev->pci,buf->pt, |
1052 | buf->vb.dma.sglist, | 1064 | dma->sglist, |
1053 | buf->vb.dma.sglen, | 1065 | dma->sglen, |
1054 | saa7134_buffer_startpage(buf)); | 1066 | saa7134_buffer_startpage(buf)); |
1055 | if (err) | 1067 | if (err) |
1056 | goto oops; | 1068 | goto oops; |
@@ -1273,26 +1285,24 @@ static int saa7134_resource(struct saa7134_fh *fh) | |||
1273 | static int video_open(struct inode *inode, struct file *file) | 1285 | static int video_open(struct inode *inode, struct file *file) |
1274 | { | 1286 | { |
1275 | int minor = iminor(inode); | 1287 | int minor = iminor(inode); |
1276 | struct saa7134_dev *h,*dev = NULL; | 1288 | struct saa7134_dev *dev; |
1277 | struct saa7134_fh *fh; | 1289 | struct saa7134_fh *fh; |
1278 | struct list_head *list; | ||
1279 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1290 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1280 | int radio = 0; | 1291 | int radio = 0; |
1281 | list_for_each(list,&saa7134_devlist) { | 1292 | list_for_each_entry(dev, &saa7134_devlist, devlist) { |
1282 | h = list_entry(list, struct saa7134_dev, devlist); | 1293 | if (dev->video_dev && (dev->video_dev->minor == minor)) |
1283 | if (h->video_dev && (h->video_dev->minor == minor)) | 1294 | goto found; |
1284 | dev = h; | 1295 | if (dev->radio_dev && (dev->radio_dev->minor == minor)) { |
1285 | if (h->radio_dev && (h->radio_dev->minor == minor)) { | ||
1286 | radio = 1; | 1296 | radio = 1; |
1287 | dev = h; | 1297 | goto found; |
1288 | } | 1298 | } |
1289 | if (h->vbi_dev && (h->vbi_dev->minor == minor)) { | 1299 | if (dev->vbi_dev && (dev->vbi_dev->minor == minor)) { |
1290 | type = V4L2_BUF_TYPE_VBI_CAPTURE; | 1300 | type = V4L2_BUF_TYPE_VBI_CAPTURE; |
1291 | dev = h; | 1301 | goto found; |
1292 | } | 1302 | } |
1293 | } | 1303 | } |
1294 | if (NULL == dev) | 1304 | return -ENODEV; |
1295 | return -ENODEV; | 1305 | found: |
1296 | 1306 | ||
1297 | dprintk("open minor=%d radio=%d type=%s\n",minor,radio, | 1307 | dprintk("open minor=%d radio=%d type=%s\n",minor,radio, |
1298 | v4l2_type_names[type]); | 1308 | v4l2_type_names[type]); |
@@ -1310,13 +1320,13 @@ static int video_open(struct inode *inode, struct file *file) | |||
1310 | fh->height = 576; | 1320 | fh->height = 576; |
1311 | v4l2_prio_open(&dev->prio,&fh->prio); | 1321 | v4l2_prio_open(&dev->prio,&fh->prio); |
1312 | 1322 | ||
1313 | videobuf_queue_init(&fh->cap, &video_qops, | 1323 | videobuf_queue_pci_init(&fh->cap, &video_qops, |
1314 | dev->pci, &dev->slock, | 1324 | dev->pci, &dev->slock, |
1315 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 1325 | V4L2_BUF_TYPE_VIDEO_CAPTURE, |
1316 | V4L2_FIELD_INTERLACED, | 1326 | V4L2_FIELD_INTERLACED, |
1317 | sizeof(struct saa7134_buf), | 1327 | sizeof(struct saa7134_buf), |
1318 | fh); | 1328 | fh); |
1319 | videobuf_queue_init(&fh->vbi, &saa7134_vbi_qops, | 1329 | videobuf_queue_pci_init(&fh->vbi, &saa7134_vbi_qops, |
1320 | dev->pci, &dev->slock, | 1330 | dev->pci, &dev->slock, |
1321 | V4L2_BUF_TYPE_VBI_CAPTURE, | 1331 | V4L2_BUF_TYPE_VBI_CAPTURE, |
1322 | V4L2_FIELD_SEQ_TB, | 1332 | V4L2_FIELD_SEQ_TB, |
@@ -1833,7 +1843,11 @@ static int video_do_ioctl(struct inode *inode, struct file *file, | |||
1833 | if (res_check(fh, RESOURCE_OVERLAY)) { | 1843 | if (res_check(fh, RESOURCE_OVERLAY)) { |
1834 | spin_lock_irqsave(&dev->slock,flags); | 1844 | spin_lock_irqsave(&dev->slock,flags); |
1835 | stop_preview(dev,fh); | 1845 | stop_preview(dev,fh); |
1846 | spin_unlock_irqrestore(&dev->slock, flags); | ||
1847 | |||
1836 | set_tvnorm(dev,&tvnorms[i]); | 1848 | set_tvnorm(dev,&tvnorms[i]); |
1849 | |||
1850 | spin_lock_irqsave(&dev->slock, flags); | ||
1837 | start_preview(dev,fh); | 1851 | start_preview(dev,fh); |
1838 | spin_unlock_irqrestore(&dev->slock,flags); | 1852 | spin_unlock_irqrestore(&dev->slock,flags); |
1839 | } else | 1853 | } else |
@@ -2138,29 +2152,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, | |||
2138 | } | 2152 | } |
2139 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 2153 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
2140 | case VIDIOCGMBUF: | 2154 | case VIDIOCGMBUF: |
2141 | { | 2155 | return videobuf_cgmbuf(saa7134_queue(fh), arg, gbuffers); |
2142 | struct video_mbuf *mbuf = arg; | ||
2143 | struct videobuf_queue *q; | ||
2144 | struct v4l2_requestbuffers req; | ||
2145 | unsigned int i; | ||
2146 | |||
2147 | q = saa7134_queue(fh); | ||
2148 | memset(&req,0,sizeof(req)); | ||
2149 | req.type = q->type; | ||
2150 | req.count = gbuffers; | ||
2151 | req.memory = V4L2_MEMORY_MMAP; | ||
2152 | err = videobuf_reqbufs(q,&req); | ||
2153 | if (err < 0) | ||
2154 | return err; | ||
2155 | memset(mbuf,0,sizeof(*mbuf)); | ||
2156 | mbuf->frames = req.count; | ||
2157 | mbuf->size = 0; | ||
2158 | for (i = 0; i < mbuf->frames; i++) { | ||
2159 | mbuf->offsets[i] = q->bufs[i]->boff; | ||
2160 | mbuf->size += q->bufs[i]->bsize; | ||
2161 | } | ||
2162 | return 0; | ||
2163 | } | ||
2164 | #endif | 2156 | #endif |
2165 | case VIDIOC_REQBUFS: | 2157 | case VIDIOC_REQBUFS: |
2166 | return videobuf_reqbufs(saa7134_queue(fh),arg); | 2158 | return videobuf_reqbufs(saa7134_queue(fh),arg); |
@@ -2412,34 +2404,40 @@ int saa7134_video_init1(struct saa7134_dev *dev) | |||
2412 | dev->video_q.timeout.data = (unsigned long)(&dev->video_q); | 2404 | dev->video_q.timeout.data = (unsigned long)(&dev->video_q); |
2413 | dev->video_q.dev = dev; | 2405 | dev->video_q.dev = dev; |
2414 | 2406 | ||
2415 | if (saa7134_boards[dev->board].video_out) { | 2407 | if (saa7134_boards[dev->board].video_out) |
2416 | /* enable video output */ | 2408 | saa7134_videoport_init(dev); |
2417 | int vo = saa7134_boards[dev->board].video_out; | 2409 | |
2418 | int video_reg; | 2410 | return 0; |
2419 | unsigned int vid_port_opts = saa7134_boards[dev->board].vid_port_opts; | 2411 | } |
2420 | saa_writeb(SAA7134_VIDEO_PORT_CTRL0, video_out[vo][0]); | 2412 | |
2421 | video_reg = video_out[vo][1]; | 2413 | int saa7134_videoport_init(struct saa7134_dev *dev) |
2422 | if (vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED) | 2414 | { |
2423 | video_reg &= ~VP_T_CODE_P_INVERTED; | 2415 | /* enable video output */ |
2424 | saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_reg); | 2416 | int vo = saa7134_boards[dev->board].video_out; |
2425 | saa_writeb(SAA7134_VIDEO_PORT_CTRL2, video_out[vo][2]); | 2417 | int video_reg; |
2426 | saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]); | 2418 | unsigned int vid_port_opts = saa7134_boards[dev->board].vid_port_opts; |
2427 | saa_writeb(SAA7134_VIDEO_PORT_CTRL4, video_out[vo][4]); | 2419 | saa_writeb(SAA7134_VIDEO_PORT_CTRL0, video_out[vo][0]); |
2428 | video_reg = video_out[vo][5]; | 2420 | video_reg = video_out[vo][1]; |
2429 | if (vid_port_opts & SET_CLOCK_NOT_DELAYED) | 2421 | if (vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED) |
2430 | video_reg &= ~VP_CLK_CTRL2_DELAYED; | 2422 | video_reg &= ~VP_T_CODE_P_INVERTED; |
2431 | if (vid_port_opts & SET_CLOCK_INVERTED) | 2423 | saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_reg); |
2432 | video_reg |= VP_CLK_CTRL1_INVERTED; | 2424 | saa_writeb(SAA7134_VIDEO_PORT_CTRL2, video_out[vo][2]); |
2433 | saa_writeb(SAA7134_VIDEO_PORT_CTRL5, video_reg); | 2425 | saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]); |
2434 | video_reg = video_out[vo][6]; | 2426 | saa_writeb(SAA7134_VIDEO_PORT_CTRL4, video_out[vo][4]); |
2435 | if (vid_port_opts & SET_VSYNC_OFF) { | 2427 | video_reg = video_out[vo][5]; |
2436 | video_reg &= ~VP_VS_TYPE_MASK; | 2428 | if (vid_port_opts & SET_CLOCK_NOT_DELAYED) |
2437 | video_reg |= VP_VS_TYPE_OFF; | 2429 | video_reg &= ~VP_CLK_CTRL2_DELAYED; |
2438 | } | 2430 | if (vid_port_opts & SET_CLOCK_INVERTED) |
2439 | saa_writeb(SAA7134_VIDEO_PORT_CTRL6, video_reg); | 2431 | video_reg |= VP_CLK_CTRL1_INVERTED; |
2440 | saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]); | 2432 | saa_writeb(SAA7134_VIDEO_PORT_CTRL5, video_reg); |
2441 | saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]); | 2433 | video_reg = video_out[vo][6]; |
2442 | } | 2434 | if (vid_port_opts & SET_VSYNC_OFF) { |
2435 | video_reg &= ~VP_VS_TYPE_MASK; | ||
2436 | video_reg |= VP_VS_TYPE_OFF; | ||
2437 | } | ||
2438 | saa_writeb(SAA7134_VIDEO_PORT_CTRL6, video_reg); | ||
2439 | saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]); | ||
2440 | saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]); | ||
2443 | 2441 | ||
2444 | return 0; | 2442 | return 0; |
2445 | } | 2443 | } |
@@ -2454,7 +2452,7 @@ int saa7134_video_init2(struct saa7134_dev *dev) | |||
2454 | return 0; | 2452 | return 0; |
2455 | } | 2453 | } |
2456 | 2454 | ||
2457 | void saa7134_irq_video_intl(struct saa7134_dev *dev) | 2455 | void saa7134_irq_video_signalchange(struct saa7134_dev *dev) |
2458 | { | 2456 | { |
2459 | static const char *st[] = { | 2457 | static const char *st[] = { |
2460 | "(no signal)", "NTSC", "PAL", "SECAM" }; | 2458 | "(no signal)", "NTSC", "PAL", "SECAM" }; |
@@ -2466,24 +2464,28 @@ void saa7134_irq_video_intl(struct saa7134_dev *dev) | |||
2466 | (st1 & 0x40) ? "not locked" : "locked", | 2464 | (st1 & 0x40) ? "not locked" : "locked", |
2467 | (st2 & 0x40) ? "no" : "yes", | 2465 | (st2 & 0x40) ? "no" : "yes", |
2468 | st[st1 & 0x03]); | 2466 | st[st1 & 0x03]); |
2469 | dev->nosignal = (st1 & 0x40) || (st2 & 0x40); | 2467 | dev->nosignal = (st1 & 0x40) || (st2 & 0x40) || !(st2 & 0x1); |
2470 | 2468 | ||
2471 | if (dev->nosignal) { | 2469 | if (dev->nosignal) { |
2472 | /* no video signal -> mute audio */ | 2470 | /* no video signal -> mute audio */ |
2473 | if (dev->ctl_automute) | 2471 | if (dev->ctl_automute) |
2474 | dev->automute = 1; | 2472 | dev->automute = 1; |
2475 | saa7134_tvaudio_setmute(dev); | 2473 | saa7134_tvaudio_setmute(dev); |
2476 | saa_setb(SAA7134_SYNC_CTRL, 0x20); | ||
2477 | } else { | 2474 | } else { |
2478 | /* wake up tvaudio audio carrier scan thread */ | 2475 | /* wake up tvaudio audio carrier scan thread */ |
2479 | saa7134_tvaudio_do_scan(dev); | 2476 | saa7134_tvaudio_do_scan(dev); |
2480 | if (!noninterlaced) | ||
2481 | saa_clearb(SAA7134_SYNC_CTRL, 0x20); | ||
2482 | } | 2477 | } |
2478 | |||
2479 | if ((st2 & 0x80) && !noninterlaced && !dev->nosignal) | ||
2480 | saa_clearb(SAA7134_SYNC_CTRL, 0x20); | ||
2481 | else | ||
2482 | saa_setb(SAA7134_SYNC_CTRL, 0x20); | ||
2483 | |||
2483 | if (dev->mops && dev->mops->signal_change) | 2484 | if (dev->mops && dev->mops->signal_change) |
2484 | dev->mops->signal_change(dev); | 2485 | dev->mops->signal_change(dev); |
2485 | } | 2486 | } |
2486 | 2487 | ||
2488 | |||
2487 | void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status) | 2489 | void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status) |
2488 | { | 2490 | { |
2489 | enum v4l2_field field; | 2491 | enum v4l2_field field; |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 346255468dad..28ec6804bd5d 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -37,12 +37,12 @@ | |||
37 | #include <media/tuner.h> | 37 | #include <media/tuner.h> |
38 | #include <media/ir-common.h> | 38 | #include <media/ir-common.h> |
39 | #include <media/ir-kbd-i2c.h> | 39 | #include <media/ir-kbd-i2c.h> |
40 | #include <media/video-buf.h> | 40 | #include <media/videobuf-dma-sg.h> |
41 | #include <sound/driver.h> | 41 | #include <sound/driver.h> |
42 | #include <sound/core.h> | 42 | #include <sound/core.h> |
43 | #include <sound/pcm.h> | 43 | #include <sound/pcm.h> |
44 | #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) | 44 | #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE) |
45 | #include <media/video-buf-dvb.h> | 45 | #include <media/videobuf-dvb.h> |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #define UNSET (-1U) | 48 | #define UNSET (-1U) |
@@ -239,6 +239,7 @@ struct saa7134_format { | |||
239 | #define SAA7134_BOARD_KWORLD_DVBT_210 114 | 239 | #define SAA7134_BOARD_KWORLD_DVBT_210 114 |
240 | #define SAA7134_BOARD_SABRENT_TV_PCB05 115 | 240 | #define SAA7134_BOARD_SABRENT_TV_PCB05 115 |
241 | #define SAA7134_BOARD_10MOONSTVMASTER3 116 | 241 | #define SAA7134_BOARD_10MOONSTVMASTER3 116 |
242 | #define SAA7134_BOARD_AVERMEDIA_SUPER_007 117 | ||
242 | 243 | ||
243 | #define SAA7134_MAXBOARDS 8 | 244 | #define SAA7134_MAXBOARDS 8 |
244 | #define SAA7134_INPUT_MAX 8 | 245 | #define SAA7134_INPUT_MAX 8 |
@@ -523,6 +524,7 @@ struct saa7134_dev { | |||
523 | unsigned int hw_mute; | 524 | unsigned int hw_mute; |
524 | int last_carrier; | 525 | int last_carrier; |
525 | int nosignal; | 526 | int nosignal; |
527 | unsigned int inresume; | ||
526 | 528 | ||
527 | /* SAA7134_MPEG_* */ | 529 | /* SAA7134_MPEG_* */ |
528 | struct saa7134_ts ts; | 530 | struct saa7134_ts ts; |
@@ -536,7 +538,7 @@ struct saa7134_dev { | |||
536 | struct work_struct empress_workqueue; | 538 | struct work_struct empress_workqueue; |
537 | int empress_started; | 539 | int empress_started; |
538 | 540 | ||
539 | #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) | 541 | #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE) |
540 | /* SAA7134_MPEG_DVB only */ | 542 | /* SAA7134_MPEG_DVB only */ |
541 | struct videobuf_dvb dvb; | 543 | struct videobuf_dvb dvb; |
542 | int (*original_demod_sleep)(struct dvb_frontend* fe); | 544 | int (*original_demod_sleep)(struct dvb_frontend* fe); |
@@ -593,6 +595,9 @@ void saa7134_buffer_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q); | |||
593 | void saa7134_buffer_timeout(unsigned long data); | 595 | void saa7134_buffer_timeout(unsigned long data); |
594 | void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf); | 596 | void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf); |
595 | 597 | ||
598 | int saa7134_buffer_requeue(struct saa7134_dev *dev, | ||
599 | struct saa7134_dmaqueue *q); | ||
600 | |||
596 | int saa7134_set_dmabits(struct saa7134_dev *dev); | 601 | int saa7134_set_dmabits(struct saa7134_dev *dev); |
597 | 602 | ||
598 | extern int (*saa7134_dmasound_init)(struct saa7134_dev *dev); | 603 | extern int (*saa7134_dmasound_init)(struct saa7134_dev *dev); |
@@ -625,12 +630,16 @@ void saa7134_i2c_call_clients(struct saa7134_dev *dev, | |||
625 | extern struct video_device saa7134_video_template; | 630 | extern struct video_device saa7134_video_template; |
626 | extern struct video_device saa7134_radio_template; | 631 | extern struct video_device saa7134_radio_template; |
627 | 632 | ||
633 | void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm); | ||
634 | int saa7134_videoport_init(struct saa7134_dev *dev); | ||
635 | void saa7134_set_decoder(struct saa7134_dev *dev); | ||
636 | |||
628 | int saa7134_common_ioctl(struct saa7134_dev *dev, | 637 | int saa7134_common_ioctl(struct saa7134_dev *dev, |
629 | unsigned int cmd, void *arg); | 638 | unsigned int cmd, void *arg); |
630 | 639 | ||
631 | int saa7134_video_init1(struct saa7134_dev *dev); | 640 | int saa7134_video_init1(struct saa7134_dev *dev); |
632 | int saa7134_video_init2(struct saa7134_dev *dev); | 641 | int saa7134_video_init2(struct saa7134_dev *dev); |
633 | void saa7134_irq_video_intl(struct saa7134_dev *dev); | 642 | void saa7134_irq_video_signalchange(struct saa7134_dev *dev); |
634 | void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status); | 643 | void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status); |
635 | 644 | ||
636 | 645 | ||
@@ -648,6 +657,8 @@ void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status); | |||
648 | int saa7134_ts_register(struct saa7134_mpeg_ops *ops); | 657 | int saa7134_ts_register(struct saa7134_mpeg_ops *ops); |
649 | void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops); | 658 | void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops); |
650 | 659 | ||
660 | int saa7134_ts_init_hw(struct saa7134_dev *dev); | ||
661 | |||
651 | /* ----------------------------------------------------------- */ | 662 | /* ----------------------------------------------------------- */ |
652 | /* saa7134-vbi.c */ | 663 | /* saa7134-vbi.c */ |
653 | 664 | ||
@@ -676,6 +687,8 @@ int saa7134_tvaudio_do_scan(struct saa7134_dev *dev); | |||
676 | 687 | ||
677 | int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value); | 688 | int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value); |
678 | 689 | ||
690 | void saa7134_enable_i2s(struct saa7134_dev *dev); | ||
691 | |||
679 | /* ----------------------------------------------------------- */ | 692 | /* ----------------------------------------------------------- */ |
680 | /* saa7134-oss.c */ | 693 | /* saa7134-oss.c */ |
681 | 694 | ||
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 36d8a455e0ec..6991e06f7651 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/param.h> | 24 | #include <linux/param.h> |
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
27 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
28 | #include <linux/device.h> | 27 | #include <linux/device.h> |
@@ -1030,7 +1029,8 @@ static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count) | |||
1030 | NOTE 2: buffers are PAGE_SIZE long | 1029 | NOTE 2: buffers are PAGE_SIZE long |
1031 | */ | 1030 | */ |
1032 | 1031 | ||
1033 | static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf) | 1032 | static ssize_t sn9c102_show_reg(struct device* cd, |
1033 | struct device_attribute *attr, char* buf) | ||
1034 | { | 1034 | { |
1035 | struct sn9c102_device* cam; | 1035 | struct sn9c102_device* cam; |
1036 | ssize_t count; | 1036 | ssize_t count; |
@@ -1054,7 +1054,8 @@ static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf) | |||
1054 | 1054 | ||
1055 | 1055 | ||
1056 | static ssize_t | 1056 | static ssize_t |
1057 | sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len) | 1057 | sn9c102_store_reg(struct device* cd, struct device_attribute *attr, |
1058 | const char* buf, size_t len) | ||
1058 | { | 1059 | { |
1059 | struct sn9c102_device* cam; | 1060 | struct sn9c102_device* cam; |
1060 | u16 index; | 1061 | u16 index; |
@@ -1087,7 +1088,8 @@ sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len) | |||
1087 | } | 1088 | } |
1088 | 1089 | ||
1089 | 1090 | ||
1090 | static ssize_t sn9c102_show_val(struct class_device* cd, char* buf) | 1091 | static ssize_t sn9c102_show_val(struct device* cd, |
1092 | struct device_attribute *attr, char* buf) | ||
1091 | { | 1093 | { |
1092 | struct sn9c102_device* cam; | 1094 | struct sn9c102_device* cam; |
1093 | ssize_t count; | 1095 | ssize_t count; |
@@ -1119,7 +1121,8 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf) | |||
1119 | 1121 | ||
1120 | 1122 | ||
1121 | static ssize_t | 1123 | static ssize_t |
1122 | sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) | 1124 | sn9c102_store_val(struct device* cd, struct device_attribute *attr, |
1125 | const char* buf, size_t len) | ||
1123 | { | 1126 | { |
1124 | struct sn9c102_device* cam; | 1127 | struct sn9c102_device* cam; |
1125 | u16 value; | 1128 | u16 value; |
@@ -1158,7 +1161,8 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) | |||
1158 | } | 1161 | } |
1159 | 1162 | ||
1160 | 1163 | ||
1161 | static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf) | 1164 | static ssize_t sn9c102_show_i2c_reg(struct device* cd, |
1165 | struct device_attribute *attr, char* buf) | ||
1162 | { | 1166 | { |
1163 | struct sn9c102_device* cam; | 1167 | struct sn9c102_device* cam; |
1164 | ssize_t count; | 1168 | ssize_t count; |
@@ -1184,7 +1188,8 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf) | |||
1184 | 1188 | ||
1185 | 1189 | ||
1186 | static ssize_t | 1190 | static ssize_t |
1187 | sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) | 1191 | sn9c102_store_i2c_reg(struct device* cd, struct device_attribute *attr, |
1192 | const char* buf, size_t len) | ||
1188 | { | 1193 | { |
1189 | struct sn9c102_device* cam; | 1194 | struct sn9c102_device* cam; |
1190 | u16 index; | 1195 | u16 index; |
@@ -1217,7 +1222,8 @@ sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) | |||
1217 | } | 1222 | } |
1218 | 1223 | ||
1219 | 1224 | ||
1220 | static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) | 1225 | static ssize_t sn9c102_show_i2c_val(struct device* cd, |
1226 | struct device_attribute *attr, char* buf) | ||
1221 | { | 1227 | { |
1222 | struct sn9c102_device* cam; | 1228 | struct sn9c102_device* cam; |
1223 | ssize_t count; | 1229 | ssize_t count; |
@@ -1254,7 +1260,8 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) | |||
1254 | 1260 | ||
1255 | 1261 | ||
1256 | static ssize_t | 1262 | static ssize_t |
1257 | sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) | 1263 | sn9c102_store_i2c_val(struct device* cd, struct device_attribute *attr, |
1264 | const char* buf, size_t len) | ||
1258 | { | 1265 | { |
1259 | struct sn9c102_device* cam; | 1266 | struct sn9c102_device* cam; |
1260 | u16 value; | 1267 | u16 value; |
@@ -1299,7 +1306,8 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) | |||
1299 | 1306 | ||
1300 | 1307 | ||
1301 | static ssize_t | 1308 | static ssize_t |
1302 | sn9c102_store_green(struct class_device* cd, const char* buf, size_t len) | 1309 | sn9c102_store_green(struct device* cd, struct device_attribute *attr, |
1310 | const char* buf, size_t len) | ||
1303 | { | 1311 | { |
1304 | struct sn9c102_device* cam; | 1312 | struct sn9c102_device* cam; |
1305 | enum sn9c102_bridge bridge; | 1313 | enum sn9c102_bridge bridge; |
@@ -1330,16 +1338,16 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len) | |||
1330 | case BRIDGE_SN9C102: | 1338 | case BRIDGE_SN9C102: |
1331 | if (value > 0x0f) | 1339 | if (value > 0x0f) |
1332 | return -EINVAL; | 1340 | return -EINVAL; |
1333 | if ((res = sn9c102_store_reg(cd, "0x11", 4)) >= 0) | 1341 | if ((res = sn9c102_store_reg(cd, attr, "0x11", 4)) >= 0) |
1334 | res = sn9c102_store_val(cd, buf, len); | 1342 | res = sn9c102_store_val(cd, attr, buf, len); |
1335 | break; | 1343 | break; |
1336 | case BRIDGE_SN9C103: | 1344 | case BRIDGE_SN9C103: |
1337 | case BRIDGE_SN9C105: | 1345 | case BRIDGE_SN9C105: |
1338 | case BRIDGE_SN9C120: | 1346 | case BRIDGE_SN9C120: |
1339 | if (value > 0x7f) | 1347 | if (value > 0x7f) |
1340 | return -EINVAL; | 1348 | return -EINVAL; |
1341 | if ((res = sn9c102_store_reg(cd, "0x07", 4)) >= 0) | 1349 | if ((res = sn9c102_store_reg(cd, attr, "0x07", 4)) >= 0) |
1342 | res = sn9c102_store_val(cd, buf, len); | 1350 | res = sn9c102_store_val(cd, attr, buf, len); |
1343 | break; | 1351 | break; |
1344 | } | 1352 | } |
1345 | 1353 | ||
@@ -1348,7 +1356,8 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len) | |||
1348 | 1356 | ||
1349 | 1357 | ||
1350 | static ssize_t | 1358 | static ssize_t |
1351 | sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len) | 1359 | sn9c102_store_blue(struct device* cd, struct device_attribute *attr, |
1360 | const char* buf, size_t len) | ||
1352 | { | 1361 | { |
1353 | ssize_t res = 0; | 1362 | ssize_t res = 0; |
1354 | u16 value; | 1363 | u16 value; |
@@ -1358,15 +1367,16 @@ sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len) | |||
1358 | if (!count || value > 0x7f) | 1367 | if (!count || value > 0x7f) |
1359 | return -EINVAL; | 1368 | return -EINVAL; |
1360 | 1369 | ||
1361 | if ((res = sn9c102_store_reg(cd, "0x06", 4)) >= 0) | 1370 | if ((res = sn9c102_store_reg(cd, attr, "0x06", 4)) >= 0) |
1362 | res = sn9c102_store_val(cd, buf, len); | 1371 | res = sn9c102_store_val(cd, attr, buf, len); |
1363 | 1372 | ||
1364 | return res; | 1373 | return res; |
1365 | } | 1374 | } |
1366 | 1375 | ||
1367 | 1376 | ||
1368 | static ssize_t | 1377 | static ssize_t |
1369 | sn9c102_store_red(struct class_device* cd, const char* buf, size_t len) | 1378 | sn9c102_store_red(struct device* cd, struct device_attribute *attr, |
1379 | const char* buf, size_t len) | ||
1370 | { | 1380 | { |
1371 | ssize_t res = 0; | 1381 | ssize_t res = 0; |
1372 | u16 value; | 1382 | u16 value; |
@@ -1376,14 +1386,16 @@ sn9c102_store_red(struct class_device* cd, const char* buf, size_t len) | |||
1376 | if (!count || value > 0x7f) | 1386 | if (!count || value > 0x7f) |
1377 | return -EINVAL; | 1387 | return -EINVAL; |
1378 | 1388 | ||
1379 | if ((res = sn9c102_store_reg(cd, "0x05", 4)) >= 0) | 1389 | if ((res = sn9c102_store_reg(cd, attr, "0x05", 4)) >= 0) |
1380 | res = sn9c102_store_val(cd, buf, len); | 1390 | res = sn9c102_store_val(cd, attr, buf, len); |
1381 | 1391 | ||
1382 | return res; | 1392 | return res; |
1383 | } | 1393 | } |
1384 | 1394 | ||
1385 | 1395 | ||
1386 | static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf) | 1396 | static ssize_t sn9c102_show_frame_header(struct device* cd, |
1397 | struct device_attribute *attr, | ||
1398 | char* buf) | ||
1387 | { | 1399 | { |
1388 | struct sn9c102_device* cam; | 1400 | struct sn9c102_device* cam; |
1389 | ssize_t count; | 1401 | ssize_t count; |
@@ -1402,72 +1414,63 @@ static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf) | |||
1402 | } | 1414 | } |
1403 | 1415 | ||
1404 | 1416 | ||
1405 | static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, | 1417 | static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, sn9c102_show_reg, sn9c102_store_reg); |
1406 | sn9c102_show_reg, sn9c102_store_reg); | 1418 | static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, sn9c102_show_val, sn9c102_store_val); |
1407 | static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR, | 1419 | static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, |
1408 | sn9c102_show_val, sn9c102_store_val); | 1420 | sn9c102_show_i2c_reg, sn9c102_store_i2c_reg); |
1409 | static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, | 1421 | static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, |
1410 | sn9c102_show_i2c_reg, sn9c102_store_i2c_reg); | 1422 | sn9c102_show_i2c_val, sn9c102_store_i2c_val); |
1411 | static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, | 1423 | static DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green); |
1412 | sn9c102_show_i2c_val, sn9c102_store_i2c_val); | 1424 | static DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue); |
1413 | static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green); | 1425 | static DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red); |
1414 | static CLASS_DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue); | 1426 | static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL); |
1415 | static CLASS_DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red); | ||
1416 | static CLASS_DEVICE_ATTR(frame_header, S_IRUGO, | ||
1417 | sn9c102_show_frame_header, NULL); | ||
1418 | 1427 | ||
1419 | 1428 | ||
1420 | static int sn9c102_create_sysfs(struct sn9c102_device* cam) | 1429 | static int sn9c102_create_sysfs(struct sn9c102_device* cam) |
1421 | { | 1430 | { |
1422 | struct class_device *classdev = &(cam->v4ldev->class_dev); | 1431 | struct device *classdev = &(cam->v4ldev->class_dev); |
1423 | int err = 0; | 1432 | int err = 0; |
1424 | 1433 | ||
1425 | if ((err = class_device_create_file(classdev, &class_device_attr_reg))) | 1434 | if ((err = device_create_file(classdev, &dev_attr_reg))) |
1426 | goto err_out; | 1435 | goto err_out; |
1427 | if ((err = class_device_create_file(classdev, &class_device_attr_val))) | 1436 | if ((err = device_create_file(classdev, &dev_attr_val))) |
1428 | goto err_reg; | 1437 | goto err_reg; |
1429 | if ((err = class_device_create_file(classdev, | 1438 | if ((err = device_create_file(classdev, &dev_attr_frame_header))) |
1430 | &class_device_attr_frame_header))) | ||
1431 | goto err_val; | 1439 | goto err_val; |
1432 | 1440 | ||
1433 | if (cam->sensor.sysfs_ops) { | 1441 | if (cam->sensor.sysfs_ops) { |
1434 | if ((err = class_device_create_file(classdev, | 1442 | if ((err = device_create_file(classdev, &dev_attr_i2c_reg))) |
1435 | &class_device_attr_i2c_reg))) | ||
1436 | goto err_frame_header; | 1443 | goto err_frame_header; |
1437 | if ((err = class_device_create_file(classdev, | 1444 | if ((err = device_create_file(classdev, &dev_attr_i2c_val))) |
1438 | &class_device_attr_i2c_val))) | ||
1439 | goto err_i2c_reg; | 1445 | goto err_i2c_reg; |
1440 | } | 1446 | } |
1441 | 1447 | ||
1442 | if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { | 1448 | if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { |
1443 | if ((err = class_device_create_file(classdev, | 1449 | if ((err = device_create_file(classdev, &dev_attr_green))) |
1444 | &class_device_attr_green))) | ||
1445 | goto err_i2c_val; | 1450 | goto err_i2c_val; |
1446 | } else { | 1451 | } else { |
1447 | if ((err = class_device_create_file(classdev, | 1452 | if ((err = device_create_file(classdev, &dev_attr_blue))) |
1448 | &class_device_attr_blue))) | ||
1449 | goto err_i2c_val; | 1453 | goto err_i2c_val; |
1450 | if ((err = class_device_create_file(classdev, | 1454 | if ((err = device_create_file(classdev, &dev_attr_red))) |
1451 | &class_device_attr_red))) | ||
1452 | goto err_blue; | 1455 | goto err_blue; |
1453 | } | 1456 | } |
1454 | 1457 | ||
1455 | return 0; | 1458 | return 0; |
1456 | 1459 | ||
1457 | err_blue: | 1460 | err_blue: |
1458 | class_device_remove_file(classdev, &class_device_attr_blue); | 1461 | device_remove_file(classdev, &dev_attr_blue); |
1459 | err_i2c_val: | 1462 | err_i2c_val: |
1460 | if (cam->sensor.sysfs_ops) | 1463 | if (cam->sensor.sysfs_ops) |
1461 | class_device_remove_file(classdev, &class_device_attr_i2c_val); | 1464 | device_remove_file(classdev, &dev_attr_i2c_val); |
1462 | err_i2c_reg: | 1465 | err_i2c_reg: |
1463 | if (cam->sensor.sysfs_ops) | 1466 | if (cam->sensor.sysfs_ops) |
1464 | class_device_remove_file(classdev, &class_device_attr_i2c_reg); | 1467 | device_remove_file(classdev, &dev_attr_i2c_reg); |
1465 | err_frame_header: | 1468 | err_frame_header: |
1466 | class_device_remove_file(classdev, &class_device_attr_frame_header); | 1469 | device_remove_file(classdev, &dev_attr_frame_header); |
1467 | err_val: | 1470 | err_val: |
1468 | class_device_remove_file(classdev, &class_device_attr_val); | 1471 | device_remove_file(classdev, &dev_attr_val); |
1469 | err_reg: | 1472 | err_reg: |
1470 | class_device_remove_file(classdev, &class_device_attr_reg); | 1473 | device_remove_file(classdev, &dev_attr_reg); |
1471 | err_out: | 1474 | err_out: |
1472 | return err; | 1475 | return err; |
1473 | } | 1476 | } |
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index 4dc5bc714b95..9e009a7ab863 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c | |||
@@ -499,13 +499,14 @@ exit: | |||
499 | * sysfs | 499 | * sysfs |
500 | ***************************************************************************/ | 500 | ***************************************************************************/ |
501 | #define stv680_file(name, variable, field) \ | 501 | #define stv680_file(name, variable, field) \ |
502 | static ssize_t show_##name(struct class_device *class_dev, char *buf) \ | 502 | static ssize_t show_##name(struct device *class_dev, \ |
503 | struct device_attribute *attr, char *buf) \ | ||
503 | { \ | 504 | { \ |
504 | struct video_device *vdev = to_video_device(class_dev); \ | 505 | struct video_device *vdev = to_video_device(class_dev); \ |
505 | struct usb_stv *stv = video_get_drvdata(vdev); \ | 506 | struct usb_stv *stv = video_get_drvdata(vdev); \ |
506 | return sprintf(buf, field, stv->variable); \ | 507 | return sprintf(buf, field, stv->variable); \ |
507 | } \ | 508 | } \ |
508 | static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); | 509 | static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); |
509 | 510 | ||
510 | stv680_file(model, camera_name, "%s\n"); | 511 | stv680_file(model, camera_name, "%s\n"); |
511 | stv680_file(in_use, user, "%d\n"); | 512 | stv680_file(in_use, user, "%d\n"); |
@@ -520,53 +521,53 @@ static int stv680_create_sysfs_files(struct video_device *vdev) | |||
520 | { | 521 | { |
521 | int rc; | 522 | int rc; |
522 | 523 | ||
523 | rc = video_device_create_file(vdev, &class_device_attr_model); | 524 | rc = video_device_create_file(vdev, &dev_attr_model); |
524 | if (rc) goto err; | 525 | if (rc) goto err; |
525 | rc = video_device_create_file(vdev, &class_device_attr_in_use); | 526 | rc = video_device_create_file(vdev, &dev_attr_in_use); |
526 | if (rc) goto err_model; | 527 | if (rc) goto err_model; |
527 | rc = video_device_create_file(vdev, &class_device_attr_streaming); | 528 | rc = video_device_create_file(vdev, &dev_attr_streaming); |
528 | if (rc) goto err_inuse; | 529 | if (rc) goto err_inuse; |
529 | rc = video_device_create_file(vdev, &class_device_attr_palette); | 530 | rc = video_device_create_file(vdev, &dev_attr_palette); |
530 | if (rc) goto err_stream; | 531 | if (rc) goto err_stream; |
531 | rc = video_device_create_file(vdev, &class_device_attr_frames_total); | 532 | rc = video_device_create_file(vdev, &dev_attr_frames_total); |
532 | if (rc) goto err_pal; | 533 | if (rc) goto err_pal; |
533 | rc = video_device_create_file(vdev, &class_device_attr_frames_read); | 534 | rc = video_device_create_file(vdev, &dev_attr_frames_read); |
534 | if (rc) goto err_framtot; | 535 | if (rc) goto err_framtot; |
535 | rc = video_device_create_file(vdev, &class_device_attr_packets_dropped); | 536 | rc = video_device_create_file(vdev, &dev_attr_packets_dropped); |
536 | if (rc) goto err_framread; | 537 | if (rc) goto err_framread; |
537 | rc = video_device_create_file(vdev, &class_device_attr_decoding_errors); | 538 | rc = video_device_create_file(vdev, &dev_attr_decoding_errors); |
538 | if (rc) goto err_dropped; | 539 | if (rc) goto err_dropped; |
539 | 540 | ||
540 | return 0; | 541 | return 0; |
541 | 542 | ||
542 | err_dropped: | 543 | err_dropped: |
543 | video_device_remove_file(vdev, &class_device_attr_packets_dropped); | 544 | video_device_remove_file(vdev, &dev_attr_packets_dropped); |
544 | err_framread: | 545 | err_framread: |
545 | video_device_remove_file(vdev, &class_device_attr_frames_read); | 546 | video_device_remove_file(vdev, &dev_attr_frames_read); |
546 | err_framtot: | 547 | err_framtot: |
547 | video_device_remove_file(vdev, &class_device_attr_frames_total); | 548 | video_device_remove_file(vdev, &dev_attr_frames_total); |
548 | err_pal: | 549 | err_pal: |
549 | video_device_remove_file(vdev, &class_device_attr_palette); | 550 | video_device_remove_file(vdev, &dev_attr_palette); |
550 | err_stream: | 551 | err_stream: |
551 | video_device_remove_file(vdev, &class_device_attr_streaming); | 552 | video_device_remove_file(vdev, &dev_attr_streaming); |
552 | err_inuse: | 553 | err_inuse: |
553 | video_device_remove_file(vdev, &class_device_attr_in_use); | 554 | video_device_remove_file(vdev, &dev_attr_in_use); |
554 | err_model: | 555 | err_model: |
555 | video_device_remove_file(vdev, &class_device_attr_model); | 556 | video_device_remove_file(vdev, &dev_attr_model); |
556 | err: | 557 | err: |
557 | return rc; | 558 | return rc; |
558 | } | 559 | } |
559 | 560 | ||
560 | static void stv680_remove_sysfs_files(struct video_device *vdev) | 561 | static void stv680_remove_sysfs_files(struct video_device *vdev) |
561 | { | 562 | { |
562 | video_device_remove_file(vdev, &class_device_attr_model); | 563 | video_device_remove_file(vdev, &dev_attr_model); |
563 | video_device_remove_file(vdev, &class_device_attr_in_use); | 564 | video_device_remove_file(vdev, &dev_attr_in_use); |
564 | video_device_remove_file(vdev, &class_device_attr_streaming); | 565 | video_device_remove_file(vdev, &dev_attr_streaming); |
565 | video_device_remove_file(vdev, &class_device_attr_palette); | 566 | video_device_remove_file(vdev, &dev_attr_palette); |
566 | video_device_remove_file(vdev, &class_device_attr_frames_total); | 567 | video_device_remove_file(vdev, &dev_attr_frames_total); |
567 | video_device_remove_file(vdev, &class_device_attr_frames_read); | 568 | video_device_remove_file(vdev, &dev_attr_frames_read); |
568 | video_device_remove_file(vdev, &class_device_attr_packets_dropped); | 569 | video_device_remove_file(vdev, &dev_attr_packets_dropped); |
569 | video_device_remove_file(vdev, &class_device_attr_decoding_errors); | 570 | video_device_remove_file(vdev, &dev_attr_decoding_errors); |
570 | } | 571 | } |
571 | 572 | ||
572 | /******************************************************************** | 573 | /******************************************************************** |
diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c new file mode 100644 index 000000000000..41cd6a0b0485 --- /dev/null +++ b/drivers/media/video/tcm825x.c | |||
@@ -0,0 +1,928 @@ | |||
1 | /* | ||
2 | * drivers/media/video/tcm825x.c | ||
3 | * | ||
4 | * TCM825X camera sensor driver. | ||
5 | * | ||
6 | * Copyright (C) 2007 Nokia Corporation. | ||
7 | * | ||
8 | * Contact: Sakari Ailus <sakari.ailus@nokia.com> | ||
9 | * | ||
10 | * Based on code from David Cohen <david.cohen@indt.org.br> | ||
11 | * | ||
12 | * This driver was based on ov9640 sensor driver from MontaVista | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * version 2 as published by the Free Software Foundation. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, but | ||
19 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
21 | * General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
26 | * 02110-1301 USA | ||
27 | */ | ||
28 | |||
29 | #include <linux/i2c.h> | ||
30 | #include <media/v4l2-int-device.h> | ||
31 | |||
32 | #include "tcm825x.h" | ||
33 | |||
34 | /* | ||
35 | * The sensor has two fps modes: the lower one just gives half the fps | ||
36 | * at the same xclk than the high one. | ||
37 | */ | ||
38 | #define MAX_FPS 30 | ||
39 | #define MIN_FPS 8 | ||
40 | #define MAX_HALF_FPS (MAX_FPS / 2) | ||
41 | #define HIGH_FPS_MODE_LOWER_LIMIT 14 | ||
42 | #define DEFAULT_FPS MAX_HALF_FPS | ||
43 | |||
44 | struct tcm825x_sensor { | ||
45 | const struct tcm825x_platform_data *platform_data; | ||
46 | struct v4l2_int_device *v4l2_int_device; | ||
47 | struct i2c_client *i2c_client; | ||
48 | struct v4l2_pix_format pix; | ||
49 | struct v4l2_fract timeperframe; | ||
50 | }; | ||
51 | |||
52 | /* list of image formats supported by TCM825X sensor */ | ||
53 | const static struct v4l2_fmtdesc tcm825x_formats[] = { | ||
54 | { | ||
55 | .description = "YUYV (YUV 4:2:2), packed", | ||
56 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
57 | }, { | ||
58 | /* Note: V4L2 defines RGB565 as: | ||
59 | * | ||
60 | * Byte 0 Byte 1 | ||
61 | * g2 g1 g0 r4 r3 r2 r1 r0 b4 b3 b2 b1 b0 g5 g4 g3 | ||
62 | * | ||
63 | * We interpret RGB565 as: | ||
64 | * | ||
65 | * Byte 0 Byte 1 | ||
66 | * g2 g1 g0 b4 b3 b2 b1 b0 r4 r3 r2 r1 r0 g5 g4 g3 | ||
67 | */ | ||
68 | .description = "RGB565, le", | ||
69 | .pixelformat = V4L2_PIX_FMT_RGB565, | ||
70 | }, | ||
71 | }; | ||
72 | |||
73 | #define TCM825X_NUM_CAPTURE_FORMATS ARRAY_SIZE(tcm825x_formats) | ||
74 | |||
75 | /* | ||
76 | * TCM825X register configuration for all combinations of pixel format and | ||
77 | * image size | ||
78 | */ | ||
79 | const static struct tcm825x_reg subqcif = { 0x20, TCM825X_PICSIZ }; | ||
80 | const static struct tcm825x_reg qcif = { 0x18, TCM825X_PICSIZ }; | ||
81 | const static struct tcm825x_reg cif = { 0x14, TCM825X_PICSIZ }; | ||
82 | const static struct tcm825x_reg qqvga = { 0x0c, TCM825X_PICSIZ }; | ||
83 | const static struct tcm825x_reg qvga = { 0x04, TCM825X_PICSIZ }; | ||
84 | const static struct tcm825x_reg vga = { 0x00, TCM825X_PICSIZ }; | ||
85 | |||
86 | const static struct tcm825x_reg yuv422 = { 0x00, TCM825X_PICFMT }; | ||
87 | const static struct tcm825x_reg rgb565 = { 0x02, TCM825X_PICFMT }; | ||
88 | |||
89 | /* Our own specific controls */ | ||
90 | #define V4L2_CID_ALC V4L2_CID_PRIVATE_BASE | ||
91 | #define V4L2_CID_H_EDGE_EN V4L2_CID_PRIVATE_BASE + 1 | ||
92 | #define V4L2_CID_V_EDGE_EN V4L2_CID_PRIVATE_BASE + 2 | ||
93 | #define V4L2_CID_LENS V4L2_CID_PRIVATE_BASE + 3 | ||
94 | #define V4L2_CID_MAX_EXPOSURE_TIME V4L2_CID_PRIVATE_BASE + 4 | ||
95 | #define V4L2_CID_LAST_PRIV V4L2_CID_MAX_EXPOSURE_TIME | ||
96 | |||
97 | /* Video controls */ | ||
98 | static struct vcontrol { | ||
99 | struct v4l2_queryctrl qc; | ||
100 | u16 reg; | ||
101 | u16 start_bit; | ||
102 | } video_control[] = { | ||
103 | { | ||
104 | { | ||
105 | .id = V4L2_CID_GAIN, | ||
106 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
107 | .name = "Gain", | ||
108 | .minimum = 0, | ||
109 | .maximum = 63, | ||
110 | .step = 1, | ||
111 | }, | ||
112 | .reg = TCM825X_AG, | ||
113 | .start_bit = 0, | ||
114 | }, | ||
115 | { | ||
116 | { | ||
117 | .id = V4L2_CID_RED_BALANCE, | ||
118 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
119 | .name = "Red Balance", | ||
120 | .minimum = 0, | ||
121 | .maximum = 255, | ||
122 | .step = 1, | ||
123 | }, | ||
124 | .reg = TCM825X_MRG, | ||
125 | .start_bit = 0, | ||
126 | }, | ||
127 | { | ||
128 | { | ||
129 | .id = V4L2_CID_BLUE_BALANCE, | ||
130 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
131 | .name = "Blue Balance", | ||
132 | .minimum = 0, | ||
133 | .maximum = 255, | ||
134 | .step = 1, | ||
135 | }, | ||
136 | .reg = TCM825X_MBG, | ||
137 | .start_bit = 0, | ||
138 | }, | ||
139 | { | ||
140 | { | ||
141 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | ||
142 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
143 | .name = "Auto White Balance", | ||
144 | .minimum = 0, | ||
145 | .maximum = 1, | ||
146 | .step = 0, | ||
147 | }, | ||
148 | .reg = TCM825X_AWBSW, | ||
149 | .start_bit = 7, | ||
150 | }, | ||
151 | { | ||
152 | { | ||
153 | .id = V4L2_CID_EXPOSURE, | ||
154 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
155 | .name = "Exposure Time", | ||
156 | .minimum = 0, | ||
157 | .maximum = 0x1fff, | ||
158 | .step = 1, | ||
159 | }, | ||
160 | .reg = TCM825X_ESRSPD_U, | ||
161 | .start_bit = 0, | ||
162 | }, | ||
163 | { | ||
164 | { | ||
165 | .id = V4L2_CID_HFLIP, | ||
166 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
167 | .name = "Mirror Image", | ||
168 | .minimum = 0, | ||
169 | .maximum = 1, | ||
170 | .step = 0, | ||
171 | }, | ||
172 | .reg = TCM825X_H_INV, | ||
173 | .start_bit = 6, | ||
174 | }, | ||
175 | { | ||
176 | { | ||
177 | .id = V4L2_CID_VFLIP, | ||
178 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
179 | .name = "Vertical Flip", | ||
180 | .minimum = 0, | ||
181 | .maximum = 1, | ||
182 | .step = 0, | ||
183 | }, | ||
184 | .reg = TCM825X_V_INV, | ||
185 | .start_bit = 7, | ||
186 | }, | ||
187 | /* Private controls */ | ||
188 | { | ||
189 | { | ||
190 | .id = V4L2_CID_ALC, | ||
191 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
192 | .name = "Auto Luminance Control", | ||
193 | .minimum = 0, | ||
194 | .maximum = 1, | ||
195 | .step = 0, | ||
196 | }, | ||
197 | .reg = TCM825X_ALCSW, | ||
198 | .start_bit = 7, | ||
199 | }, | ||
200 | { | ||
201 | { | ||
202 | .id = V4L2_CID_H_EDGE_EN, | ||
203 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
204 | .name = "Horizontal Edge Enhancement", | ||
205 | .minimum = 0, | ||
206 | .maximum = 0xff, | ||
207 | .step = 1, | ||
208 | }, | ||
209 | .reg = TCM825X_HDTG, | ||
210 | .start_bit = 0, | ||
211 | }, | ||
212 | { | ||
213 | { | ||
214 | .id = V4L2_CID_V_EDGE_EN, | ||
215 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
216 | .name = "Vertical Edge Enhancement", | ||
217 | .minimum = 0, | ||
218 | .maximum = 0xff, | ||
219 | .step = 1, | ||
220 | }, | ||
221 | .reg = TCM825X_VDTG, | ||
222 | .start_bit = 0, | ||
223 | }, | ||
224 | { | ||
225 | { | ||
226 | .id = V4L2_CID_LENS, | ||
227 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
228 | .name = "Lens Shading Compensation", | ||
229 | .minimum = 0, | ||
230 | .maximum = 0x3f, | ||
231 | .step = 1, | ||
232 | }, | ||
233 | .reg = TCM825X_LENS, | ||
234 | .start_bit = 0, | ||
235 | }, | ||
236 | { | ||
237 | { | ||
238 | .id = V4L2_CID_MAX_EXPOSURE_TIME, | ||
239 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
240 | .name = "Maximum Exposure Time", | ||
241 | .minimum = 0, | ||
242 | .maximum = 0x3, | ||
243 | .step = 1, | ||
244 | }, | ||
245 | .reg = TCM825X_ESRLIM, | ||
246 | .start_bit = 5, | ||
247 | }, | ||
248 | }; | ||
249 | |||
250 | |||
251 | const static struct tcm825x_reg *tcm825x_siz_reg[NUM_IMAGE_SIZES] = | ||
252 | { &subqcif, &qqvga, &qcif, &qvga, &cif, &vga }; | ||
253 | |||
254 | const static struct tcm825x_reg *tcm825x_fmt_reg[NUM_PIXEL_FORMATS] = | ||
255 | { &yuv422, &rgb565 }; | ||
256 | |||
257 | /* | ||
258 | * Read a value from a register in an TCM825X sensor device. The value is | ||
259 | * returned in 'val'. | ||
260 | * Returns zero if successful, or non-zero otherwise. | ||
261 | */ | ||
262 | static int tcm825x_read_reg(struct i2c_client *client, int reg) | ||
263 | { | ||
264 | int err; | ||
265 | struct i2c_msg msg[2]; | ||
266 | u8 reg_buf, data_buf = 0; | ||
267 | |||
268 | if (!client->adapter) | ||
269 | return -ENODEV; | ||
270 | |||
271 | msg[0].addr = client->addr; | ||
272 | msg[0].flags = 0; | ||
273 | msg[0].len = 1; | ||
274 | msg[0].buf = ®_buf; | ||
275 | msg[1].addr = client->addr; | ||
276 | msg[1].flags = I2C_M_RD; | ||
277 | msg[1].len = 1; | ||
278 | msg[1].buf = &data_buf; | ||
279 | |||
280 | reg_buf = reg; | ||
281 | |||
282 | err = i2c_transfer(client->adapter, msg, 2); | ||
283 | if (err < 0) | ||
284 | return err; | ||
285 | return data_buf; | ||
286 | } | ||
287 | |||
288 | /* | ||
289 | * Write a value to a register in an TCM825X sensor device. | ||
290 | * Returns zero if successful, or non-zero otherwise. | ||
291 | */ | ||
292 | static int tcm825x_write_reg(struct i2c_client *client, u8 reg, u8 val) | ||
293 | { | ||
294 | int err; | ||
295 | struct i2c_msg msg[1]; | ||
296 | unsigned char data[2]; | ||
297 | |||
298 | if (!client->adapter) | ||
299 | return -ENODEV; | ||
300 | |||
301 | msg->addr = client->addr; | ||
302 | msg->flags = 0; | ||
303 | msg->len = 2; | ||
304 | msg->buf = data; | ||
305 | data[0] = reg; | ||
306 | data[1] = val; | ||
307 | err = i2c_transfer(client->adapter, msg, 1); | ||
308 | if (err >= 0) | ||
309 | return 0; | ||
310 | return err; | ||
311 | } | ||
312 | |||
313 | static int __tcm825x_write_reg_mask(struct i2c_client *client, | ||
314 | u8 reg, u8 val, u8 mask) | ||
315 | { | ||
316 | int rc; | ||
317 | |||
318 | /* need to do read - modify - write */ | ||
319 | rc = tcm825x_read_reg(client, reg); | ||
320 | if (rc < 0) | ||
321 | return rc; | ||
322 | |||
323 | rc &= (~mask); /* Clear the masked bits */ | ||
324 | val &= mask; /* Enforce mask on value */ | ||
325 | val |= rc; | ||
326 | |||
327 | /* write the new value to the register */ | ||
328 | rc = tcm825x_write_reg(client, reg, val); | ||
329 | if (rc) | ||
330 | return rc; | ||
331 | |||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | #define tcm825x_write_reg_mask(client, regmask, val) \ | ||
336 | __tcm825x_write_reg_mask(client, TCM825X_ADDR((regmask)), val, \ | ||
337 | TCM825X_MASK((regmask))) | ||
338 | |||
339 | |||
340 | /* | ||
341 | * Initialize a list of TCM825X registers. | ||
342 | * The list of registers is terminated by the pair of values | ||
343 | * { TCM825X_REG_TERM, TCM825X_VAL_TERM }. | ||
344 | * Returns zero if successful, or non-zero otherwise. | ||
345 | */ | ||
346 | static int tcm825x_write_default_regs(struct i2c_client *client, | ||
347 | const struct tcm825x_reg *reglist) | ||
348 | { | ||
349 | int err; | ||
350 | const struct tcm825x_reg *next = reglist; | ||
351 | |||
352 | while (!((next->reg == TCM825X_REG_TERM) | ||
353 | && (next->val == TCM825X_VAL_TERM))) { | ||
354 | err = tcm825x_write_reg(client, next->reg, next->val); | ||
355 | if (err) { | ||
356 | dev_err(&client->dev, "register writing failed\n"); | ||
357 | return err; | ||
358 | } | ||
359 | next++; | ||
360 | } | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static struct vcontrol *find_vctrl(int id) | ||
366 | { | ||
367 | int i; | ||
368 | |||
369 | if (id < V4L2_CID_BASE) | ||
370 | return NULL; | ||
371 | |||
372 | for (i = 0; i < ARRAY_SIZE(video_control); i++) | ||
373 | if (video_control[i].qc.id == id) | ||
374 | return &video_control[i]; | ||
375 | |||
376 | return NULL; | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | * Find the best match for a requested image capture size. The best match | ||
381 | * is chosen as the nearest match that has the same number or fewer pixels | ||
382 | * as the requested size, or the smallest image size if the requested size | ||
383 | * has fewer pixels than the smallest image. | ||
384 | */ | ||
385 | static enum image_size tcm825x_find_size(struct v4l2_int_device *s, | ||
386 | unsigned int width, | ||
387 | unsigned int height) | ||
388 | { | ||
389 | enum image_size isize; | ||
390 | unsigned long pixels = width * height; | ||
391 | struct tcm825x_sensor *sensor = s->priv; | ||
392 | |||
393 | for (isize = subQCIF; isize < VGA; isize++) { | ||
394 | if (tcm825x_sizes[isize + 1].height | ||
395 | * tcm825x_sizes[isize + 1].width > pixels) { | ||
396 | dev_dbg(&sensor->i2c_client->dev, "size %d\n", isize); | ||
397 | |||
398 | return isize; | ||
399 | } | ||
400 | } | ||
401 | |||
402 | dev_dbg(&sensor->i2c_client->dev, "format default VGA\n"); | ||
403 | |||
404 | return VGA; | ||
405 | } | ||
406 | |||
407 | /* | ||
408 | * Configure the TCM825X for current image size, pixel format, and | ||
409 | * frame period. fper is the frame period (in seconds) expressed as a | ||
410 | * fraction. Returns zero if successful, or non-zero otherwise. The | ||
411 | * actual frame period is returned in fper. | ||
412 | */ | ||
413 | static int tcm825x_configure(struct v4l2_int_device *s) | ||
414 | { | ||
415 | struct tcm825x_sensor *sensor = s->priv; | ||
416 | struct v4l2_pix_format *pix = &sensor->pix; | ||
417 | enum image_size isize = tcm825x_find_size(s, pix->width, pix->height); | ||
418 | struct v4l2_fract *fper = &sensor->timeperframe; | ||
419 | enum pixel_format pfmt; | ||
420 | int err; | ||
421 | u32 tgt_fps; | ||
422 | u8 val; | ||
423 | |||
424 | /* common register initialization */ | ||
425 | err = tcm825x_write_default_regs( | ||
426 | sensor->i2c_client, sensor->platform_data->default_regs()); | ||
427 | if (err) | ||
428 | return err; | ||
429 | |||
430 | /* configure image size */ | ||
431 | val = tcm825x_siz_reg[isize]->val; | ||
432 | dev_dbg(&sensor->i2c_client->dev, | ||
433 | "configuring image size %d\n", isize); | ||
434 | err = tcm825x_write_reg_mask(sensor->i2c_client, | ||
435 | tcm825x_siz_reg[isize]->reg, val); | ||
436 | if (err) | ||
437 | return err; | ||
438 | |||
439 | /* configure pixel format */ | ||
440 | switch (pix->pixelformat) { | ||
441 | default: | ||
442 | case V4L2_PIX_FMT_RGB565: | ||
443 | pfmt = RGB565; | ||
444 | break; | ||
445 | case V4L2_PIX_FMT_UYVY: | ||
446 | pfmt = YUV422; | ||
447 | break; | ||
448 | } | ||
449 | |||
450 | dev_dbg(&sensor->i2c_client->dev, | ||
451 | "configuring pixel format %d\n", pfmt); | ||
452 | val = tcm825x_fmt_reg[pfmt]->val; | ||
453 | |||
454 | err = tcm825x_write_reg_mask(sensor->i2c_client, | ||
455 | tcm825x_fmt_reg[pfmt]->reg, val); | ||
456 | if (err) | ||
457 | return err; | ||
458 | |||
459 | /* | ||
460 | * For frame rate < 15, the FPS reg (addr 0x02, bit 7) must be | ||
461 | * set. Frame rate will be halved from the normal. | ||
462 | */ | ||
463 | tgt_fps = fper->denominator / fper->numerator; | ||
464 | if (tgt_fps <= HIGH_FPS_MODE_LOWER_LIMIT) { | ||
465 | val = tcm825x_read_reg(sensor->i2c_client, 0x02); | ||
466 | val |= 0x80; | ||
467 | tcm825x_write_reg(sensor->i2c_client, 0x02, val); | ||
468 | } | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static int ioctl_queryctrl(struct v4l2_int_device *s, | ||
474 | struct v4l2_queryctrl *qc) | ||
475 | { | ||
476 | struct vcontrol *control; | ||
477 | |||
478 | control = find_vctrl(qc->id); | ||
479 | |||
480 | if (control == NULL) | ||
481 | return -EINVAL; | ||
482 | |||
483 | *qc = control->qc; | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static int ioctl_g_ctrl(struct v4l2_int_device *s, | ||
489 | struct v4l2_control *vc) | ||
490 | { | ||
491 | struct tcm825x_sensor *sensor = s->priv; | ||
492 | struct i2c_client *client = sensor->i2c_client; | ||
493 | int val, r; | ||
494 | struct vcontrol *lvc; | ||
495 | |||
496 | /* exposure time is special, spread accross 2 registers */ | ||
497 | if (vc->id == V4L2_CID_EXPOSURE) { | ||
498 | int val_lower, val_upper; | ||
499 | |||
500 | val_upper = tcm825x_read_reg(client, | ||
501 | TCM825X_ADDR(TCM825X_ESRSPD_U)); | ||
502 | if (val_upper < 0) | ||
503 | return val_upper; | ||
504 | val_lower = tcm825x_read_reg(client, | ||
505 | TCM825X_ADDR(TCM825X_ESRSPD_L)); | ||
506 | if (val_lower < 0) | ||
507 | return val_lower; | ||
508 | |||
509 | vc->value = ((val_upper & 0x1f) << 8) | (val_lower); | ||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | lvc = find_vctrl(vc->id); | ||
514 | if (lvc == NULL) | ||
515 | return -EINVAL; | ||
516 | |||
517 | r = tcm825x_read_reg(client, TCM825X_ADDR(lvc->reg)); | ||
518 | if (r < 0) | ||
519 | return r; | ||
520 | val = r & TCM825X_MASK(lvc->reg); | ||
521 | val >>= lvc->start_bit; | ||
522 | |||
523 | if (val < 0) | ||
524 | return val; | ||
525 | |||
526 | vc->value = val; | ||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static int ioctl_s_ctrl(struct v4l2_int_device *s, | ||
531 | struct v4l2_control *vc) | ||
532 | { | ||
533 | struct tcm825x_sensor *sensor = s->priv; | ||
534 | struct i2c_client *client = sensor->i2c_client; | ||
535 | struct vcontrol *lvc; | ||
536 | int val = vc->value; | ||
537 | |||
538 | /* exposure time is special, spread accross 2 registers */ | ||
539 | if (vc->id == V4L2_CID_EXPOSURE) { | ||
540 | int val_lower, val_upper; | ||
541 | val_lower = val & TCM825X_MASK(TCM825X_ESRSPD_L); | ||
542 | val_upper = (val >> 8) & TCM825X_MASK(TCM825X_ESRSPD_U); | ||
543 | |||
544 | if (tcm825x_write_reg_mask(client, | ||
545 | TCM825X_ESRSPD_U, val_upper)) | ||
546 | return -EIO; | ||
547 | |||
548 | if (tcm825x_write_reg_mask(client, | ||
549 | TCM825X_ESRSPD_L, val_lower)) | ||
550 | return -EIO; | ||
551 | |||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | lvc = find_vctrl(vc->id); | ||
556 | if (lvc == NULL) | ||
557 | return -EINVAL; | ||
558 | |||
559 | val = val << lvc->start_bit; | ||
560 | if (tcm825x_write_reg_mask(client, lvc->reg, val)) | ||
561 | return -EIO; | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static int ioctl_enum_fmt_cap(struct v4l2_int_device *s, | ||
567 | struct v4l2_fmtdesc *fmt) | ||
568 | { | ||
569 | int index = fmt->index; | ||
570 | |||
571 | switch (fmt->type) { | ||
572 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
573 | if (index >= TCM825X_NUM_CAPTURE_FORMATS) | ||
574 | return -EINVAL; | ||
575 | break; | ||
576 | |||
577 | default: | ||
578 | return -EINVAL; | ||
579 | } | ||
580 | |||
581 | fmt->flags = tcm825x_formats[index].flags; | ||
582 | strlcpy(fmt->description, tcm825x_formats[index].description, | ||
583 | sizeof(fmt->description)); | ||
584 | fmt->pixelformat = tcm825x_formats[index].pixelformat; | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | static int ioctl_try_fmt_cap(struct v4l2_int_device *s, | ||
590 | struct v4l2_format *f) | ||
591 | { | ||
592 | struct tcm825x_sensor *sensor = s->priv; | ||
593 | enum image_size isize; | ||
594 | int ifmt; | ||
595 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
596 | |||
597 | isize = tcm825x_find_size(s, pix->width, pix->height); | ||
598 | dev_dbg(&sensor->i2c_client->dev, "isize = %d num_capture = %lu\n", | ||
599 | isize, (unsigned long)TCM825X_NUM_CAPTURE_FORMATS); | ||
600 | |||
601 | pix->width = tcm825x_sizes[isize].width; | ||
602 | pix->height = tcm825x_sizes[isize].height; | ||
603 | |||
604 | for (ifmt = 0; ifmt < TCM825X_NUM_CAPTURE_FORMATS; ifmt++) | ||
605 | if (pix->pixelformat == tcm825x_formats[ifmt].pixelformat) | ||
606 | break; | ||
607 | |||
608 | if (ifmt == TCM825X_NUM_CAPTURE_FORMATS) | ||
609 | ifmt = 0; /* Default = YUV 4:2:2 */ | ||
610 | |||
611 | pix->pixelformat = tcm825x_formats[ifmt].pixelformat; | ||
612 | pix->field = V4L2_FIELD_NONE; | ||
613 | pix->bytesperline = pix->width * TCM825X_BYTES_PER_PIXEL; | ||
614 | pix->sizeimage = pix->bytesperline * pix->height; | ||
615 | pix->priv = 0; | ||
616 | dev_dbg(&sensor->i2c_client->dev, "format = 0x%08x\n", | ||
617 | pix->pixelformat); | ||
618 | |||
619 | switch (pix->pixelformat) { | ||
620 | case V4L2_PIX_FMT_UYVY: | ||
621 | default: | ||
622 | pix->colorspace = V4L2_COLORSPACE_JPEG; | ||
623 | break; | ||
624 | case V4L2_PIX_FMT_RGB565: | ||
625 | pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
626 | break; | ||
627 | } | ||
628 | |||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | static int ioctl_s_fmt_cap(struct v4l2_int_device *s, | ||
633 | struct v4l2_format *f) | ||
634 | { | ||
635 | struct tcm825x_sensor *sensor = s->priv; | ||
636 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
637 | int rval; | ||
638 | |||
639 | rval = ioctl_try_fmt_cap(s, f); | ||
640 | if (rval) | ||
641 | return rval; | ||
642 | |||
643 | rval = tcm825x_configure(s); | ||
644 | |||
645 | sensor->pix = *pix; | ||
646 | |||
647 | return rval; | ||
648 | } | ||
649 | |||
650 | static int ioctl_g_fmt_cap(struct v4l2_int_device *s, | ||
651 | struct v4l2_format *f) | ||
652 | { | ||
653 | struct tcm825x_sensor *sensor = s->priv; | ||
654 | |||
655 | f->fmt.pix = sensor->pix; | ||
656 | |||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | static int ioctl_g_parm(struct v4l2_int_device *s, | ||
661 | struct v4l2_streamparm *a) | ||
662 | { | ||
663 | struct tcm825x_sensor *sensor = s->priv; | ||
664 | struct v4l2_captureparm *cparm = &a->parm.capture; | ||
665 | |||
666 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
667 | return -EINVAL; | ||
668 | |||
669 | memset(a, 0, sizeof(*a)); | ||
670 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
671 | |||
672 | cparm->capability = V4L2_CAP_TIMEPERFRAME; | ||
673 | cparm->timeperframe = sensor->timeperframe; | ||
674 | |||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | static int ioctl_s_parm(struct v4l2_int_device *s, | ||
679 | struct v4l2_streamparm *a) | ||
680 | { | ||
681 | struct tcm825x_sensor *sensor = s->priv; | ||
682 | struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe; | ||
683 | u32 tgt_fps; /* target frames per secound */ | ||
684 | int rval; | ||
685 | |||
686 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
687 | return -EINVAL; | ||
688 | |||
689 | if ((timeperframe->numerator == 0) | ||
690 | || (timeperframe->denominator == 0)) { | ||
691 | timeperframe->denominator = DEFAULT_FPS; | ||
692 | timeperframe->numerator = 1; | ||
693 | } | ||
694 | |||
695 | tgt_fps = timeperframe->denominator / timeperframe->numerator; | ||
696 | |||
697 | if (tgt_fps > MAX_FPS) { | ||
698 | timeperframe->denominator = MAX_FPS; | ||
699 | timeperframe->numerator = 1; | ||
700 | } else if (tgt_fps < MIN_FPS) { | ||
701 | timeperframe->denominator = MIN_FPS; | ||
702 | timeperframe->numerator = 1; | ||
703 | } | ||
704 | |||
705 | sensor->timeperframe = *timeperframe; | ||
706 | |||
707 | rval = tcm825x_configure(s); | ||
708 | |||
709 | return rval; | ||
710 | } | ||
711 | |||
712 | static int ioctl_s_power(struct v4l2_int_device *s, int on) | ||
713 | { | ||
714 | struct tcm825x_sensor *sensor = s->priv; | ||
715 | |||
716 | return sensor->platform_data->power_set(on); | ||
717 | } | ||
718 | |||
719 | /* | ||
720 | * Given the image capture format in pix, the nominal frame period in | ||
721 | * timeperframe, calculate the required xclk frequency. | ||
722 | * | ||
723 | * TCM825X input frequency characteristics are: | ||
724 | * Minimum 11.9 MHz, Typical 24.57 MHz and maximum 25/27 MHz | ||
725 | */ | ||
726 | |||
727 | static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) | ||
728 | { | ||
729 | struct tcm825x_sensor *sensor = s->priv; | ||
730 | struct v4l2_fract *timeperframe = &sensor->timeperframe; | ||
731 | u32 tgt_xclk; /* target xclk */ | ||
732 | u32 tgt_fps; /* target frames per secound */ | ||
733 | int rval; | ||
734 | |||
735 | rval = sensor->platform_data->ifparm(p); | ||
736 | if (rval) | ||
737 | return rval; | ||
738 | |||
739 | tgt_fps = timeperframe->denominator / timeperframe->numerator; | ||
740 | |||
741 | tgt_xclk = (tgt_fps <= HIGH_FPS_MODE_LOWER_LIMIT) ? | ||
742 | (2457 * tgt_fps) / MAX_HALF_FPS : | ||
743 | (2457 * tgt_fps) / MAX_FPS; | ||
744 | tgt_xclk *= 10000; | ||
745 | |||
746 | tgt_xclk = min(tgt_xclk, (u32)TCM825X_XCLK_MAX); | ||
747 | tgt_xclk = max(tgt_xclk, (u32)TCM825X_XCLK_MIN); | ||
748 | |||
749 | p->u.bt656.clock_curr = tgt_xclk; | ||
750 | |||
751 | return 0; | ||
752 | } | ||
753 | |||
754 | static int ioctl_g_needs_reset(struct v4l2_int_device *s, void *buf) | ||
755 | { | ||
756 | struct tcm825x_sensor *sensor = s->priv; | ||
757 | |||
758 | return sensor->platform_data->needs_reset(s, buf, &sensor->pix); | ||
759 | } | ||
760 | |||
761 | static int ioctl_reset(struct v4l2_int_device *s) | ||
762 | { | ||
763 | return -EBUSY; | ||
764 | } | ||
765 | |||
766 | static int ioctl_init(struct v4l2_int_device *s) | ||
767 | { | ||
768 | return tcm825x_configure(s); | ||
769 | } | ||
770 | |||
771 | static int ioctl_dev_exit(struct v4l2_int_device *s) | ||
772 | { | ||
773 | return 0; | ||
774 | } | ||
775 | |||
776 | static int ioctl_dev_init(struct v4l2_int_device *s) | ||
777 | { | ||
778 | struct tcm825x_sensor *sensor = s->priv; | ||
779 | int r; | ||
780 | |||
781 | r = tcm825x_read_reg(sensor->i2c_client, 0x01); | ||
782 | if (r < 0) | ||
783 | return r; | ||
784 | if (r == 0) { | ||
785 | dev_err(&sensor->i2c_client->dev, "device not detected\n"); | ||
786 | return -EIO; | ||
787 | } | ||
788 | return 0; | ||
789 | } | ||
790 | |||
791 | static struct v4l2_int_ioctl_desc tcm825x_ioctl_desc[] = { | ||
792 | { vidioc_int_dev_init_num, | ||
793 | (v4l2_int_ioctl_func *)ioctl_dev_init }, | ||
794 | { vidioc_int_dev_exit_num, | ||
795 | (v4l2_int_ioctl_func *)ioctl_dev_exit }, | ||
796 | { vidioc_int_s_power_num, | ||
797 | (v4l2_int_ioctl_func *)ioctl_s_power }, | ||
798 | { vidioc_int_g_ifparm_num, | ||
799 | (v4l2_int_ioctl_func *)ioctl_g_ifparm }, | ||
800 | { vidioc_int_g_needs_reset_num, | ||
801 | (v4l2_int_ioctl_func *)ioctl_g_needs_reset }, | ||
802 | { vidioc_int_reset_num, | ||
803 | (v4l2_int_ioctl_func *)ioctl_reset }, | ||
804 | { vidioc_int_init_num, | ||
805 | (v4l2_int_ioctl_func *)ioctl_init }, | ||
806 | { vidioc_int_enum_fmt_cap_num, | ||
807 | (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap }, | ||
808 | { vidioc_int_try_fmt_cap_num, | ||
809 | (v4l2_int_ioctl_func *)ioctl_try_fmt_cap }, | ||
810 | { vidioc_int_g_fmt_cap_num, | ||
811 | (v4l2_int_ioctl_func *)ioctl_g_fmt_cap }, | ||
812 | { vidioc_int_s_fmt_cap_num, | ||
813 | (v4l2_int_ioctl_func *)ioctl_s_fmt_cap }, | ||
814 | { vidioc_int_g_parm_num, | ||
815 | (v4l2_int_ioctl_func *)ioctl_g_parm }, | ||
816 | { vidioc_int_s_parm_num, | ||
817 | (v4l2_int_ioctl_func *)ioctl_s_parm }, | ||
818 | { vidioc_int_queryctrl_num, | ||
819 | (v4l2_int_ioctl_func *)ioctl_queryctrl }, | ||
820 | { vidioc_int_g_ctrl_num, | ||
821 | (v4l2_int_ioctl_func *)ioctl_g_ctrl }, | ||
822 | { vidioc_int_s_ctrl_num, | ||
823 | (v4l2_int_ioctl_func *)ioctl_s_ctrl }, | ||
824 | }; | ||
825 | |||
826 | static struct v4l2_int_slave tcm825x_slave = { | ||
827 | .ioctls = tcm825x_ioctl_desc, | ||
828 | .num_ioctls = ARRAY_SIZE(tcm825x_ioctl_desc), | ||
829 | }; | ||
830 | |||
831 | static struct tcm825x_sensor tcm825x; | ||
832 | |||
833 | static struct v4l2_int_device tcm825x_int_device = { | ||
834 | .module = THIS_MODULE, | ||
835 | .name = TCM825X_NAME, | ||
836 | .priv = &tcm825x, | ||
837 | .type = v4l2_int_type_slave, | ||
838 | .u = { | ||
839 | .slave = &tcm825x_slave, | ||
840 | }, | ||
841 | }; | ||
842 | |||
843 | static int tcm825x_probe(struct i2c_client *client) | ||
844 | { | ||
845 | struct tcm825x_sensor *sensor = &tcm825x; | ||
846 | int rval; | ||
847 | |||
848 | if (i2c_get_clientdata(client)) | ||
849 | return -EBUSY; | ||
850 | |||
851 | sensor->platform_data = client->dev.platform_data; | ||
852 | |||
853 | if (sensor->platform_data == NULL | ||
854 | && !sensor->platform_data->is_okay()) | ||
855 | return -ENODEV; | ||
856 | |||
857 | sensor->v4l2_int_device = &tcm825x_int_device; | ||
858 | |||
859 | sensor->i2c_client = client; | ||
860 | i2c_set_clientdata(client, sensor); | ||
861 | |||
862 | /* Make the default capture format QVGA RGB565 */ | ||
863 | sensor->pix.width = tcm825x_sizes[QVGA].width; | ||
864 | sensor->pix.height = tcm825x_sizes[QVGA].height; | ||
865 | sensor->pix.pixelformat = V4L2_PIX_FMT_RGB565; | ||
866 | |||
867 | rval = v4l2_int_device_register(sensor->v4l2_int_device); | ||
868 | if (rval) | ||
869 | i2c_set_clientdata(client, NULL); | ||
870 | |||
871 | return rval; | ||
872 | } | ||
873 | |||
874 | static int __exit tcm825x_remove(struct i2c_client *client) | ||
875 | { | ||
876 | struct tcm825x_sensor *sensor = i2c_get_clientdata(client); | ||
877 | |||
878 | if (!client->adapter) | ||
879 | return -ENODEV; /* our client isn't attached */ | ||
880 | |||
881 | v4l2_int_device_unregister(sensor->v4l2_int_device); | ||
882 | i2c_set_clientdata(client, NULL); | ||
883 | |||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | static struct i2c_driver tcm825x_i2c_driver = { | ||
888 | .driver = { | ||
889 | .name = TCM825X_NAME, | ||
890 | }, | ||
891 | .probe = tcm825x_probe, | ||
892 | .remove = __exit_p(tcm825x_remove), | ||
893 | }; | ||
894 | |||
895 | static struct tcm825x_sensor tcm825x = { | ||
896 | .timeperframe = { | ||
897 | .numerator = 1, | ||
898 | .denominator = DEFAULT_FPS, | ||
899 | }, | ||
900 | }; | ||
901 | |||
902 | static int __init tcm825x_init(void) | ||
903 | { | ||
904 | int rval; | ||
905 | |||
906 | rval = i2c_add_driver(&tcm825x_i2c_driver); | ||
907 | if (rval) | ||
908 | printk(KERN_INFO "%s: failed registering " TCM825X_NAME "\n", | ||
909 | __FUNCTION__); | ||
910 | |||
911 | return rval; | ||
912 | } | ||
913 | |||
914 | static void __exit tcm825x_exit(void) | ||
915 | { | ||
916 | i2c_del_driver(&tcm825x_i2c_driver); | ||
917 | } | ||
918 | |||
919 | /* | ||
920 | * FIXME: Menelaus isn't ready (?) at module_init stage, so use | ||
921 | * late_initcall for now. | ||
922 | */ | ||
923 | late_initcall(tcm825x_init); | ||
924 | module_exit(tcm825x_exit); | ||
925 | |||
926 | MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>"); | ||
927 | MODULE_DESCRIPTION("TCM825x camera sensor driver"); | ||
928 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/tcm825x.h b/drivers/media/video/tcm825x.h new file mode 100644 index 000000000000..966765b66b3a --- /dev/null +++ b/drivers/media/video/tcm825x.h | |||
@@ -0,0 +1,199 @@ | |||
1 | /* | ||
2 | * drivers/media/video/tcm825x.h | ||
3 | * | ||
4 | * Register definitions for the TCM825X CameraChip. | ||
5 | * | ||
6 | * Author: David Cohen (david.cohen@indt.org.br) | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public License | ||
9 | * version 2. This program is licensed "as is" without any warranty of any | ||
10 | * kind, whether express or implied. | ||
11 | * | ||
12 | * This file was based on ov9640.h from MontaVista | ||
13 | */ | ||
14 | |||
15 | #ifndef TCM825X_H | ||
16 | #define TCM825X_H | ||
17 | |||
18 | #include <linux/videodev2.h> | ||
19 | |||
20 | #include <media/v4l2-int-device.h> | ||
21 | |||
22 | #define TCM825X_NAME "tcm825x" | ||
23 | |||
24 | #define TCM825X_MASK(x) x & 0x00ff | ||
25 | #define TCM825X_ADDR(x) (x & 0xff00) >> 8 | ||
26 | |||
27 | /* The TCM825X I2C sensor chip has a fixed slave address of 0x3d. */ | ||
28 | #define TCM825X_I2C_ADDR 0x3d | ||
29 | |||
30 | /* | ||
31 | * define register offsets for the TCM825X sensor chip | ||
32 | * OFFSET(8 bits) + MASK(8 bits) | ||
33 | * MASK bit 4 and 3 are used when the register uses more than one address | ||
34 | */ | ||
35 | #define TCM825X_FPS 0x0280 | ||
36 | #define TCM825X_ACF 0x0240 | ||
37 | #define TCM825X_DOUTBUF 0x020C | ||
38 | #define TCM825X_DCLKP 0x0202 | ||
39 | #define TCM825X_ACFDET 0x0201 | ||
40 | #define TCM825X_DOUTSW 0x0380 | ||
41 | #define TCM825X_DATAHZ 0x0340 | ||
42 | #define TCM825X_PICSIZ 0x033c | ||
43 | #define TCM825X_PICFMT 0x0302 | ||
44 | #define TCM825X_V_INV 0x0480 | ||
45 | #define TCM825X_H_INV 0x0440 | ||
46 | #define TCM825X_ESRLSW 0x0430 | ||
47 | #define TCM825X_V_LENGTH 0x040F | ||
48 | #define TCM825X_ALCSW 0x0580 | ||
49 | #define TCM825X_ESRLIM 0x0560 | ||
50 | #define TCM825X_ESRSPD_U 0x051F | ||
51 | #define TCM825X_ESRSPD_L 0x06FF | ||
52 | #define TCM825X_AG 0x07FF | ||
53 | #define TCM825X_ESRSPD2 0x06FF | ||
54 | #define TCM825X_ALCMODE 0x0830 | ||
55 | #define TCM825X_ALCH 0x080F | ||
56 | #define TCM825X_ALCL 0x09FF | ||
57 | #define TCM825X_AWBSW 0x0A80 | ||
58 | #define TCM825X_MRG 0x0BFF | ||
59 | #define TCM825X_MBG 0x0CFF | ||
60 | #define TCM825X_GAMSW 0x0D80 | ||
61 | #define TCM825X_HDTG 0x0EFF | ||
62 | #define TCM825X_VDTG 0x0FFF | ||
63 | #define TCM825X_HDTCORE 0x10F0 | ||
64 | #define TCM825X_VDTCORE 0x100F | ||
65 | #define TCM825X_CONT 0x11FF | ||
66 | #define TCM825X_BRIGHT 0x12FF | ||
67 | #define TCM825X_VHUE 0x137F | ||
68 | #define TCM825X_UHUE 0x147F | ||
69 | #define TCM825X_VGAIN 0x153F | ||
70 | #define TCM825X_UGAIN 0x163F | ||
71 | #define TCM825X_UVCORE 0x170F | ||
72 | #define TCM825X_SATU 0x187F | ||
73 | #define TCM825X_MHMODE 0x1980 | ||
74 | #define TCM825X_MHLPFSEL 0x1940 | ||
75 | #define TCM825X_YMODE 0x1930 | ||
76 | #define TCM825X_MIXHG 0x1907 | ||
77 | #define TCM825X_LENS 0x1A3F | ||
78 | #define TCM825X_AGLIM 0x1BE0 | ||
79 | #define TCM825X_LENSRPOL 0x1B10 | ||
80 | #define TCM825X_LENSRGAIN 0x1B0F | ||
81 | #define TCM825X_ES100S 0x1CFF | ||
82 | #define TCM825X_ES120S 0x1DFF | ||
83 | #define TCM825X_DMASK 0x1EC0 | ||
84 | #define TCM825X_CODESW 0x1E20 | ||
85 | #define TCM825X_CODESEL 0x1E10 | ||
86 | #define TCM825X_TESPIC 0x1E04 | ||
87 | #define TCM825X_PICSEL 0x1E03 | ||
88 | #define TCM825X_HNUM 0x20FF | ||
89 | #define TCM825X_VOUTPH 0x287F | ||
90 | #define TCM825X_ESROUT 0x327F | ||
91 | #define TCM825X_ESROUT2 0x33FF | ||
92 | #define TCM825X_AGOUT 0x34FF | ||
93 | #define TCM825X_DGOUT 0x353F | ||
94 | #define TCM825X_AGSLOW1 0x39C0 | ||
95 | #define TCM825X_FLLSMODE 0x3930 | ||
96 | #define TCM825X_FLLSLIM 0x390F | ||
97 | #define TCM825X_DETSEL 0x3AF0 | ||
98 | #define TCM825X_ACDETNC 0x3A0F | ||
99 | #define TCM825X_AGSLOW2 0x3BC0 | ||
100 | #define TCM825X_DG 0x3B3F | ||
101 | #define TCM825X_REJHLEV 0x3CFF | ||
102 | #define TCM825X_ALCLOCK 0x3D80 | ||
103 | #define TCM825X_FPSLNKSW 0x3D40 | ||
104 | #define TCM825X_ALCSPD 0x3D30 | ||
105 | #define TCM825X_REJH 0x3D03 | ||
106 | #define TCM825X_SHESRSW 0x3E80 | ||
107 | #define TCM825X_ESLIMSEL 0x3E40 | ||
108 | #define TCM825X_SHESRSPD 0x3E30 | ||
109 | #define TCM825X_ELSTEP 0x3E0C | ||
110 | #define TCM825X_ELSTART 0x3E03 | ||
111 | #define TCM825X_AGMIN 0x3FFF | ||
112 | #define TCM825X_PREGRG 0x423F | ||
113 | #define TCM825X_PREGBG 0x433F | ||
114 | #define TCM825X_PRERG 0x443F | ||
115 | #define TCM825X_PREBG 0x453F | ||
116 | #define TCM825X_MSKBR 0x477F | ||
117 | #define TCM825X_MSKGR 0x487F | ||
118 | #define TCM825X_MSKRB 0x497F | ||
119 | #define TCM825X_MSKGB 0x4A7F | ||
120 | #define TCM825X_MSKRG 0x4B7F | ||
121 | #define TCM825X_MSKBG 0x4C7F | ||
122 | #define TCM825X_HDTCSW 0x4D80 | ||
123 | #define TCM825X_VDTCSW 0x4D40 | ||
124 | #define TCM825X_DTCYL 0x4D3F | ||
125 | #define TCM825X_HDTPSW 0x4E80 | ||
126 | #define TCM825X_VDTPSW 0x4E40 | ||
127 | #define TCM825X_DTCGAIN 0x4E3F | ||
128 | #define TCM825X_DTLLIMSW 0x4F10 | ||
129 | #define TCM825X_DTLYLIM 0x4F0F | ||
130 | #define TCM825X_YLCUTLMSK 0x5080 | ||
131 | #define TCM825X_YLCUTL 0x503F | ||
132 | #define TCM825X_YLCUTHMSK 0x5180 | ||
133 | #define TCM825X_YLCUTH 0x513F | ||
134 | #define TCM825X_UVSKNC 0x527F | ||
135 | #define TCM825X_UVLJ 0x537F | ||
136 | #define TCM825X_WBGMIN 0x54FF | ||
137 | #define TCM825X_WBGMAX 0x55FF | ||
138 | #define TCM825X_WBSPDUP 0x5603 | ||
139 | #define TCM825X_ALLAREA 0x5820 | ||
140 | #define TCM825X_WBLOCK 0x5810 | ||
141 | #define TCM825X_WB2SP 0x580F | ||
142 | #define TCM825X_KIZUSW 0x5920 | ||
143 | #define TCM825X_PBRSW 0x5910 | ||
144 | #define TCM825X_ABCSW 0x5903 | ||
145 | #define TCM825X_PBDLV 0x5AFF | ||
146 | #define TCM825X_PBC1LV 0x5BFF | ||
147 | |||
148 | #define TCM825X_NUM_REGS (TCM825X_ADDR(TCM825X_PBC1LV) + 1) | ||
149 | |||
150 | #define TCM825X_BYTES_PER_PIXEL 2 | ||
151 | |||
152 | #define TCM825X_REG_TERM 0xff /* terminating list entry for reg */ | ||
153 | #define TCM825X_VAL_TERM 0xff /* terminating list entry for val */ | ||
154 | |||
155 | /* define a structure for tcm825x register initialization values */ | ||
156 | struct tcm825x_reg { | ||
157 | u8 val; | ||
158 | u16 reg; | ||
159 | }; | ||
160 | |||
161 | enum image_size { subQCIF = 0, QQVGA, QCIF, QVGA, CIF, VGA }; | ||
162 | enum pixel_format { YUV422 = 0, RGB565 }; | ||
163 | #define NUM_IMAGE_SIZES 6 | ||
164 | #define NUM_PIXEL_FORMATS 2 | ||
165 | |||
166 | #define TCM825X_XCLK_MIN 11900000 | ||
167 | #define TCM825X_XCLK_MAX 25000000 | ||
168 | |||
169 | struct capture_size { | ||
170 | unsigned long width; | ||
171 | unsigned long height; | ||
172 | }; | ||
173 | |||
174 | struct tcm825x_platform_data { | ||
175 | /* Is the sensor usable? Doesn't yet mean it's there, but you | ||
176 | * can try! */ | ||
177 | int (*is_okay)(void); | ||
178 | /* Set power state, zero is off, non-zero is on. */ | ||
179 | int (*power_set)(int power); | ||
180 | /* Default registers written after power-on or reset. */ | ||
181 | const struct tcm825x_reg *(*default_regs)(void); | ||
182 | int (*needs_reset)(struct v4l2_int_device *s, void *buf, | ||
183 | struct v4l2_pix_format *fmt); | ||
184 | int (*ifparm)(struct v4l2_ifparm *p); | ||
185 | }; | ||
186 | |||
187 | /* Array of image sizes supported by TCM825X. These must be ordered from | ||
188 | * smallest image size to largest. | ||
189 | */ | ||
190 | const static struct capture_size tcm825x_sizes[] = { | ||
191 | { 128, 96 }, /* subQCIF */ | ||
192 | { 160, 120 }, /* QQVGA */ | ||
193 | { 176, 144 }, /* QCIF */ | ||
194 | { 320, 240 }, /* QVGA */ | ||
195 | { 352, 288 }, /* CIF */ | ||
196 | { 640, 480 }, /* VGA */ | ||
197 | }; | ||
198 | |||
199 | #endif /* ifndef TCM825X_H */ | ||
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 59cff5a3c59e..0e5cf459d3ed 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c | |||
@@ -16,21 +16,37 @@ | |||
16 | You should have received a copy of the GNU General Public License | 16 | You should have received a copy of the GNU General Public License |
17 | along with this program; if not, write to the Free Software | 17 | along with this program; if not, write to the Free Software |
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 | |||
20 | This "tda8290" module was split apart from the original "tuner" module. | ||
19 | */ | 21 | */ |
20 | 22 | ||
21 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
22 | #include <linux/videodev.h> | ||
23 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
24 | #include "tuner-driver.h" | 25 | #include <linux/videodev.h> |
26 | #include "tuner-i2c.h" | ||
27 | #include "tda8290.h" | ||
28 | |||
29 | static int debug = 0; | ||
30 | module_param(debug, int, 0644); | ||
31 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
32 | |||
33 | #define PREFIX "tda8290 " | ||
25 | 34 | ||
26 | /* ---------------------------------------------------------------------- */ | 35 | /* ---------------------------------------------------------------------- */ |
27 | 36 | ||
28 | struct tda8290_priv { | 37 | struct tda8290_priv { |
38 | struct tuner_i2c_props i2c_props; | ||
39 | |||
29 | unsigned char tda8290_easy_mode; | 40 | unsigned char tda8290_easy_mode; |
30 | unsigned char tda827x_lpsel; | 41 | unsigned char tda827x_lpsel; |
31 | unsigned char tda827x_addr; | 42 | unsigned char tda827x_addr; |
32 | unsigned char tda827x_ver; | 43 | unsigned char tda827x_ver; |
33 | unsigned int sgIF; | 44 | unsigned int sgIF; |
45 | |||
46 | u32 frequency; | ||
47 | |||
48 | unsigned int *lna_cfg; | ||
49 | int (*tuner_callback) (void *dev, int command,int arg); | ||
34 | }; | 50 | }; |
35 | 51 | ||
36 | /* ---------------------------------------------------------------------- */ | 52 | /* ---------------------------------------------------------------------- */ |
@@ -79,20 +95,21 @@ static struct tda827x_data tda827x_analog[] = { | |||
79 | { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} /* End */ | 95 | { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} /* End */ |
80 | }; | 96 | }; |
81 | 97 | ||
82 | static void tda827x_tune(struct i2c_client *c, u16 ifc, unsigned int freq) | 98 | static void tda827x_set_analog_params(struct dvb_frontend *fe, |
99 | struct analog_parameters *params) | ||
83 | { | 100 | { |
84 | unsigned char tuner_reg[8]; | 101 | unsigned char tuner_reg[8]; |
85 | unsigned char reg2[2]; | 102 | unsigned char reg2[2]; |
86 | u32 N; | 103 | u32 N; |
87 | int i; | 104 | int i; |
88 | struct tuner *t = i2c_get_clientdata(c); | 105 | struct tda8290_priv *priv = fe->tuner_priv; |
89 | struct tda8290_priv *priv = t->priv; | ||
90 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0}; | 106 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0}; |
107 | unsigned int freq = params->frequency; | ||
91 | 108 | ||
92 | if (t->mode == V4L2_TUNER_RADIO) | 109 | if (params->mode == V4L2_TUNER_RADIO) |
93 | freq = freq / 1000; | 110 | freq = freq / 1000; |
94 | 111 | ||
95 | N = freq + ifc; | 112 | N = freq + priv->sgIF; |
96 | i = 0; | 113 | i = 0; |
97 | while (tda827x_analog[i].lomax < N) { | 114 | while (tda827x_analog[i].lomax < N) { |
98 | if(tda827x_analog[i + 1].lomax == 0) | 115 | if(tda827x_analog[i + 1].lomax == 0) |
@@ -114,54 +131,53 @@ static void tda827x_tune(struct i2c_client *c, u16 ifc, unsigned int freq) | |||
114 | 131 | ||
115 | msg.buf = tuner_reg; | 132 | msg.buf = tuner_reg; |
116 | msg.len = 8; | 133 | msg.len = 8; |
117 | i2c_transfer(c->adapter, &msg, 1); | 134 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
118 | 135 | ||
119 | msg.buf= reg2; | 136 | msg.buf= reg2; |
120 | msg.len = 2; | 137 | msg.len = 2; |
121 | reg2[0] = 0x80; | 138 | reg2[0] = 0x80; |
122 | reg2[1] = 0; | 139 | reg2[1] = 0; |
123 | i2c_transfer(c->adapter, &msg, 1); | 140 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
124 | 141 | ||
125 | reg2[0] = 0x60; | 142 | reg2[0] = 0x60; |
126 | reg2[1] = 0xbf; | 143 | reg2[1] = 0xbf; |
127 | i2c_transfer(c->adapter, &msg, 1); | 144 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
128 | 145 | ||
129 | reg2[0] = 0x30; | 146 | reg2[0] = 0x30; |
130 | reg2[1] = tuner_reg[4] + 0x80; | 147 | reg2[1] = tuner_reg[4] + 0x80; |
131 | i2c_transfer(c->adapter, &msg, 1); | 148 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
132 | 149 | ||
133 | msleep(1); | 150 | msleep(1); |
134 | reg2[0] = 0x30; | 151 | reg2[0] = 0x30; |
135 | reg2[1] = tuner_reg[4] + 4; | 152 | reg2[1] = tuner_reg[4] + 4; |
136 | i2c_transfer(c->adapter, &msg, 1); | 153 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
137 | 154 | ||
138 | msleep(1); | 155 | msleep(1); |
139 | reg2[0] = 0x30; | 156 | reg2[0] = 0x30; |
140 | reg2[1] = tuner_reg[4]; | 157 | reg2[1] = tuner_reg[4]; |
141 | i2c_transfer(c->adapter, &msg, 1); | 158 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
142 | 159 | ||
143 | msleep(550); | 160 | msleep(550); |
144 | reg2[0] = 0x30; | 161 | reg2[0] = 0x30; |
145 | reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_analog[i].cp ; | 162 | reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_analog[i].cp ; |
146 | i2c_transfer(c->adapter, &msg, 1); | 163 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
147 | 164 | ||
148 | reg2[0] = 0x60; | 165 | reg2[0] = 0x60; |
149 | reg2[1] = 0x3f; | 166 | reg2[1] = 0x3f; |
150 | i2c_transfer(c->adapter, &msg, 1); | 167 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
151 | 168 | ||
152 | reg2[0] = 0x80; | 169 | reg2[0] = 0x80; |
153 | reg2[1] = 0x08; // Vsync en | 170 | reg2[1] = 0x08; // Vsync en |
154 | i2c_transfer(c->adapter, &msg, 1); | 171 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
155 | } | 172 | } |
156 | 173 | ||
157 | static void tda827x_agcf(struct i2c_client *c) | 174 | static void tda827x_agcf(struct dvb_frontend *fe) |
158 | { | 175 | { |
159 | struct tuner *t = i2c_get_clientdata(c); | 176 | struct tda8290_priv *priv = fe->tuner_priv; |
160 | struct tda8290_priv *priv = t->priv; | ||
161 | unsigned char data[] = {0x80, 0x0c}; | 177 | unsigned char data[] = {0x80, 0x0c}; |
162 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data, | 178 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data, |
163 | .flags = 0, .len = 2}; | 179 | .flags = 0, .len = 2}; |
164 | i2c_transfer(c->adapter, &msg, 1); | 180 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
165 | } | 181 | } |
166 | 182 | ||
167 | /* ---------------------------------------------------------------------- */ | 183 | /* ---------------------------------------------------------------------- */ |
@@ -204,58 +220,64 @@ static struct tda827xa_data tda827xa_analog[] = { | |||
204 | { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} /* End */ | 220 | { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} /* End */ |
205 | }; | 221 | }; |
206 | 222 | ||
207 | static void tda827xa_lna_gain(struct i2c_client *c, int high) | 223 | static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, |
224 | struct analog_parameters *params) | ||
208 | { | 225 | { |
209 | struct tuner *t = i2c_get_clientdata(c); | 226 | struct tda8290_priv *priv = fe->tuner_priv; |
210 | unsigned char buf[] = {0x22, 0x01}; | 227 | unsigned char buf[] = {0x22, 0x01}; |
211 | int arg; | 228 | int arg; |
212 | struct i2c_msg msg = {.addr = c->addr, .flags = 0, .buf = buf, .len = sizeof(buf)}; | 229 | struct i2c_msg msg = {.addr = priv->i2c_props.addr, .flags = 0, .buf = buf, .len = sizeof(buf)}; |
213 | if (t->config) { | 230 | |
231 | if ((priv->lna_cfg == NULL) || (priv->tuner_callback == NULL)) | ||
232 | return; | ||
233 | |||
234 | if (*priv->lna_cfg) { | ||
214 | if (high) | 235 | if (high) |
215 | tuner_dbg("setting LNA to high gain\n"); | 236 | tuner_dbg("setting LNA to high gain\n"); |
216 | else | 237 | else |
217 | tuner_dbg("setting LNA to low gain\n"); | 238 | tuner_dbg("setting LNA to low gain\n"); |
218 | } | 239 | } |
219 | switch (t->config) { | 240 | switch (*priv->lna_cfg) { |
220 | case 0: /* no LNA */ | 241 | case 0: /* no LNA */ |
221 | break; | 242 | break; |
222 | case 1: /* switch is GPIO 0 of tda8290 */ | 243 | case 1: /* switch is GPIO 0 of tda8290 */ |
223 | case 2: | 244 | case 2: |
224 | /* turn Vsync on */ | 245 | /* turn Vsync on */ |
225 | if (t->std & V4L2_STD_MN) | 246 | if (params->std & V4L2_STD_MN) |
226 | arg = 1; | 247 | arg = 1; |
227 | else | 248 | else |
228 | arg = 0; | 249 | arg = 0; |
229 | if (t->tuner_callback) | 250 | if (priv->tuner_callback) |
230 | t->tuner_callback(c->adapter->algo_data, 1, arg); | 251 | priv->tuner_callback(priv->i2c_props.adap->algo_data, 1, arg); |
231 | buf[1] = high ? 0 : 1; | 252 | buf[1] = high ? 0 : 1; |
232 | if (t->config == 2) | 253 | if (*priv->lna_cfg == 2) |
233 | buf[1] = high ? 1 : 0; | 254 | buf[1] = high ? 1 : 0; |
234 | i2c_transfer(c->adapter, &msg, 1); | 255 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
235 | break; | 256 | break; |
236 | case 3: /* switch with GPIO of saa713x */ | 257 | case 3: /* switch with GPIO of saa713x */ |
237 | if (t->tuner_callback) | 258 | if (priv->tuner_callback) |
238 | t->tuner_callback(c->adapter->algo_data, 0, high); | 259 | priv->tuner_callback(priv->i2c_props.adap->algo_data, 0, high); |
239 | break; | 260 | break; |
240 | } | 261 | } |
241 | } | 262 | } |
242 | 263 | ||
243 | static void tda827xa_tune(struct i2c_client *c, u16 ifc, unsigned int freq) | 264 | static void tda827xa_set_analog_params(struct dvb_frontend *fe, |
265 | struct analog_parameters *params) | ||
244 | { | 266 | { |
245 | unsigned char tuner_reg[11]; | 267 | unsigned char tuner_reg[11]; |
246 | u32 N; | 268 | u32 N; |
247 | int i; | 269 | int i; |
248 | struct tuner *t = i2c_get_clientdata(c); | 270 | struct tda8290_priv *priv = fe->tuner_priv; |
249 | struct tda8290_priv *priv = t->priv; | ||
250 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0, .buf = tuner_reg}; | 271 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0, .buf = tuner_reg}; |
272 | unsigned int freq = params->frequency; | ||
251 | 273 | ||
252 | tda827xa_lna_gain( c, 1); | 274 | tda827xa_lna_gain(fe, 1, params); |
253 | msleep(10); | 275 | msleep(10); |
254 | 276 | ||
255 | if (t->mode == V4L2_TUNER_RADIO) | 277 | if (params->mode == V4L2_TUNER_RADIO) |
256 | freq = freq / 1000; | 278 | freq = freq / 1000; |
257 | 279 | ||
258 | N = freq + ifc; | 280 | N = freq + priv->sgIF; |
259 | i = 0; | 281 | i = 0; |
260 | while (tda827xa_analog[i].lomax < N) { | 282 | while (tda827xa_analog[i].lomax < N) { |
261 | if(tda827xa_analog[i + 1].lomax == 0) | 283 | if(tda827xa_analog[i + 1].lomax == 0) |
@@ -278,7 +300,7 @@ static void tda827xa_tune(struct i2c_client *c, u16 ifc, unsigned int freq) | |||
278 | tuner_reg[9] = 0x20; | 300 | tuner_reg[9] = 0x20; |
279 | tuner_reg[10] = 0x00; | 301 | tuner_reg[10] = 0x00; |
280 | msg.len = 11; | 302 | msg.len = 11; |
281 | i2c_transfer(c->adapter, &msg, 1); | 303 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
282 | 304 | ||
283 | tuner_reg[0] = 0x90; | 305 | tuner_reg[0] = 0x90; |
284 | tuner_reg[1] = 0xff; | 306 | tuner_reg[1] = 0xff; |
@@ -286,82 +308,131 @@ static void tda827xa_tune(struct i2c_client *c, u16 ifc, unsigned int freq) | |||
286 | tuner_reg[3] = 0; | 308 | tuner_reg[3] = 0; |
287 | tuner_reg[4] = 0x99 + (priv->tda827x_lpsel << 1); | 309 | tuner_reg[4] = 0x99 + (priv->tda827x_lpsel << 1); |
288 | msg.len = 5; | 310 | msg.len = 5; |
289 | i2c_transfer(c->adapter, &msg, 1); | 311 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
290 | 312 | ||
291 | tuner_reg[0] = 0xa0; | 313 | tuner_reg[0] = 0xa0; |
292 | tuner_reg[1] = 0xc0; | 314 | tuner_reg[1] = 0xc0; |
293 | msg.len = 2; | 315 | msg.len = 2; |
294 | i2c_transfer(c->adapter, &msg, 1); | 316 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
295 | 317 | ||
296 | tuner_reg[0] = 0x30; | 318 | tuner_reg[0] = 0x30; |
297 | tuner_reg[1] = 0x10 + tda827xa_analog[i].scr; | 319 | tuner_reg[1] = 0x10 + tda827xa_analog[i].scr; |
298 | i2c_transfer(c->adapter, &msg, 1); | 320 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
299 | 321 | ||
300 | msg.flags = I2C_M_RD; | 322 | msg.flags = I2C_M_RD; |
301 | i2c_transfer(c->adapter, &msg, 1); | 323 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
302 | msg.flags = 0; | 324 | msg.flags = 0; |
303 | tuner_reg[1] >>= 4; | 325 | tuner_reg[1] >>= 4; |
304 | tuner_dbg("AGC2 gain is: %d\n", tuner_reg[1]); | 326 | tuner_dbg("AGC2 gain is: %d\n", tuner_reg[1]); |
305 | if (tuner_reg[1] < 1) | 327 | if (tuner_reg[1] < 1) |
306 | tda827xa_lna_gain( c, 0); | 328 | tda827xa_lna_gain(fe, 0, params); |
307 | 329 | ||
308 | msleep(100); | 330 | msleep(100); |
309 | tuner_reg[0] = 0x60; | 331 | tuner_reg[0] = 0x60; |
310 | tuner_reg[1] = 0x3c; | 332 | tuner_reg[1] = 0x3c; |
311 | i2c_transfer(c->adapter, &msg, 1); | 333 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
312 | 334 | ||
313 | msleep(163); | 335 | msleep(163); |
314 | tuner_reg[0] = 0x50; | 336 | tuner_reg[0] = 0x50; |
315 | tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4); | 337 | tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4); |
316 | i2c_transfer(c->adapter, &msg, 1); | 338 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
317 | 339 | ||
318 | tuner_reg[0] = 0x80; | 340 | tuner_reg[0] = 0x80; |
319 | tuner_reg[1] = 0x28; | 341 | tuner_reg[1] = 0x28; |
320 | i2c_transfer(c->adapter, &msg, 1); | 342 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
321 | 343 | ||
322 | tuner_reg[0] = 0xb0; | 344 | tuner_reg[0] = 0xb0; |
323 | tuner_reg[1] = 0x01; | 345 | tuner_reg[1] = 0x01; |
324 | i2c_transfer(c->adapter, &msg, 1); | 346 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
325 | 347 | ||
326 | tuner_reg[0] = 0xc0; | 348 | tuner_reg[0] = 0xc0; |
327 | tuner_reg[1] = 0x19 + (priv->tda827x_lpsel << 1); | 349 | tuner_reg[1] = 0x19 + (priv->tda827x_lpsel << 1); |
328 | i2c_transfer(c->adapter, &msg, 1); | 350 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
329 | } | 351 | } |
330 | 352 | ||
331 | static void tda827xa_agcf(struct i2c_client *c) | 353 | static void tda827xa_agcf(struct dvb_frontend *fe) |
332 | { | 354 | { |
333 | struct tuner *t = i2c_get_clientdata(c); | 355 | struct tda8290_priv *priv = fe->tuner_priv; |
334 | struct tda8290_priv *priv = t->priv; | ||
335 | unsigned char data[] = {0x80, 0x2c}; | 356 | unsigned char data[] = {0x80, 0x2c}; |
336 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data, | 357 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data, |
337 | .flags = 0, .len = 2}; | 358 | .flags = 0, .len = 2}; |
338 | i2c_transfer(c->adapter, &msg, 1); | 359 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
339 | } | 360 | } |
340 | 361 | ||
341 | /*---------------------------------------------------------------------*/ | 362 | /*---------------------------------------------------------------------*/ |
342 | 363 | ||
343 | static void tda8290_i2c_bridge(struct i2c_client *c, int close) | 364 | static void tda8290_i2c_bridge(struct dvb_frontend *fe, int close) |
344 | { | 365 | { |
366 | struct tda8290_priv *priv = fe->tuner_priv; | ||
367 | |||
345 | unsigned char enable[2] = { 0x21, 0xC0 }; | 368 | unsigned char enable[2] = { 0x21, 0xC0 }; |
346 | unsigned char disable[2] = { 0x21, 0x00 }; | 369 | unsigned char disable[2] = { 0x21, 0x00 }; |
347 | unsigned char *msg; | 370 | unsigned char *msg; |
348 | if(close) { | 371 | if(close) { |
349 | msg = enable; | 372 | msg = enable; |
350 | i2c_master_send(c, msg, 2); | 373 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); |
351 | /* let the bridge stabilize */ | 374 | /* let the bridge stabilize */ |
352 | msleep(20); | 375 | msleep(20); |
353 | } else { | 376 | } else { |
354 | msg = disable; | 377 | msg = disable; |
355 | i2c_master_send(c, msg, 2); | 378 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); |
356 | } | 379 | } |
357 | } | 380 | } |
358 | 381 | ||
359 | /*---------------------------------------------------------------------*/ | 382 | /*---------------------------------------------------------------------*/ |
360 | 383 | ||
361 | static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) | 384 | static void set_audio(struct dvb_frontend *fe, |
385 | struct analog_parameters *params) | ||
386 | { | ||
387 | struct tda8290_priv *priv = fe->tuner_priv; | ||
388 | char* mode; | ||
389 | |||
390 | priv->tda827x_lpsel = 0; | ||
391 | if (params->std & V4L2_STD_MN) { | ||
392 | priv->sgIF = 92; | ||
393 | priv->tda8290_easy_mode = 0x01; | ||
394 | priv->tda827x_lpsel = 1; | ||
395 | mode = "MN"; | ||
396 | } else if (params->std & V4L2_STD_B) { | ||
397 | priv->sgIF = 108; | ||
398 | priv->tda8290_easy_mode = 0x02; | ||
399 | mode = "B"; | ||
400 | } else if (params->std & V4L2_STD_GH) { | ||
401 | priv->sgIF = 124; | ||
402 | priv->tda8290_easy_mode = 0x04; | ||
403 | mode = "GH"; | ||
404 | } else if (params->std & V4L2_STD_PAL_I) { | ||
405 | priv->sgIF = 124; | ||
406 | priv->tda8290_easy_mode = 0x08; | ||
407 | mode = "I"; | ||
408 | } else if (params->std & V4L2_STD_DK) { | ||
409 | priv->sgIF = 124; | ||
410 | priv->tda8290_easy_mode = 0x10; | ||
411 | mode = "DK"; | ||
412 | } else if (params->std & V4L2_STD_SECAM_L) { | ||
413 | priv->sgIF = 124; | ||
414 | priv->tda8290_easy_mode = 0x20; | ||
415 | mode = "L"; | ||
416 | } else if (params->std & V4L2_STD_SECAM_LC) { | ||
417 | priv->sgIF = 20; | ||
418 | priv->tda8290_easy_mode = 0x40; | ||
419 | mode = "LC"; | ||
420 | } else { | ||
421 | priv->sgIF = 124; | ||
422 | priv->tda8290_easy_mode = 0x10; | ||
423 | mode = "xx"; | ||
424 | } | ||
425 | |||
426 | if (params->mode == V4L2_TUNER_RADIO) | ||
427 | priv->sgIF = 88; /* if frequency is 5.5 MHz */ | ||
428 | |||
429 | tuner_dbg("setting tda8290 to system %s\n", mode); | ||
430 | } | ||
431 | |||
432 | static int tda8290_set_params(struct dvb_frontend *fe, | ||
433 | struct analog_parameters *params) | ||
362 | { | 434 | { |
363 | struct tuner *t = i2c_get_clientdata(c); | 435 | struct tda8290_priv *priv = fe->tuner_priv; |
364 | struct tda8290_priv *priv = t->priv; | ||
365 | unsigned char soft_reset[] = { 0x00, 0x00 }; | 436 | unsigned char soft_reset[] = { 0x00, 0x00 }; |
366 | unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; | 437 | unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; |
367 | unsigned char expert_mode[] = { 0x01, 0x80 }; | 438 | unsigned char expert_mode[] = { 0x01, 0x80 }; |
@@ -384,35 +455,38 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) | |||
384 | pll_stat; | 455 | pll_stat; |
385 | int i; | 456 | int i; |
386 | 457 | ||
387 | tuner_dbg("tda827xa config is 0x%02x\n", t->config); | 458 | set_audio(fe, params); |
388 | i2c_master_send(c, easy_mode, 2); | 459 | |
389 | i2c_master_send(c, agc_out_on, 2); | 460 | if (priv->lna_cfg) |
390 | i2c_master_send(c, soft_reset, 2); | 461 | tuner_dbg("tda827xa config is 0x%02x\n", *priv->lna_cfg); |
462 | tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2); | ||
463 | tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2); | ||
464 | tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2); | ||
391 | msleep(1); | 465 | msleep(1); |
392 | 466 | ||
393 | expert_mode[1] = priv->tda8290_easy_mode + 0x80; | 467 | expert_mode[1] = priv->tda8290_easy_mode + 0x80; |
394 | i2c_master_send(c, expert_mode, 2); | 468 | tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2); |
395 | i2c_master_send(c, gainset_off, 2); | 469 | tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2); |
396 | i2c_master_send(c, if_agc_spd, 2); | 470 | tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2); |
397 | if (priv->tda8290_easy_mode & 0x60) | 471 | if (priv->tda8290_easy_mode & 0x60) |
398 | i2c_master_send(c, adc_head_9, 2); | 472 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2); |
399 | else | 473 | else |
400 | i2c_master_send(c, adc_head_6, 2); | 474 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2); |
401 | i2c_master_send(c, pll_bw_nom, 2); | 475 | tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); |
402 | 476 | ||
403 | tda8290_i2c_bridge(c, 1); | 477 | tda8290_i2c_bridge(fe, 1); |
404 | if (priv->tda827x_ver != 0) | 478 | if (priv->tda827x_ver != 0) |
405 | tda827xa_tune(c, ifc, freq); | 479 | tda827xa_set_analog_params(fe, params); |
406 | else | 480 | else |
407 | tda827x_tune(c, ifc, freq); | 481 | tda827x_set_analog_params(fe, params); |
408 | for (i = 0; i < 3; i++) { | 482 | for (i = 0; i < 3; i++) { |
409 | i2c_master_send(c, &addr_pll_stat, 1); | 483 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); |
410 | i2c_master_recv(c, &pll_stat, 1); | 484 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); |
411 | if (pll_stat & 0x80) { | 485 | if (pll_stat & 0x80) { |
412 | i2c_master_send(c, &addr_adc_sat, 1); | 486 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); |
413 | i2c_master_recv(c, &adc_sat, 1); | 487 | tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); |
414 | i2c_master_send(c, &addr_agc_stat, 1); | 488 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); |
415 | i2c_master_recv(c, &agc_stat, 1); | 489 | tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); |
416 | tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat); | 490 | tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat); |
417 | break; | 491 | break; |
418 | } else { | 492 | } else { |
@@ -424,28 +498,28 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) | |||
424 | if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) { | 498 | if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) { |
425 | tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n", | 499 | tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n", |
426 | agc_stat, adc_sat, pll_stat & 0x80); | 500 | agc_stat, adc_sat, pll_stat & 0x80); |
427 | i2c_master_send(c, gainset_2, 2); | 501 | tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2); |
428 | msleep(100); | 502 | msleep(100); |
429 | i2c_master_send(c, &addr_agc_stat, 1); | 503 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); |
430 | i2c_master_recv(c, &agc_stat, 1); | 504 | tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); |
431 | i2c_master_send(c, &addr_pll_stat, 1); | 505 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); |
432 | i2c_master_recv(c, &pll_stat, 1); | 506 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); |
433 | if ((agc_stat > 115) || !(pll_stat & 0x80)) { | 507 | if ((agc_stat > 115) || !(pll_stat & 0x80)) { |
434 | tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", | 508 | tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", |
435 | agc_stat, pll_stat & 0x80); | 509 | agc_stat, pll_stat & 0x80); |
436 | if (priv->tda827x_ver != 0) | 510 | if (priv->tda827x_ver != 0) |
437 | tda827xa_agcf(c); | 511 | tda827xa_agcf(fe); |
438 | else | 512 | else |
439 | tda827x_agcf(c); | 513 | tda827x_agcf(fe); |
440 | msleep(100); | 514 | msleep(100); |
441 | i2c_master_send(c, &addr_agc_stat, 1); | 515 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); |
442 | i2c_master_recv(c, &agc_stat, 1); | 516 | tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); |
443 | i2c_master_send(c, &addr_pll_stat, 1); | 517 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); |
444 | i2c_master_recv(c, &pll_stat, 1); | 518 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); |
445 | if((agc_stat > 115) || !(pll_stat & 0x80)) { | 519 | if((agc_stat > 115) || !(pll_stat & 0x80)) { |
446 | tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat); | 520 | tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat); |
447 | i2c_master_send(c, adc_head_12, 2); | 521 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2); |
448 | i2c_master_send(c, pll_bw_low, 2); | 522 | tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2); |
449 | msleep(100); | 523 | msleep(100); |
450 | } | 524 | } |
451 | } | 525 | } |
@@ -453,132 +527,106 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) | |||
453 | 527 | ||
454 | /* l/ l' deadlock? */ | 528 | /* l/ l' deadlock? */ |
455 | if(priv->tda8290_easy_mode & 0x60) { | 529 | if(priv->tda8290_easy_mode & 0x60) { |
456 | i2c_master_send(c, &addr_adc_sat, 1); | 530 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); |
457 | i2c_master_recv(c, &adc_sat, 1); | 531 | tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); |
458 | i2c_master_send(c, &addr_pll_stat, 1); | 532 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); |
459 | i2c_master_recv(c, &pll_stat, 1); | 533 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); |
460 | if ((adc_sat > 20) || !(pll_stat & 0x80)) { | 534 | if ((adc_sat > 20) || !(pll_stat & 0x80)) { |
461 | tuner_dbg("trying to resolve SECAM L deadlock\n"); | 535 | tuner_dbg("trying to resolve SECAM L deadlock\n"); |
462 | i2c_master_send(c, agc_rst_on, 2); | 536 | tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2); |
463 | msleep(40); | 537 | msleep(40); |
464 | i2c_master_send(c, agc_rst_off, 2); | 538 | tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2); |
465 | } | 539 | } |
466 | } | 540 | } |
467 | 541 | ||
468 | tda8290_i2c_bridge(c, 0); | 542 | tda8290_i2c_bridge(fe, 0); |
469 | i2c_master_send(c, if_agc_set, 2); | 543 | tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2); |
544 | |||
545 | priv->frequency = (V4L2_TUNER_RADIO == params->mode) ? | ||
546 | params->frequency * 125 / 2 : params->frequency * 62500; | ||
547 | |||
470 | return 0; | 548 | return 0; |
471 | } | 549 | } |
472 | 550 | ||
473 | /*---------------------------------------------------------------------*/ | 551 | /*---------------------------------------------------------------------*/ |
474 | 552 | ||
475 | static void set_audio(struct tuner *t) | 553 | static int tda8290_has_signal(struct dvb_frontend *fe) |
476 | { | 554 | { |
477 | struct tda8290_priv *priv = t->priv; | 555 | struct tda8290_priv *priv = fe->tuner_priv; |
478 | char* mode; | 556 | int ret; |
479 | 557 | ||
480 | priv->tda827x_lpsel = 0; | 558 | unsigned char i2c_get_afc[1] = { 0x1B }; |
481 | if (t->std & V4L2_STD_MN) { | 559 | unsigned char afc = 0; |
482 | priv->sgIF = 92; | ||
483 | priv->tda8290_easy_mode = 0x01; | ||
484 | priv->tda827x_lpsel = 1; | ||
485 | mode = "MN"; | ||
486 | } else if (t->std & V4L2_STD_B) { | ||
487 | priv->sgIF = 108; | ||
488 | priv->tda8290_easy_mode = 0x02; | ||
489 | mode = "B"; | ||
490 | } else if (t->std & V4L2_STD_GH) { | ||
491 | priv->sgIF = 124; | ||
492 | priv->tda8290_easy_mode = 0x04; | ||
493 | mode = "GH"; | ||
494 | } else if (t->std & V4L2_STD_PAL_I) { | ||
495 | priv->sgIF = 124; | ||
496 | priv->tda8290_easy_mode = 0x08; | ||
497 | mode = "I"; | ||
498 | } else if (t->std & V4L2_STD_DK) { | ||
499 | priv->sgIF = 124; | ||
500 | priv->tda8290_easy_mode = 0x10; | ||
501 | mode = "DK"; | ||
502 | } else if (t->std & V4L2_STD_SECAM_L) { | ||
503 | priv->sgIF = 124; | ||
504 | priv->tda8290_easy_mode = 0x20; | ||
505 | mode = "L"; | ||
506 | } else if (t->std & V4L2_STD_SECAM_LC) { | ||
507 | priv->sgIF = 20; | ||
508 | priv->tda8290_easy_mode = 0x40; | ||
509 | mode = "LC"; | ||
510 | } else { | ||
511 | priv->sgIF = 124; | ||
512 | priv->tda8290_easy_mode = 0x10; | ||
513 | mode = "xx"; | ||
514 | } | ||
515 | tuner_dbg("setting tda8290 to system %s\n", mode); | ||
516 | } | ||
517 | 560 | ||
518 | static void set_tv_freq(struct i2c_client *c, unsigned int freq) | 561 | /* for now, report based on afc status */ |
519 | { | 562 | tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc)); |
520 | struct tuner *t = i2c_get_clientdata(c); | 563 | tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1); |
521 | struct tda8290_priv *priv = t->priv; | 564 | |
565 | ret = (afc & 0x80) ? 65535 : 0; | ||
522 | 566 | ||
523 | set_audio(t); | 567 | tuner_dbg("AFC status: %d\n", ret); |
524 | tda8290_tune(c, priv->sgIF, freq); | 568 | |
569 | return ret; | ||
525 | } | 570 | } |
526 | 571 | ||
527 | static void set_radio_freq(struct i2c_client *c, unsigned int freq) | 572 | static int tda8290_get_status(struct dvb_frontend *fe, u32 *status) |
528 | { | 573 | { |
529 | /* if frequency is 5.5 MHz */ | 574 | *status = 0; |
530 | tda8290_tune(c, 88, freq); | 575 | |
576 | if (tda8290_has_signal(fe)) | ||
577 | *status = TUNER_STATUS_LOCKED; | ||
578 | |||
579 | return 0; | ||
531 | } | 580 | } |
532 | 581 | ||
533 | static int has_signal(struct i2c_client *c) | 582 | static int tda8290_get_rf_strength(struct dvb_frontend *fe, u16 *strength) |
534 | { | 583 | { |
535 | unsigned char i2c_get_afc[1] = { 0x1B }; | 584 | *strength = tda8290_has_signal(fe); |
536 | unsigned char afc = 0; | ||
537 | 585 | ||
538 | i2c_master_send(c, i2c_get_afc, ARRAY_SIZE(i2c_get_afc)); | 586 | return 0; |
539 | i2c_master_recv(c, &afc, 1); | ||
540 | return (afc & 0x80)? 65535:0; | ||
541 | } | 587 | } |
542 | 588 | ||
543 | /*---------------------------------------------------------------------*/ | 589 | /*---------------------------------------------------------------------*/ |
544 | 590 | ||
545 | static void standby(struct i2c_client *c) | 591 | static int tda8290_standby(struct dvb_frontend *fe) |
546 | { | 592 | { |
547 | struct tuner *t = i2c_get_clientdata(c); | 593 | struct tda8290_priv *priv = fe->tuner_priv; |
548 | struct tda8290_priv *priv = t->priv; | ||
549 | unsigned char cb1[] = { 0x30, 0xD0 }; | 594 | unsigned char cb1[] = { 0x30, 0xD0 }; |
550 | unsigned char tda8290_standby[] = { 0x00, 0x02 }; | 595 | unsigned char tda8290_standby[] = { 0x00, 0x02 }; |
551 | unsigned char tda8290_agc_tri[] = { 0x02, 0x20 }; | 596 | unsigned char tda8290_agc_tri[] = { 0x02, 0x20 }; |
552 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; | 597 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; |
553 | 598 | ||
554 | tda8290_i2c_bridge(c, 1); | 599 | tda8290_i2c_bridge(fe, 1); |
555 | if (priv->tda827x_ver != 0) | 600 | if (priv->tda827x_ver != 0) |
556 | cb1[1] = 0x90; | 601 | cb1[1] = 0x90; |
557 | i2c_transfer(c->adapter, &msg, 1); | 602 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
558 | tda8290_i2c_bridge(c, 0); | 603 | tda8290_i2c_bridge(fe, 0); |
559 | i2c_master_send(c, tda8290_agc_tri, 2); | 604 | tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2); |
560 | i2c_master_send(c, tda8290_standby, 2); | 605 | tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2); |
606 | |||
607 | return 0; | ||
561 | } | 608 | } |
562 | 609 | ||
563 | 610 | ||
564 | static void tda8290_init_if(struct i2c_client *c) | 611 | static void tda8290_init_if(struct dvb_frontend *fe) |
565 | { | 612 | { |
566 | struct tuner *t = i2c_get_clientdata(c); | 613 | struct tda8290_priv *priv = fe->tuner_priv; |
614 | |||
567 | unsigned char set_VS[] = { 0x30, 0x6F }; | 615 | unsigned char set_VS[] = { 0x30, 0x6F }; |
568 | unsigned char set_GP00_CF[] = { 0x20, 0x01 }; | 616 | unsigned char set_GP00_CF[] = { 0x20, 0x01 }; |
569 | unsigned char set_GP01_CF[] = { 0x20, 0x0B }; | 617 | unsigned char set_GP01_CF[] = { 0x20, 0x0B }; |
570 | 618 | ||
571 | if ((t->config == 1) || (t->config == 2)) | 619 | if ((priv->lna_cfg) && |
572 | i2c_master_send(c, set_GP00_CF, 2); | 620 | ((*priv->lna_cfg == 1) || (*priv->lna_cfg == 2))) |
621 | tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2); | ||
573 | else | 622 | else |
574 | i2c_master_send(c, set_GP01_CF, 2); | 623 | tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2); |
575 | i2c_master_send(c, set_VS, 2); | 624 | tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2); |
576 | } | 625 | } |
577 | 626 | ||
578 | static void tda8290_init_tuner(struct i2c_client *c) | 627 | static void tda8290_init_tuner(struct dvb_frontend *fe) |
579 | { | 628 | { |
580 | struct tuner *t = i2c_get_clientdata(c); | 629 | struct tda8290_priv *priv = fe->tuner_priv; |
581 | struct tda8290_priv *priv = t->priv; | ||
582 | unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, | 630 | unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, |
583 | 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; | 631 | 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; |
584 | unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, | 632 | unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, |
@@ -588,33 +636,43 @@ static void tda8290_init_tuner(struct i2c_client *c) | |||
588 | if (priv->tda827x_ver != 0) | 636 | if (priv->tda827x_ver != 0) |
589 | msg.buf = tda8275a_init; | 637 | msg.buf = tda8275a_init; |
590 | 638 | ||
591 | tda8290_i2c_bridge(c, 1); | 639 | tda8290_i2c_bridge(fe, 1); |
592 | i2c_transfer(c->adapter, &msg, 1); | 640 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
593 | tda8290_i2c_bridge(c, 0); | 641 | tda8290_i2c_bridge(fe, 0); |
594 | } | 642 | } |
595 | 643 | ||
596 | /*---------------------------------------------------------------------*/ | 644 | /*---------------------------------------------------------------------*/ |
597 | 645 | ||
598 | static void tda8290_release(struct i2c_client *c) | 646 | static int tda8290_release(struct dvb_frontend *fe) |
599 | { | 647 | { |
600 | struct tuner *t = i2c_get_clientdata(c); | 648 | kfree(fe->tuner_priv); |
649 | fe->tuner_priv = NULL; | ||
601 | 650 | ||
602 | kfree(t->priv); | 651 | return 0; |
603 | t->priv = NULL; | ||
604 | } | 652 | } |
605 | 653 | ||
606 | static struct tuner_operations tda8290_tuner_ops = { | 654 | static int tda8290_get_frequency(struct dvb_frontend *fe, u32 *frequency) |
607 | .set_tv_freq = set_tv_freq, | 655 | { |
608 | .set_radio_freq = set_radio_freq, | 656 | struct tda8290_priv *priv = fe->tuner_priv; |
609 | .has_signal = has_signal, | 657 | *frequency = priv->frequency; |
610 | .standby = standby, | 658 | return 0; |
611 | .release = tda8290_release, | 659 | } |
660 | |||
661 | static struct dvb_tuner_ops tda8290_tuner_ops = { | ||
662 | .sleep = tda8290_standby, | ||
663 | .set_analog_params = tda8290_set_params, | ||
664 | .release = tda8290_release, | ||
665 | .get_frequency = tda8290_get_frequency, | ||
666 | .get_status = tda8290_get_status, | ||
667 | .get_rf_strength = tda8290_get_rf_strength, | ||
612 | }; | 668 | }; |
613 | 669 | ||
614 | int tda8290_init(struct i2c_client *c) | 670 | struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, |
671 | struct i2c_adapter* i2c_adap, | ||
672 | u8 i2c_addr, | ||
673 | struct tda8290_config *cfg) | ||
615 | { | 674 | { |
616 | struct tda8290_priv *priv = NULL; | 675 | struct tda8290_priv *priv = NULL; |
617 | struct tuner *t = i2c_get_clientdata(c); | ||
618 | u8 data; | 676 | u8 data; |
619 | int i, ret, tuners_found; | 677 | int i, ret, tuners_found; |
620 | u32 tuner_addrs; | 678 | u32 tuner_addrs; |
@@ -622,16 +680,23 @@ int tda8290_init(struct i2c_client *c) | |||
622 | 680 | ||
623 | priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); | 681 | priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); |
624 | if (priv == NULL) | 682 | if (priv == NULL) |
625 | return -ENOMEM; | 683 | return NULL; |
626 | t->priv = priv; | 684 | fe->tuner_priv = priv; |
685 | |||
686 | priv->i2c_props.addr = i2c_addr; | ||
687 | priv->i2c_props.adap = i2c_adap; | ||
688 | if (cfg) { | ||
689 | priv->lna_cfg = cfg->lna_cfg; | ||
690 | priv->tuner_callback = cfg->tuner_callback; | ||
691 | } | ||
627 | 692 | ||
628 | tda8290_i2c_bridge(c, 1); | 693 | tda8290_i2c_bridge(fe, 1); |
629 | /* probe for tuner chip */ | 694 | /* probe for tuner chip */ |
630 | tuners_found = 0; | 695 | tuners_found = 0; |
631 | tuner_addrs = 0; | 696 | tuner_addrs = 0; |
632 | for (i=0x60; i<= 0x63; i++) { | 697 | for (i=0x60; i<= 0x63; i++) { |
633 | msg.addr = i; | 698 | msg.addr = i; |
634 | ret = i2c_transfer(c->adapter, &msg, 1); | 699 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); |
635 | if (ret == 1) { | 700 | if (ret == 1) { |
636 | tuners_found++; | 701 | tuners_found++; |
637 | tuner_addrs = (tuner_addrs << 8) + i; | 702 | tuner_addrs = (tuner_addrs << 8) + i; |
@@ -641,11 +706,11 @@ int tda8290_init(struct i2c_client *c) | |||
641 | behind the bridge and we choose the highest address that doesn't | 706 | behind the bridge and we choose the highest address that doesn't |
642 | give a response now | 707 | give a response now |
643 | */ | 708 | */ |
644 | tda8290_i2c_bridge(c, 0); | 709 | tda8290_i2c_bridge(fe, 0); |
645 | if(tuners_found > 1) | 710 | if(tuners_found > 1) |
646 | for (i = 0; i < tuners_found; i++) { | 711 | for (i = 0; i < tuners_found; i++) { |
647 | msg.addr = tuner_addrs & 0xff; | 712 | msg.addr = tuner_addrs & 0xff; |
648 | ret = i2c_transfer(c->adapter, &msg, 1); | 713 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); |
649 | if(ret == 1) | 714 | if(ret == 1) |
650 | tuner_addrs = tuner_addrs >> 8; | 715 | tuner_addrs = tuner_addrs >> 8; |
651 | else | 716 | else |
@@ -653,40 +718,53 @@ int tda8290_init(struct i2c_client *c) | |||
653 | } | 718 | } |
654 | if (tuner_addrs == 0) { | 719 | if (tuner_addrs == 0) { |
655 | tuner_addrs = 0x61; | 720 | tuner_addrs = 0x61; |
656 | tuner_info ("could not clearly identify tuner address, defaulting to %x\n", | 721 | tuner_info("could not clearly identify tuner address, defaulting to %x\n", |
657 | tuner_addrs); | 722 | tuner_addrs); |
658 | } else { | 723 | } else { |
659 | tuner_addrs = tuner_addrs & 0xff; | 724 | tuner_addrs = tuner_addrs & 0xff; |
660 | tuner_info ("setting tuner address to %x\n", tuner_addrs); | 725 | tuner_info("setting tuner address to %x\n", tuner_addrs); |
661 | } | 726 | } |
662 | priv->tda827x_addr = tuner_addrs; | 727 | priv->tda827x_addr = tuner_addrs; |
663 | msg.addr = tuner_addrs; | 728 | msg.addr = tuner_addrs; |
664 | 729 | ||
665 | tda8290_i2c_bridge(c, 1); | 730 | tda8290_i2c_bridge(fe, 1); |
666 | ret = i2c_transfer(c->adapter, &msg, 1); | 731 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); |
667 | if( ret != 1) | 732 | if( ret != 1) |
668 | tuner_warn ("TDA827x access failed!\n"); | 733 | tuner_warn("TDA827x access failed!\n"); |
734 | |||
735 | memcpy(&fe->ops.tuner_ops, &tda8290_tuner_ops, | ||
736 | sizeof(struct dvb_tuner_ops)); | ||
737 | |||
669 | if ((data & 0x3c) == 0) { | 738 | if ((data & 0x3c) == 0) { |
670 | strlcpy(c->name, "tda8290+75", sizeof(c->name)); | 739 | strlcpy(fe->ops.tuner_ops.info.name, "tda8290+75", |
740 | sizeof(fe->ops.tuner_ops.info.name)); | ||
741 | fe->ops.tuner_ops.info.frequency_min = 55000000; | ||
742 | fe->ops.tuner_ops.info.frequency_max = 860000000; | ||
743 | fe->ops.tuner_ops.info.frequency_step = 250000; | ||
671 | priv->tda827x_ver = 0; | 744 | priv->tda827x_ver = 0; |
672 | } else { | 745 | } else { |
673 | strlcpy(c->name, "tda8290+75a", sizeof(c->name)); | 746 | strlcpy(fe->ops.tuner_ops.info.name, "tda8290+75a", |
747 | sizeof(fe->ops.tuner_ops.info.name)); | ||
748 | fe->ops.tuner_ops.info.frequency_min = 44000000; | ||
749 | fe->ops.tuner_ops.info.frequency_max = 906000000; | ||
750 | fe->ops.tuner_ops.info.frequency_step = 62500; | ||
674 | priv->tda827x_ver = 2; | 751 | priv->tda827x_ver = 2; |
675 | } | 752 | } |
676 | tuner_info("type set to %s\n", c->name); | ||
677 | |||
678 | memcpy(&t->ops, &tda8290_tuner_ops, sizeof(struct tuner_operations)); | ||
679 | 753 | ||
680 | priv->tda827x_lpsel = 0; | 754 | priv->tda827x_lpsel = 0; |
681 | t->mode = V4L2_TUNER_ANALOG_TV; | ||
682 | 755 | ||
683 | tda8290_init_tuner(c); | 756 | tda8290_init_tuner(fe); |
684 | tda8290_init_if(c); | 757 | tda8290_init_if(fe); |
685 | return 0; | 758 | return fe; |
686 | } | 759 | } |
687 | 760 | ||
688 | int tda8290_probe(struct i2c_client *c) | 761 | int tda8290_probe(struct i2c_adapter* i2c_adap, u8 i2c_addr) |
689 | { | 762 | { |
763 | struct tuner_i2c_props i2c_props = { | ||
764 | .adap = i2c_adap, | ||
765 | .addr = i2c_addr | ||
766 | }; | ||
767 | |||
690 | unsigned char soft_reset[] = { 0x00, 0x00 }; | 768 | unsigned char soft_reset[] = { 0x00, 0x00 }; |
691 | unsigned char easy_mode_b[] = { 0x01, 0x02 }; | 769 | unsigned char easy_mode_b[] = { 0x01, 0x02 }; |
692 | unsigned char easy_mode_g[] = { 0x01, 0x04 }; | 770 | unsigned char easy_mode_g[] = { 0x01, 0x04 }; |
@@ -694,23 +772,30 @@ int tda8290_probe(struct i2c_client *c) | |||
694 | unsigned char addr_dto_lsb = 0x07; | 772 | unsigned char addr_dto_lsb = 0x07; |
695 | unsigned char data; | 773 | unsigned char data; |
696 | 774 | ||
697 | i2c_master_send(c, easy_mode_b, 2); | 775 | tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2); |
698 | i2c_master_send(c, soft_reset, 2); | 776 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); |
699 | i2c_master_send(c, &addr_dto_lsb, 1); | 777 | tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); |
700 | i2c_master_recv(c, &data, 1); | 778 | tuner_i2c_xfer_recv(&i2c_props, &data, 1); |
701 | if (data == 0) { | 779 | if (data == 0) { |
702 | i2c_master_send(c, easy_mode_g, 2); | 780 | tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2); |
703 | i2c_master_send(c, soft_reset, 2); | 781 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); |
704 | i2c_master_send(c, &addr_dto_lsb, 1); | 782 | tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); |
705 | i2c_master_recv(c, &data, 1); | 783 | tuner_i2c_xfer_recv(&i2c_props, &data, 1); |
706 | if (data == 0x7b) { | 784 | if (data == 0x7b) { |
707 | return 0; | 785 | return 0; |
708 | } | 786 | } |
709 | } | 787 | } |
710 | i2c_master_send(c, restore_9886, 3); | 788 | tuner_i2c_xfer_send(&i2c_props, restore_9886, 3); |
711 | return -1; | 789 | return -1; |
712 | } | 790 | } |
713 | 791 | ||
792 | EXPORT_SYMBOL_GPL(tda8290_probe); | ||
793 | EXPORT_SYMBOL_GPL(tda8290_attach); | ||
794 | |||
795 | MODULE_DESCRIPTION("Philips TDA8290 + TDA8275 / TDA8275a tuner driver"); | ||
796 | MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann"); | ||
797 | MODULE_LICENSE("GPL"); | ||
798 | |||
714 | /* | 799 | /* |
715 | * Overrides for Emacs so that we follow Linus's tabbing style. | 800 | * Overrides for Emacs so that we follow Linus's tabbing style. |
716 | * --------------------------------------------------------------------------- | 801 | * --------------------------------------------------------------------------- |
diff --git a/drivers/media/video/tda8290.h b/drivers/media/video/tda8290.h new file mode 100644 index 000000000000..107b24b05aa1 --- /dev/null +++ b/drivers/media/video/tda8290.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | This program is free software; you can redistribute it and/or modify | ||
3 | it under the terms of the GNU General Public License as published by | ||
4 | the Free Software Foundation; either version 2 of the License, or | ||
5 | (at your option) any later version. | ||
6 | |||
7 | This program is distributed in the hope that it will be useful, | ||
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | GNU General Public License for more details. | ||
11 | |||
12 | You should have received a copy of the GNU General Public License | ||
13 | along with this program; if not, write to the Free Software | ||
14 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
15 | */ | ||
16 | |||
17 | #ifndef __TDA8290_H__ | ||
18 | #define __TDA8290_H__ | ||
19 | |||
20 | #include <linux/i2c.h> | ||
21 | #include "dvb_frontend.h" | ||
22 | |||
23 | struct tda8290_config | ||
24 | { | ||
25 | unsigned int *lna_cfg; | ||
26 | int (*tuner_callback) (void *dev, int command,int arg); | ||
27 | }; | ||
28 | |||
29 | #if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE)) | ||
30 | extern int tda8290_probe(struct i2c_adapter* i2c_adap, u8 i2c_addr); | ||
31 | |||
32 | extern struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, | ||
33 | struct i2c_adapter* i2c_adap, | ||
34 | u8 i2c_addr, | ||
35 | struct tda8290_config *cfg); | ||
36 | #else | ||
37 | static inline int tda8290_probe(struct i2c_adapter* i2c_adap, u8 i2c_addr) | ||
38 | { | ||
39 | printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", | ||
40 | __FUNCTION__); | ||
41 | return -EINVAL; | ||
42 | } | ||
43 | |||
44 | static inline struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, | ||
45 | struct i2c_adapter* i2c_adap, | ||
46 | u8 i2c_addr, | ||
47 | struct tda8290_config *cfg) | ||
48 | { | ||
49 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | ||
50 | return NULL; | ||
51 | } | ||
52 | #endif | ||
53 | |||
54 | #endif /* __TDA8290_H__ */ | ||
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index a8f773274fe3..be5387f11afb 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c | |||
@@ -1,14 +1,12 @@ | |||
1 | #include <linux/module.h> | 1 | #include <linux/module.h> |
2 | #include <linux/moduleparam.h> | ||
3 | #include <linux/kernel.h> | 2 | #include <linux/kernel.h> |
4 | #include <linux/i2c.h> | 3 | #include <linux/i2c.h> |
5 | #include <linux/types.h> | 4 | #include <linux/types.h> |
6 | #include <linux/videodev.h> | ||
7 | #include <linux/init.h> | 5 | #include <linux/init.h> |
8 | #include <linux/errno.h> | 6 | #include <linux/errno.h> |
9 | #include <linux/slab.h> | 7 | #include <linux/slab.h> |
10 | #include <linux/delay.h> | 8 | #include <linux/delay.h> |
11 | 9 | #include <linux/videodev.h> | |
12 | #include <media/v4l2-common.h> | 10 | #include <media/v4l2-common.h> |
13 | #include <media/tuner.h> | 11 | #include <media/tuner.h> |
14 | #include "tuner-driver.h" | 12 | #include "tuner-driver.h" |
@@ -31,6 +29,8 @@ | |||
31 | i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) | 29 | i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) |
32 | 30 | ||
33 | struct tda9887_priv { | 31 | struct tda9887_priv { |
32 | struct tuner_i2c_props i2c_props; | ||
33 | |||
34 | unsigned char data[4]; | 34 | unsigned char data[4]; |
35 | }; | 35 | }; |
36 | 36 | ||
@@ -97,6 +97,8 @@ struct tvnorm { | |||
97 | #define cAudioIF_6_5 0x03 // bit e0:1 | 97 | #define cAudioIF_6_5 0x03 // bit e0:1 |
98 | 98 | ||
99 | 99 | ||
100 | #define cVideoIFMask 0x1c // bit e2:4 | ||
101 | /* Video IF selection in TV Mode (bit B3=0) */ | ||
100 | #define cVideoIF_58_75 0x00 // bit e2:4 | 102 | #define cVideoIF_58_75 0x00 // bit e2:4 |
101 | #define cVideoIF_45_75 0x04 // bit e2:4 | 103 | #define cVideoIF_45_75 0x04 // bit e2:4 |
102 | #define cVideoIF_38_90 0x08 // bit e2:4 | 104 | #define cVideoIF_38_90 0x08 // bit e2:4 |
@@ -106,6 +108,13 @@ struct tvnorm { | |||
106 | #define cRadioIF_45_75 0x18 // bit e2:4 | 108 | #define cRadioIF_45_75 0x18 // bit e2:4 |
107 | #define cRadioIF_38_90 0x1C // bit e2:4 | 109 | #define cRadioIF_38_90 0x1C // bit e2:4 |
108 | 110 | ||
111 | /* IF1 selection in Radio Mode (bit B3=1) */ | ||
112 | #define cRadioIF_33_30 0x00 // bit e2,4 (also 0x10,0x14) | ||
113 | #define cRadioIF_41_30 0x04 // bit e2,4 | ||
114 | |||
115 | /* Output of AFC pin in radio mode when bit E7=1 */ | ||
116 | #define cRadioAGC_SIF 0x00 // bit e3 | ||
117 | #define cRadioAGC_FM 0x08 // bit e3 | ||
109 | 118 | ||
110 | #define cTunerGainNormal 0x00 // bit e5 | 119 | #define cTunerGainNormal 0x00 // bit e5 |
111 | #define cTunerGainLow 0x20 // bit e5 | 120 | #define cTunerGainLow 0x20 // bit e5 |
@@ -487,9 +496,13 @@ static int tda9887_set_config(struct tuner *t, char *buf) | |||
487 | if (t->tda9887_config & TDA9887_GATING_18) | 496 | if (t->tda9887_config & TDA9887_GATING_18) |
488 | buf[3] &= ~cGating_36; | 497 | buf[3] &= ~cGating_36; |
489 | 498 | ||
490 | if (t->tda9887_config & TDA9887_GAIN_NORMAL) { | 499 | if (t->mode == V4L2_TUNER_RADIO) { |
491 | radio_stereo.e &= ~cTunerGainLow; | 500 | if (t->tda9887_config & TDA9887_RIF_41_3) { |
492 | radio_mono.e &= ~cTunerGainLow; | 501 | buf[3] &= ~cVideoIFMask; |
502 | buf[3] |= cRadioIF_41_30; | ||
503 | } | ||
504 | if (t->tda9887_config & TDA9887_GAIN_NORMAL) | ||
505 | buf[3] &= ~cTunerGainLow; | ||
493 | } | 506 | } |
494 | 507 | ||
495 | return 0; | 508 | return 0; |
@@ -499,19 +512,19 @@ static int tda9887_set_config(struct tuner *t, char *buf) | |||
499 | 512 | ||
500 | static int tda9887_status(struct tuner *t) | 513 | static int tda9887_status(struct tuner *t) |
501 | { | 514 | { |
515 | struct tda9887_priv *priv = t->priv; | ||
502 | unsigned char buf[1]; | 516 | unsigned char buf[1]; |
503 | int rc; | 517 | int rc; |
504 | 518 | ||
505 | memset(buf,0,sizeof(buf)); | 519 | memset(buf,0,sizeof(buf)); |
506 | if (1 != (rc = i2c_master_recv(&t->i2c,buf,1))) | 520 | if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1))) |
507 | tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); | 521 | tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); |
508 | dump_read_message(t, buf); | 522 | dump_read_message(t, buf); |
509 | return 0; | 523 | return 0; |
510 | } | 524 | } |
511 | 525 | ||
512 | static void tda9887_configure(struct i2c_client *client) | 526 | static void tda9887_configure(struct tuner *t) |
513 | { | 527 | { |
514 | struct tuner *t = i2c_get_clientdata(client); | ||
515 | struct tda9887_priv *priv = t->priv; | 528 | struct tda9887_priv *priv = t->priv; |
516 | int rc; | 529 | int rc; |
517 | 530 | ||
@@ -546,7 +559,7 @@ static void tda9887_configure(struct i2c_client *client) | |||
546 | if (tuner_debug > 1) | 559 | if (tuner_debug > 1) |
547 | dump_write_message(t, priv->data); | 560 | dump_write_message(t, priv->data); |
548 | 561 | ||
549 | if (4 != (rc = i2c_master_send(&t->i2c,priv->data,4))) | 562 | if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4))) |
550 | tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); | 563 | tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); |
551 | 564 | ||
552 | if (tuner_debug > 2) { | 565 | if (tuner_debug > 2) { |
@@ -557,16 +570,15 @@ static void tda9887_configure(struct i2c_client *client) | |||
557 | 570 | ||
558 | /* ---------------------------------------------------------------------- */ | 571 | /* ---------------------------------------------------------------------- */ |
559 | 572 | ||
560 | static void tda9887_tuner_status(struct i2c_client *client) | 573 | static void tda9887_tuner_status(struct tuner *t) |
561 | { | 574 | { |
562 | struct tuner *t = i2c_get_clientdata(client); | ||
563 | struct tda9887_priv *priv = t->priv; | 575 | struct tda9887_priv *priv = t->priv; |
564 | tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1], priv->data[2], priv->data[3]); | 576 | tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1], priv->data[2], priv->data[3]); |
565 | } | 577 | } |
566 | 578 | ||
567 | static int tda9887_get_afc(struct i2c_client *client) | 579 | static int tda9887_get_afc(struct tuner *t) |
568 | { | 580 | { |
569 | struct tuner *t = i2c_get_clientdata(client); | 581 | struct tda9887_priv *priv = t->priv; |
570 | static int AFC_BITS_2_kHz[] = { | 582 | static int AFC_BITS_2_kHz[] = { |
571 | -12500, -37500, -62500, -97500, | 583 | -12500, -37500, -62500, -97500, |
572 | -112500, -137500, -162500, -187500, | 584 | -112500, -137500, -162500, -187500, |
@@ -576,26 +588,24 @@ static int tda9887_get_afc(struct i2c_client *client) | |||
576 | int afc=0; | 588 | int afc=0; |
577 | __u8 reg = 0; | 589 | __u8 reg = 0; |
578 | 590 | ||
579 | if (1 == i2c_master_recv(&t->i2c,®,1)) | 591 | if (1 == tuner_i2c_xfer_recv(&priv->i2c_props,®,1)) |
580 | afc = AFC_BITS_2_kHz[(reg>>1)&0x0f]; | 592 | afc = AFC_BITS_2_kHz[(reg>>1)&0x0f]; |
581 | 593 | ||
582 | return afc; | 594 | return afc; |
583 | } | 595 | } |
584 | 596 | ||
585 | static void tda9887_standby(struct i2c_client *client) | 597 | static void tda9887_standby(struct tuner *t) |
586 | { | 598 | { |
587 | tda9887_configure(client); | 599 | tda9887_configure(t); |
588 | } | 600 | } |
589 | 601 | ||
590 | static void tda9887_set_freq(struct i2c_client *client, unsigned int freq) | 602 | static void tda9887_set_freq(struct tuner *t, unsigned int freq) |
591 | { | 603 | { |
592 | tda9887_configure(client); | 604 | tda9887_configure(t); |
593 | } | 605 | } |
594 | 606 | ||
595 | static void tda9887_release(struct i2c_client *c) | 607 | static void tda9887_release(struct tuner *t) |
596 | { | 608 | { |
597 | struct tuner *t = i2c_get_clientdata(c); | ||
598 | |||
599 | kfree(t->priv); | 609 | kfree(t->priv); |
600 | t->priv = NULL; | 610 | t->priv = NULL; |
601 | } | 611 | } |
@@ -609,17 +619,19 @@ static struct tuner_operations tda9887_tuner_ops = { | |||
609 | .release = tda9887_release, | 619 | .release = tda9887_release, |
610 | }; | 620 | }; |
611 | 621 | ||
612 | int tda9887_tuner_init(struct i2c_client *c) | 622 | int tda9887_tuner_init(struct tuner *t) |
613 | { | 623 | { |
614 | struct tda9887_priv *priv = NULL; | 624 | struct tda9887_priv *priv = NULL; |
615 | struct tuner *t = i2c_get_clientdata(c); | ||
616 | 625 | ||
617 | priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL); | 626 | priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL); |
618 | if (priv == NULL) | 627 | if (priv == NULL) |
619 | return -ENOMEM; | 628 | return -ENOMEM; |
620 | t->priv = priv; | 629 | t->priv = priv; |
621 | 630 | ||
622 | strlcpy(c->name, "tda9887", sizeof(c->name)); | 631 | priv->i2c_props.addr = t->i2c.addr; |
632 | priv->i2c_props.adap = t->i2c.adapter; | ||
633 | |||
634 | strlcpy(t->i2c.name, "tda9887", sizeof(t->i2c.name)); | ||
623 | 635 | ||
624 | tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr, | 636 | tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr, |
625 | t->i2c.driver->driver.name); | 637 | t->i2c.driver->driver.name); |
diff --git a/drivers/media/video/tea5761.c b/drivers/media/video/tea5761.c index ae105c2cd0ac..2150222a3860 100644 --- a/drivers/media/video/tea5761.c +++ b/drivers/media/video/tea5761.c | |||
@@ -8,15 +8,23 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/i2c.h> | 10 | #include <linux/i2c.h> |
11 | #include <linux/videodev.h> | ||
12 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
12 | #include <linux/videodev.h> | ||
13 | #include <media/tuner.h> | 13 | #include <media/tuner.h> |
14 | #include "tuner-driver.h" | 14 | #include "tuner-i2c.h" |
15 | #include "tea5761.h" | ||
15 | 16 | ||
16 | #define PREFIX "TEA5761 " | 17 | static int debug = 0; |
18 | module_param(debug, int, 0644); | ||
19 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
17 | 20 | ||
18 | /* from tuner-core.c */ | 21 | #define PREFIX "tea5761 " |
19 | extern int tuner_debug; | 22 | |
23 | struct tea5761_priv { | ||
24 | struct tuner_i2c_props i2c_props; | ||
25 | |||
26 | u32 frequency; | ||
27 | }; | ||
20 | 28 | ||
21 | /*****************************************************************************/ | 29 | /*****************************************************************************/ |
22 | 30 | ||
@@ -114,13 +122,6 @@ extern int tuner_debug; | |||
114 | 122 | ||
115 | /*****************************************************************************/ | 123 | /*****************************************************************************/ |
116 | 124 | ||
117 | static void set_tv_freq(struct i2c_client *c, unsigned int freq) | ||
118 | { | ||
119 | struct tuner *t = i2c_get_clientdata(c); | ||
120 | |||
121 | tuner_warn("This tuner doesn't support TV freq.\n"); | ||
122 | } | ||
123 | |||
124 | #define FREQ_OFFSET 0 /* for TEA5767, it is 700 to give the right freq */ | 125 | #define FREQ_OFFSET 0 /* for TEA5767, it is 700 to give the right freq */ |
125 | static void tea5761_status_dump(unsigned char *buffer) | 126 | static void tea5761_status_dump(unsigned char *buffer) |
126 | { | 127 | { |
@@ -135,16 +136,18 @@ static void tea5761_status_dump(unsigned char *buffer) | |||
135 | } | 136 | } |
136 | 137 | ||
137 | /* Freq should be specifyed at 62.5 Hz */ | 138 | /* Freq should be specifyed at 62.5 Hz */ |
138 | static void set_radio_freq(struct i2c_client *c, unsigned int frq) | 139 | static int set_radio_freq(struct dvb_frontend *fe, |
140 | struct analog_parameters *params) | ||
139 | { | 141 | { |
140 | struct tuner *t = i2c_get_clientdata(c); | 142 | struct tea5761_priv *priv = fe->tuner_priv; |
143 | unsigned int frq = params->frequency; | ||
141 | unsigned char buffer[7] = {0, 0, 0, 0, 0, 0, 0 }; | 144 | unsigned char buffer[7] = {0, 0, 0, 0, 0, 0, 0 }; |
142 | unsigned div; | 145 | unsigned div; |
143 | int rc; | 146 | int rc; |
144 | 147 | ||
145 | tuner_dbg (PREFIX "radio freq counter %d\n", frq); | 148 | tuner_dbg("radio freq counter %d\n", frq); |
146 | 149 | ||
147 | if (t->mode == T_STANDBY) { | 150 | if (params->mode == T_STANDBY) { |
148 | tuner_dbg("TEA5761 set to standby mode\n"); | 151 | tuner_dbg("TEA5761 set to standby mode\n"); |
149 | buffer[5] |= TEA5761_TNCTRL_MU; | 152 | buffer[5] |= TEA5761_TNCTRL_MU; |
150 | } else { | 153 | } else { |
@@ -152,10 +155,9 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq) | |||
152 | } | 155 | } |
153 | 156 | ||
154 | 157 | ||
155 | if (t->audmode == V4L2_TUNER_MODE_MONO) { | 158 | if (params->audmode == V4L2_TUNER_MODE_MONO) { |
156 | tuner_dbg("TEA5761 set to mono\n"); | 159 | tuner_dbg("TEA5761 set to mono\n"); |
157 | buffer[5] |= TEA5761_TNCTRL_MST; | 160 | buffer[5] |= TEA5761_TNCTRL_MST; |
158 | ; | ||
159 | } else { | 161 | } else { |
160 | tuner_dbg("TEA5761 set to stereo\n"); | 162 | tuner_dbg("TEA5761 set to stereo\n"); |
161 | } | 163 | } |
@@ -164,80 +166,155 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq) | |||
164 | buffer[1] = (div >> 8) & 0x3f; | 166 | buffer[1] = (div >> 8) & 0x3f; |
165 | buffer[2] = div & 0xff; | 167 | buffer[2] = div & 0xff; |
166 | 168 | ||
167 | if (tuner_debug) | 169 | if (debug) |
168 | tea5761_status_dump(buffer); | 170 | tea5761_status_dump(buffer); |
169 | 171 | ||
170 | if (7 != (rc = i2c_master_send(c, buffer, 7))) | 172 | if (7 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 7))) |
171 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | 173 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); |
174 | |||
175 | priv->frequency = frq * 125 / 2; | ||
176 | |||
177 | return 0; | ||
172 | } | 178 | } |
173 | 179 | ||
174 | static int tea5761_signal(struct i2c_client *c) | 180 | static int tea5761_read_status(struct dvb_frontend *fe, char *buffer) |
175 | { | 181 | { |
176 | unsigned char buffer[16]; | 182 | struct tea5761_priv *priv = fe->tuner_priv; |
177 | int rc; | 183 | int rc; |
178 | struct tuner *t = i2c_get_clientdata(c); | ||
179 | 184 | ||
180 | memset(buffer, 0, sizeof(buffer)); | 185 | memset(buffer, 0, 16); |
181 | if (16 != (rc = i2c_master_recv(c, buffer, 16))) | 186 | if (16 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 16))) { |
182 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | 187 | tuner_warn("i2c i/o error: rc == %d (should be 16)\n", rc); |
188 | return -EREMOTEIO; | ||
189 | } | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static inline int tea5761_signal(struct dvb_frontend *fe, const char *buffer) | ||
195 | { | ||
196 | struct tea5761_priv *priv = fe->tuner_priv; | ||
197 | |||
198 | int signal = ((buffer[9] & TEA5761_TUNCHECK_LEV_MASK) << (13 - 4)); | ||
199 | |||
200 | tuner_dbg("Signal strength: %d\n", signal); | ||
201 | |||
202 | return signal; | ||
203 | } | ||
204 | |||
205 | static inline int tea5761_stereo(struct dvb_frontend *fe, const char *buffer) | ||
206 | { | ||
207 | struct tea5761_priv *priv = fe->tuner_priv; | ||
208 | |||
209 | int stereo = buffer[9] & TEA5761_TUNCHECK_STEREO; | ||
183 | 210 | ||
184 | return ((buffer[9] & TEA5761_TUNCHECK_LEV_MASK) << (13 - 4)); | 211 | tuner_dbg("Radio ST GET = %02x\n", stereo); |
212 | |||
213 | return (stereo ? V4L2_TUNER_SUB_STEREO : 0); | ||
185 | } | 214 | } |
186 | 215 | ||
187 | static int tea5761_stereo(struct i2c_client *c) | 216 | static int tea5761_get_status(struct dvb_frontend *fe, u32 *status) |
188 | { | 217 | { |
189 | unsigned char buffer[16]; | 218 | unsigned char buffer[16]; |
190 | int rc; | ||
191 | struct tuner *t = i2c_get_clientdata(c); | ||
192 | 219 | ||
193 | memset(buffer, 0, sizeof(buffer)); | 220 | *status = 0; |
194 | if (16 != (rc = i2c_master_recv(c, buffer, 16))) | 221 | |
195 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | 222 | if (0 == tea5761_read_status(fe, buffer)) { |
223 | if (tea5761_signal(fe, buffer)) | ||
224 | *status = TUNER_STATUS_LOCKED; | ||
225 | if (tea5761_stereo(fe, buffer)) | ||
226 | *status |= TUNER_STATUS_STEREO; | ||
227 | } | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int tea5761_get_rf_strength(struct dvb_frontend *fe, u16 *strength) | ||
233 | { | ||
234 | unsigned char buffer[16]; | ||
196 | 235 | ||
197 | rc = buffer[9] & TEA5761_TUNCHECK_STEREO; | 236 | *strength = 0; |
198 | 237 | ||
199 | tuner_dbg("TEA5761 radio ST GET = %02x\n", rc); | 238 | if (0 == tea5761_read_status(fe, buffer)) |
239 | *strength = tea5761_signal(fe, buffer); | ||
200 | 240 | ||
201 | return (rc ? V4L2_TUNER_SUB_STEREO : 0); | 241 | return 0; |
202 | } | 242 | } |
203 | 243 | ||
204 | int tea5761_autodetection(struct i2c_client *c) | 244 | int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr) |
205 | { | 245 | { |
206 | unsigned char buffer[16]; | 246 | unsigned char buffer[16]; |
207 | int rc; | 247 | int rc; |
208 | struct tuner *t = i2c_get_clientdata(c); | 248 | struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr }; |
209 | 249 | ||
210 | if (16 != (rc = i2c_master_recv(c, buffer, 16))) { | 250 | if (16 != (rc = tuner_i2c_xfer_recv(&i2c, buffer, 16))) { |
211 | tuner_warn("it is not a TEA5761. Received %i chars.\n", rc); | 251 | printk(KERN_WARNING "it is not a TEA5761. Received %i chars.\n", rc); |
212 | return EINVAL; | 252 | return EINVAL; |
213 | } | 253 | } |
214 | 254 | ||
215 | if (!((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061))) { | 255 | if (!((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061))) { |
216 | tuner_warn("Manufacturer ID= 0x%02x, Chip ID = %02x%02x. It is not a TEA5761\n",buffer[13],buffer[14],buffer[15]); | 256 | printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x. It is not a TEA5761\n",buffer[13],buffer[14],buffer[15]); |
217 | return EINVAL; | 257 | return EINVAL; |
218 | } | 258 | } |
219 | tuner_warn("TEA5761 detected.\n"); | 259 | printk(KERN_WARNING "TEA5761 detected.\n"); |
220 | return 0; | 260 | return 0; |
221 | } | 261 | } |
222 | 262 | ||
223 | static struct tuner_operations tea5761_tuner_ops = { | 263 | static int tea5761_release(struct dvb_frontend *fe) |
224 | .set_tv_freq = set_tv_freq, | 264 | { |
225 | .set_radio_freq = set_radio_freq, | 265 | kfree(fe->tuner_priv); |
226 | .has_signal = tea5761_signal, | 266 | fe->tuner_priv = NULL; |
227 | .is_stereo = tea5761_stereo, | 267 | |
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static int tea5761_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
272 | { | ||
273 | struct tea5761_priv *priv = fe->tuner_priv; | ||
274 | *frequency = priv->frequency; | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static struct dvb_tuner_ops tea5761_tuner_ops = { | ||
279 | .info = { | ||
280 | .name = "tea5761", // Philips TEA5761HN FM Radio | ||
281 | }, | ||
282 | .set_analog_params = set_radio_freq, | ||
283 | .release = tea5761_release, | ||
284 | .get_frequency = tea5761_get_frequency, | ||
285 | .get_status = tea5761_get_status, | ||
286 | .get_rf_strength = tea5761_get_rf_strength, | ||
228 | }; | 287 | }; |
229 | 288 | ||
230 | int tea5761_tuner_init(struct i2c_client *c) | 289 | struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe, |
290 | struct i2c_adapter* i2c_adap, | ||
291 | u8 i2c_addr) | ||
231 | { | 292 | { |
232 | struct tuner *t = i2c_get_clientdata(c); | 293 | struct tea5761_priv *priv = NULL; |
233 | 294 | ||
234 | if (tea5761_autodetection(c) == EINVAL) | 295 | if (tea5761_autodetection(i2c_adap, i2c_addr) == EINVAL) |
235 | return EINVAL; | 296 | return NULL; |
297 | |||
298 | priv = kzalloc(sizeof(struct tea5761_priv), GFP_KERNEL); | ||
299 | if (priv == NULL) | ||
300 | return NULL; | ||
301 | fe->tuner_priv = priv; | ||
302 | |||
303 | priv->i2c_props.addr = i2c_addr; | ||
304 | priv->i2c_props.adap = i2c_adap; | ||
236 | 305 | ||
237 | tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5761HN FM Radio"); | 306 | memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops, |
238 | strlcpy(c->name, "tea5761", sizeof(c->name)); | 307 | sizeof(struct dvb_tuner_ops)); |
239 | 308 | ||
240 | memcpy(&t->ops, &tea5761_tuner_ops, sizeof(struct tuner_operations)); | 309 | tuner_info("type set to %s\n", "Philips TEA5761HN FM Radio"); |
241 | 310 | ||
242 | return (0); | 311 | return fe; |
243 | } | 312 | } |
313 | |||
314 | |||
315 | EXPORT_SYMBOL_GPL(tea5761_attach); | ||
316 | EXPORT_SYMBOL_GPL(tea5761_autodetection); | ||
317 | |||
318 | MODULE_DESCRIPTION("Philips TEA5761 FM tuner driver"); | ||
319 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | ||
320 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/tea5761.h b/drivers/media/video/tea5761.h new file mode 100644 index 000000000000..73a03b427843 --- /dev/null +++ b/drivers/media/video/tea5761.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | This program is free software; you can redistribute it and/or modify | ||
3 | it under the terms of the GNU General Public License as published by | ||
4 | the Free Software Foundation; either version 2 of the License, or | ||
5 | (at your option) any later version. | ||
6 | |||
7 | This program is distributed in the hope that it will be useful, | ||
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | GNU General Public License for more details. | ||
11 | |||
12 | You should have received a copy of the GNU General Public License | ||
13 | along with this program; if not, write to the Free Software | ||
14 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
15 | */ | ||
16 | |||
17 | #ifndef __TEA5761_H__ | ||
18 | #define __TEA5761_H__ | ||
19 | |||
20 | #include <linux/i2c.h> | ||
21 | #include "dvb_frontend.h" | ||
22 | |||
23 | #if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE)) | ||
24 | extern int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr); | ||
25 | |||
26 | extern struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe, | ||
27 | struct i2c_adapter* i2c_adap, | ||
28 | u8 i2c_addr); | ||
29 | #else | ||
30 | static inline int tea5761_autodetection(struct i2c_adapter* i2c_adap, | ||
31 | u8 i2c_addr) | ||
32 | { | ||
33 | printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", | ||
34 | __FUNCTION__); | ||
35 | return -EINVAL; | ||
36 | } | ||
37 | |||
38 | static inline struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe, | ||
39 | struct i2c_adapter* i2c_adap, | ||
40 | u8 i2c_addr) | ||
41 | { | ||
42 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | ||
43 | return NULL; | ||
44 | } | ||
45 | #endif | ||
46 | |||
47 | #endif /* __TEA5761_H__ */ | ||
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 4985d47a508f..71df419df7bc 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c | |||
@@ -11,14 +11,22 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/i2c.h> | 13 | #include <linux/i2c.h> |
14 | #include <linux/videodev.h> | ||
15 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
16 | #include "tuner-driver.h" | 15 | #include <linux/videodev.h> |
16 | #include "tuner-i2c.h" | ||
17 | #include "tea5767.h" | ||
17 | 18 | ||
18 | #define PREFIX "TEA5767 " | 19 | static int debug = 0; |
20 | module_param(debug, int, 0644); | ||
21 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
19 | 22 | ||
20 | /* from tuner-core.c */ | 23 | #define PREFIX "tea5767 " |
21 | extern int tuner_debug; | 24 | |
25 | struct tea5767_priv { | ||
26 | struct tuner_i2c_props i2c_props; | ||
27 | |||
28 | u32 frequency; | ||
29 | }; | ||
22 | 30 | ||
23 | /*****************************************************************************/ | 31 | /*****************************************************************************/ |
24 | 32 | ||
@@ -129,13 +137,6 @@ enum tea5767_xtal_freq { | |||
129 | 137 | ||
130 | /*****************************************************************************/ | 138 | /*****************************************************************************/ |
131 | 139 | ||
132 | static void set_tv_freq(struct i2c_client *c, unsigned int freq) | ||
133 | { | ||
134 | struct tuner *t = i2c_get_clientdata(c); | ||
135 | |||
136 | tuner_warn("This tuner doesn't support TV freq.\n"); | ||
137 | } | ||
138 | |||
139 | static void tea5767_status_dump(unsigned char *buffer) | 140 | static void tea5767_status_dump(unsigned char *buffer) |
140 | { | 141 | { |
141 | unsigned int div, frq; | 142 | unsigned int div, frq; |
@@ -190,14 +191,16 @@ static void tea5767_status_dump(unsigned char *buffer) | |||
190 | } | 191 | } |
191 | 192 | ||
192 | /* Freq should be specifyed at 62.5 Hz */ | 193 | /* Freq should be specifyed at 62.5 Hz */ |
193 | static void set_radio_freq(struct i2c_client *c, unsigned int frq) | 194 | static int set_radio_freq(struct dvb_frontend *fe, |
195 | struct analog_parameters *params) | ||
194 | { | 196 | { |
195 | struct tuner *t = i2c_get_clientdata(c); | 197 | struct tea5767_priv *priv = fe->tuner_priv; |
198 | unsigned int frq = params->frequency; | ||
196 | unsigned char buffer[5]; | 199 | unsigned char buffer[5]; |
197 | unsigned div; | 200 | unsigned div; |
198 | int rc; | 201 | int rc; |
199 | 202 | ||
200 | tuner_dbg (PREFIX "radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000); | 203 | tuner_dbg("radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000); |
201 | 204 | ||
202 | /* Rounds freq to next decimal value - for 62.5 KHz step */ | 205 | /* Rounds freq to next decimal value - for 62.5 KHz step */ |
203 | /* frq = 20*(frq/16)+radio_frq[frq%16]; */ | 206 | /* frq = 20*(frq/16)+radio_frq[frq%16]; */ |
@@ -207,7 +210,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq) | |||
207 | TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND; | 210 | TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND; |
208 | buffer[4] = 0; | 211 | buffer[4] = 0; |
209 | 212 | ||
210 | if (t->audmode == V4L2_TUNER_MODE_MONO) { | 213 | if (params->audmode == V4L2_TUNER_MODE_MONO) { |
211 | tuner_dbg("TEA5767 set to mono\n"); | 214 | tuner_dbg("TEA5767 set to mono\n"); |
212 | buffer[2] |= TEA5767_MONO; | 215 | buffer[2] |= TEA5767_MONO; |
213 | } else { | 216 | } else { |
@@ -217,26 +220,26 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq) | |||
217 | /* Should be replaced */ | 220 | /* Should be replaced */ |
218 | switch (TEA5767_HIGH_LO_32768) { | 221 | switch (TEA5767_HIGH_LO_32768) { |
219 | case TEA5767_HIGH_LO_13MHz: | 222 | case TEA5767_HIGH_LO_13MHz: |
220 | tuner_dbg ("TEA5767 radio HIGH LO inject xtal @ 13 MHz\n"); | 223 | tuner_dbg("radio HIGH LO inject xtal @ 13 MHz\n"); |
221 | buffer[2] |= TEA5767_HIGH_LO_INJECT; | 224 | buffer[2] |= TEA5767_HIGH_LO_INJECT; |
222 | buffer[4] |= TEA5767_PLLREF_ENABLE; | 225 | buffer[4] |= TEA5767_PLLREF_ENABLE; |
223 | div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000; | 226 | div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000; |
224 | break; | 227 | break; |
225 | case TEA5767_LOW_LO_13MHz: | 228 | case TEA5767_LOW_LO_13MHz: |
226 | tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 13 MHz\n"); | 229 | tuner_dbg("radio LOW LO inject xtal @ 13 MHz\n"); |
227 | 230 | ||
228 | buffer[4] |= TEA5767_PLLREF_ENABLE; | 231 | buffer[4] |= TEA5767_PLLREF_ENABLE; |
229 | div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000; | 232 | div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000; |
230 | break; | 233 | break; |
231 | case TEA5767_LOW_LO_32768: | 234 | case TEA5767_LOW_LO_32768: |
232 | tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 32,768 MHz\n"); | 235 | tuner_dbg("radio LOW LO inject xtal @ 32,768 MHz\n"); |
233 | buffer[3] |= TEA5767_XTAL_32768; | 236 | buffer[3] |= TEA5767_XTAL_32768; |
234 | /* const 700=4000*175 Khz - to adjust freq to right value */ | 237 | /* const 700=4000*175 Khz - to adjust freq to right value */ |
235 | div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15; | 238 | div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15; |
236 | break; | 239 | break; |
237 | case TEA5767_HIGH_LO_32768: | 240 | case TEA5767_HIGH_LO_32768: |
238 | default: | 241 | default: |
239 | tuner_dbg ("TEA5767 radio HIGH LO inject xtal @ 32,768 MHz\n"); | 242 | tuner_dbg("radio HIGH LO inject xtal @ 32,768 MHz\n"); |
240 | 243 | ||
241 | buffer[2] |= TEA5767_HIGH_LO_INJECT; | 244 | buffer[2] |= TEA5767_HIGH_LO_INJECT; |
242 | buffer[3] |= TEA5767_XTAL_32768; | 245 | buffer[3] |= TEA5767_XTAL_32768; |
@@ -246,51 +249,89 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq) | |||
246 | buffer[0] = (div >> 8) & 0x3f; | 249 | buffer[0] = (div >> 8) & 0x3f; |
247 | buffer[1] = div & 0xff; | 250 | buffer[1] = div & 0xff; |
248 | 251 | ||
249 | if (5 != (rc = i2c_master_send(c, buffer, 5))) | 252 | if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5))) |
250 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | 253 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); |
251 | 254 | ||
252 | if (tuner_debug) { | 255 | if (debug) { |
253 | if (5 != (rc = i2c_master_recv(c, buffer, 5))) | 256 | if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) |
254 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | 257 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); |
255 | else | 258 | else |
256 | tea5767_status_dump(buffer); | 259 | tea5767_status_dump(buffer); |
257 | } | 260 | } |
261 | |||
262 | priv->frequency = frq * 125 / 2; | ||
263 | |||
264 | return 0; | ||
258 | } | 265 | } |
259 | 266 | ||
260 | static int tea5767_signal(struct i2c_client *c) | 267 | static int tea5767_read_status(struct dvb_frontend *fe, char *buffer) |
261 | { | 268 | { |
262 | unsigned char buffer[5]; | 269 | struct tea5767_priv *priv = fe->tuner_priv; |
263 | int rc; | 270 | int rc; |
264 | struct tuner *t = i2c_get_clientdata(c); | ||
265 | 271 | ||
266 | memset(buffer, 0, sizeof(buffer)); | 272 | memset(buffer, 0, 5); |
267 | if (5 != (rc = i2c_master_recv(c, buffer, 5))) | 273 | if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) { |
268 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | 274 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); |
275 | return -EREMOTEIO; | ||
276 | } | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static inline int tea5767_signal(struct dvb_frontend *fe, const char *buffer) | ||
282 | { | ||
283 | struct tea5767_priv *priv = fe->tuner_priv; | ||
284 | |||
285 | int signal = ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8); | ||
286 | |||
287 | tuner_dbg("Signal strength: %d\n", signal); | ||
288 | |||
289 | return signal; | ||
290 | } | ||
291 | |||
292 | static inline int tea5767_stereo(struct dvb_frontend *fe, const char *buffer) | ||
293 | { | ||
294 | struct tea5767_priv *priv = fe->tuner_priv; | ||
295 | |||
296 | int stereo = buffer[2] & TEA5767_STEREO_MASK; | ||
297 | |||
298 | tuner_dbg("Radio ST GET = %02x\n", stereo); | ||
269 | 299 | ||
270 | return ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8); | 300 | return (stereo ? V4L2_TUNER_SUB_STEREO : 0); |
271 | } | 301 | } |
272 | 302 | ||
273 | static int tea5767_stereo(struct i2c_client *c) | 303 | static int tea5767_get_status(struct dvb_frontend *fe, u32 *status) |
274 | { | 304 | { |
275 | unsigned char buffer[5]; | 305 | unsigned char buffer[5]; |
276 | int rc; | ||
277 | struct tuner *t = i2c_get_clientdata(c); | ||
278 | 306 | ||
279 | memset(buffer, 0, sizeof(buffer)); | 307 | *status = 0; |
280 | if (5 != (rc = i2c_master_recv(c, buffer, 5))) | 308 | |
281 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | 309 | if (0 == tea5767_read_status(fe, buffer)) { |
310 | if (tea5767_signal(fe, buffer)) | ||
311 | *status = TUNER_STATUS_LOCKED; | ||
312 | if (tea5767_stereo(fe, buffer)) | ||
313 | *status |= TUNER_STATUS_STEREO; | ||
314 | } | ||
315 | |||
316 | return 0; | ||
317 | } | ||
282 | 318 | ||
283 | rc = buffer[2] & TEA5767_STEREO_MASK; | 319 | static int tea5767_get_rf_strength(struct dvb_frontend *fe, u16 *strength) |
320 | { | ||
321 | unsigned char buffer[5]; | ||
284 | 322 | ||
285 | tuner_dbg("TEA5767 radio ST GET = %02x\n", rc); | 323 | *strength = 0; |
286 | 324 | ||
287 | return ((buffer[2] & TEA5767_STEREO_MASK) ? V4L2_TUNER_SUB_STEREO : 0); | 325 | if (0 == tea5767_read_status(fe, buffer)) |
326 | *strength = tea5767_signal(fe, buffer); | ||
327 | |||
328 | return 0; | ||
288 | } | 329 | } |
289 | 330 | ||
290 | static void tea5767_standby(struct i2c_client *c) | 331 | static int tea5767_standby(struct dvb_frontend *fe) |
291 | { | 332 | { |
292 | unsigned char buffer[5]; | 333 | unsigned char buffer[5]; |
293 | struct tuner *t = i2c_get_clientdata(c); | 334 | struct tea5767_priv *priv = fe->tuner_priv; |
294 | unsigned div, rc; | 335 | unsigned div, rc; |
295 | 336 | ||
296 | div = (87500 * 4 + 700 + 225 + 25) / 50; /* Set frequency to 87.5 MHz */ | 337 | div = (87500 * 4 + 700 + 225 + 25) / 50; /* Set frequency to 87.5 MHz */ |
@@ -301,25 +342,27 @@ static void tea5767_standby(struct i2c_client *c) | |||
301 | TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND | TEA5767_STDBY; | 342 | TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND | TEA5767_STDBY; |
302 | buffer[4] = 0; | 343 | buffer[4] = 0; |
303 | 344 | ||
304 | if (5 != (rc = i2c_master_send(c, buffer, 5))) | 345 | if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5))) |
305 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | 346 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); |
347 | |||
348 | return 0; | ||
306 | } | 349 | } |
307 | 350 | ||
308 | int tea5767_autodetection(struct i2c_client *c) | 351 | int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr) |
309 | { | 352 | { |
353 | struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr }; | ||
310 | unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 354 | unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
311 | int rc; | 355 | int rc; |
312 | struct tuner *t = i2c_get_clientdata(c); | ||
313 | 356 | ||
314 | if ((rc = i2c_master_recv(c, buffer, 7))< 5) { | 357 | if ((rc = tuner_i2c_xfer_recv(&i2c, buffer, 7))< 5) { |
315 | tuner_warn("It is not a TEA5767. Received %i bytes.\n", rc); | 358 | printk(KERN_WARNING "It is not a TEA5767. Received %i bytes.\n", rc); |
316 | return EINVAL; | 359 | return EINVAL; |
317 | } | 360 | } |
318 | 361 | ||
319 | /* If all bytes are the same then it's a TV tuner and not a tea5767 */ | 362 | /* If all bytes are the same then it's a TV tuner and not a tea5767 */ |
320 | if (buffer[0] == buffer[1] && buffer[0] == buffer[2] && | 363 | if (buffer[0] == buffer[1] && buffer[0] == buffer[2] && |
321 | buffer[0] == buffer[3] && buffer[0] == buffer[4]) { | 364 | buffer[0] == buffer[3] && buffer[0] == buffer[4]) { |
322 | tuner_warn("All bytes are equal. It is not a TEA5767\n"); | 365 | printk(KERN_WARNING "All bytes are equal. It is not a TEA5767\n"); |
323 | return EINVAL; | 366 | return EINVAL; |
324 | } | 367 | } |
325 | 368 | ||
@@ -329,36 +372,74 @@ int tea5767_autodetection(struct i2c_client *c) | |||
329 | * Byte 5: bit 7:0 : == 0 | 372 | * Byte 5: bit 7:0 : == 0 |
330 | */ | 373 | */ |
331 | if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) { | 374 | if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) { |
332 | tuner_warn("Chip ID is not zero. It is not a TEA5767\n"); | 375 | printk(KERN_WARNING "Chip ID is not zero. It is not a TEA5767\n"); |
333 | return EINVAL; | 376 | return EINVAL; |
334 | } | 377 | } |
335 | 378 | ||
336 | /* It seems that tea5767 returns 0xff after the 5th byte */ | 379 | /* It seems that tea5767 returns 0xff after the 5th byte */ |
337 | if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) { | 380 | if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) { |
338 | tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n"); | 381 | printk(KERN_WARNING "Returned more than 5 bytes. It is not a TEA5767\n"); |
339 | return EINVAL; | 382 | return EINVAL; |
340 | } | 383 | } |
341 | 384 | ||
342 | tuner_warn("TEA5767 detected.\n"); | 385 | printk(KERN_WARNING "TEA5767 detected.\n"); |
343 | return 0; | 386 | return 0; |
344 | } | 387 | } |
345 | 388 | ||
346 | static struct tuner_operations tea5767_tuner_ops = { | 389 | static int tea5767_release(struct dvb_frontend *fe) |
347 | .set_tv_freq = set_tv_freq, | 390 | { |
348 | .set_radio_freq = set_radio_freq, | 391 | kfree(fe->tuner_priv); |
349 | .has_signal = tea5767_signal, | 392 | fe->tuner_priv = NULL; |
350 | .is_stereo = tea5767_stereo, | 393 | |
351 | .standby = tea5767_standby, | 394 | return 0; |
395 | } | ||
396 | |||
397 | static int tea5767_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
398 | { | ||
399 | struct tea5767_priv *priv = fe->tuner_priv; | ||
400 | *frequency = priv->frequency; | ||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static struct dvb_tuner_ops tea5767_tuner_ops = { | ||
405 | .info = { | ||
406 | .name = "tea5767", // Philips TEA5767HN FM Radio | ||
407 | }, | ||
408 | |||
409 | .set_analog_params = set_radio_freq, | ||
410 | .sleep = tea5767_standby, | ||
411 | .release = tea5767_release, | ||
412 | .get_frequency = tea5767_get_frequency, | ||
413 | .get_status = tea5767_get_status, | ||
414 | .get_rf_strength = tea5767_get_rf_strength, | ||
352 | }; | 415 | }; |
353 | 416 | ||
354 | int tea5767_tuner_init(struct i2c_client *c) | 417 | struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, |
418 | struct i2c_adapter* i2c_adap, | ||
419 | u8 i2c_addr) | ||
355 | { | 420 | { |
356 | struct tuner *t = i2c_get_clientdata(c); | 421 | struct tea5767_priv *priv = NULL; |
422 | |||
423 | priv = kzalloc(sizeof(struct tea5767_priv), GFP_KERNEL); | ||
424 | if (priv == NULL) | ||
425 | return NULL; | ||
426 | fe->tuner_priv = priv; | ||
427 | |||
428 | priv->i2c_props.addr = i2c_addr; | ||
429 | priv->i2c_props.adap = i2c_adap; | ||
357 | 430 | ||
358 | tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio"); | 431 | memcpy(&fe->ops.tuner_ops, &tea5767_tuner_ops, |
359 | strlcpy(c->name, "tea5767", sizeof(c->name)); | 432 | sizeof(struct dvb_tuner_ops)); |
360 | 433 | ||
361 | memcpy(&t->ops, &tea5767_tuner_ops, sizeof(struct tuner_operations)); | 434 | tuner_info("type set to %s\n", "Philips TEA5767HN FM Radio"); |
362 | 435 | ||
363 | return (0); | 436 | return fe; |
364 | } | 437 | } |
438 | |||
439 | |||
440 | EXPORT_SYMBOL_GPL(tea5767_attach); | ||
441 | EXPORT_SYMBOL_GPL(tea5767_autodetection); | ||
442 | |||
443 | MODULE_DESCRIPTION("Philips TEA5767 FM tuner driver"); | ||
444 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | ||
445 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/tea5767.h b/drivers/media/video/tea5767.h new file mode 100644 index 000000000000..5d78281adcc2 --- /dev/null +++ b/drivers/media/video/tea5767.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | This program is free software; you can redistribute it and/or modify | ||
3 | it under the terms of the GNU General Public License as published by | ||
4 | the Free Software Foundation; either version 2 of the License, or | ||
5 | (at your option) any later version. | ||
6 | |||
7 | This program is distributed in the hope that it will be useful, | ||
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | GNU General Public License for more details. | ||
11 | |||
12 | You should have received a copy of the GNU General Public License | ||
13 | along with this program; if not, write to the Free Software | ||
14 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
15 | */ | ||
16 | |||
17 | #ifndef __TEA5767_H__ | ||
18 | #define __TEA5767_H__ | ||
19 | |||
20 | #include <linux/i2c.h> | ||
21 | #include "dvb_frontend.h" | ||
22 | |||
23 | #if defined(CONFIG_TUNER_TEA5767) || (defined(CONFIG_TUNER_TEA5767_MODULE) && defined(MODULE)) | ||
24 | extern int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr); | ||
25 | |||
26 | extern struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, | ||
27 | struct i2c_adapter* i2c_adap, | ||
28 | u8 i2c_addr); | ||
29 | #else | ||
30 | static inline int tea5767_autodetection(struct i2c_adapter* i2c_adap, | ||
31 | u8 i2c_addr) | ||
32 | { | ||
33 | printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", | ||
34 | __FUNCTION__); | ||
35 | return -EINVAL; | ||
36 | } | ||
37 | |||
38 | static inline struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, | ||
39 | struct i2c_adapter* i2c_adap, | ||
40 | u8 i2c_addr) | ||
41 | { | ||
42 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | ||
43 | return NULL; | ||
44 | } | ||
45 | #endif | ||
46 | |||
47 | #endif /* __TEA5767_H__ */ | ||
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index e646465464a1..94843086cda9 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -5,7 +5,6 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/moduleparam.h> | ||
9 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
10 | #include <linux/string.h> | 9 | #include <linux/string.h> |
11 | #include <linux/timer.h> | 10 | #include <linux/timer.h> |
@@ -15,12 +14,17 @@ | |||
15 | #include <linux/poll.h> | 14 | #include <linux/poll.h> |
16 | #include <linux/i2c.h> | 15 | #include <linux/i2c.h> |
17 | #include <linux/types.h> | 16 | #include <linux/types.h> |
18 | #include <linux/videodev.h> | ||
19 | #include <linux/init.h> | 17 | #include <linux/init.h> |
20 | 18 | #include <linux/videodev.h> | |
21 | #include <media/tuner.h> | 19 | #include <media/tuner.h> |
20 | #include <media/tuner-types.h> | ||
22 | #include <media/v4l2-common.h> | 21 | #include <media/v4l2-common.h> |
23 | #include "tuner-driver.h" | 22 | #include "tuner-driver.h" |
23 | #include "mt20xx.h" | ||
24 | #include "tda8290.h" | ||
25 | #include "tea5761.h" | ||
26 | #include "tea5767.h" | ||
27 | #include "tuner-simple.h" | ||
24 | 28 | ||
25 | #define UNSET (-1U) | 29 | #define UNSET (-1U) |
26 | 30 | ||
@@ -72,6 +76,51 @@ static struct i2c_client client_template; | |||
72 | 76 | ||
73 | /* ---------------------------------------------------------------------- */ | 77 | /* ---------------------------------------------------------------------- */ |
74 | 78 | ||
79 | static void fe_set_freq(struct tuner *t, unsigned int freq) | ||
80 | { | ||
81 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; | ||
82 | |||
83 | struct analog_parameters params = { | ||
84 | .frequency = freq, | ||
85 | .mode = t->mode, | ||
86 | .audmode = t->audmode, | ||
87 | .std = t->std | ||
88 | }; | ||
89 | |||
90 | if (NULL == fe_tuner_ops->set_analog_params) { | ||
91 | tuner_warn("Tuner frontend module has no way to set freq\n"); | ||
92 | return; | ||
93 | } | ||
94 | fe_tuner_ops->set_analog_params(&t->fe, ¶ms); | ||
95 | } | ||
96 | |||
97 | static void fe_release(struct tuner *t) | ||
98 | { | ||
99 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; | ||
100 | |||
101 | if (fe_tuner_ops->release) | ||
102 | fe_tuner_ops->release(&t->fe); | ||
103 | } | ||
104 | |||
105 | static void fe_standby(struct tuner *t) | ||
106 | { | ||
107 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; | ||
108 | |||
109 | if (fe_tuner_ops->sleep) | ||
110 | fe_tuner_ops->sleep(&t->fe); | ||
111 | } | ||
112 | |||
113 | static int fe_has_signal(struct tuner *t) | ||
114 | { | ||
115 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; | ||
116 | u16 strength; | ||
117 | |||
118 | if (fe_tuner_ops->get_rf_strength) | ||
119 | fe_tuner_ops->get_rf_strength(&t->fe, &strength); | ||
120 | |||
121 | return strength; | ||
122 | } | ||
123 | |||
75 | /* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */ | 124 | /* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */ |
76 | static void set_tv_freq(struct i2c_client *c, unsigned int freq) | 125 | static void set_tv_freq(struct i2c_client *c, unsigned int freq) |
77 | { | 126 | { |
@@ -96,7 +145,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
96 | else | 145 | else |
97 | freq = tv_range[1] * 16; | 146 | freq = tv_range[1] * 16; |
98 | } | 147 | } |
99 | t->ops.set_tv_freq(c, freq); | 148 | t->ops.set_tv_freq(t, freq); |
100 | } | 149 | } |
101 | 150 | ||
102 | static void set_radio_freq(struct i2c_client *c, unsigned int freq) | 151 | static void set_radio_freq(struct i2c_client *c, unsigned int freq) |
@@ -123,7 +172,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) | |||
123 | freq = radio_range[1] * 16000; | 172 | freq = radio_range[1] * 16000; |
124 | } | 173 | } |
125 | 174 | ||
126 | t->ops.set_radio_freq(c, freq); | 175 | t->ops.set_radio_freq(t, freq); |
127 | } | 176 | } |
128 | 177 | ||
129 | static void set_freq(struct i2c_client *c, unsigned long freq) | 178 | static void set_freq(struct i2c_client *c, unsigned long freq) |
@@ -147,11 +196,51 @@ static void set_freq(struct i2c_client *c, unsigned long freq) | |||
147 | } | 196 | } |
148 | } | 197 | } |
149 | 198 | ||
199 | static void tuner_i2c_address_check(struct tuner *t) | ||
200 | { | ||
201 | if ((t->type == UNSET || t->type == TUNER_ABSENT) || | ||
202 | ((t->i2c.addr < 0x64) || (t->i2c.addr > 0x6f))) | ||
203 | return; | ||
204 | |||
205 | tuner_warn("====================== WARNING! ======================\n"); | ||
206 | tuner_warn("Support for tuners in i2c address range 0x64 thru 0x6f\n"); | ||
207 | tuner_warn("will soon be dropped. This message indicates that your\n"); | ||
208 | tuner_warn("hardware has a %s tuner at i2c address 0x%02x.\n", | ||
209 | t->i2c.name, t->i2c.addr); | ||
210 | tuner_warn("To ensure continued support for your device, please\n"); | ||
211 | tuner_warn("send a copy of this message, along with full dmesg\n"); | ||
212 | tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n"); | ||
213 | tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n"); | ||
214 | tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n", | ||
215 | t->i2c.adapter->name, t->i2c.addr, t->type, | ||
216 | tuners[t->type].name); | ||
217 | tuner_warn("====================== WARNING! ======================\n"); | ||
218 | } | ||
219 | |||
220 | static void attach_tda8290(struct tuner *t) | ||
221 | { | ||
222 | struct tda8290_config cfg = { | ||
223 | .lna_cfg = &t->config, | ||
224 | .tuner_callback = t->tuner_callback | ||
225 | }; | ||
226 | tda8290_attach(&t->fe, t->i2c.adapter, t->i2c.addr, &cfg); | ||
227 | } | ||
228 | |||
229 | static void attach_simple_tuner(struct tuner *t) | ||
230 | { | ||
231 | struct simple_tuner_config cfg = { | ||
232 | .type = t->type, | ||
233 | .tun = &tuners[t->type] | ||
234 | }; | ||
235 | simple_tuner_attach(&t->fe, t->i2c.adapter, t->i2c.addr, &cfg); | ||
236 | } | ||
237 | |||
150 | static void set_type(struct i2c_client *c, unsigned int type, | 238 | static void set_type(struct i2c_client *c, unsigned int type, |
151 | unsigned int new_mode_mask, unsigned int new_config, | 239 | unsigned int new_mode_mask, unsigned int new_config, |
152 | int (*tuner_callback) (void *dev, int command,int arg)) | 240 | int (*tuner_callback) (void *dev, int command,int arg)) |
153 | { | 241 | { |
154 | struct tuner *t = i2c_get_clientdata(c); | 242 | struct tuner *t = i2c_get_clientdata(c); |
243 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; | ||
155 | unsigned char buffer[4]; | 244 | unsigned char buffer[4]; |
156 | 245 | ||
157 | if (type == UNSET || type == TUNER_ABSENT) { | 246 | if (type == UNSET || type == TUNER_ABSENT) { |
@@ -180,7 +269,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
180 | 269 | ||
181 | /* discard private data, in case set_type() was previously called */ | 270 | /* discard private data, in case set_type() was previously called */ |
182 | if (t->ops.release) | 271 | if (t->ops.release) |
183 | t->ops.release(c); | 272 | t->ops.release(t); |
184 | else { | 273 | else { |
185 | kfree(t->priv); | 274 | kfree(t->priv); |
186 | t->priv = NULL; | 275 | t->priv = NULL; |
@@ -188,13 +277,15 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
188 | 277 | ||
189 | switch (t->type) { | 278 | switch (t->type) { |
190 | case TUNER_MT2032: | 279 | case TUNER_MT2032: |
191 | microtune_init(c); | 280 | microtune_attach(&t->fe, t->i2c.adapter, t->i2c.addr); |
192 | break; | 281 | break; |
193 | case TUNER_PHILIPS_TDA8290: | 282 | case TUNER_PHILIPS_TDA8290: |
194 | tda8290_init(c); | 283 | { |
284 | attach_tda8290(t); | ||
195 | break; | 285 | break; |
286 | } | ||
196 | case TUNER_TEA5767: | 287 | case TUNER_TEA5767: |
197 | if (tea5767_tuner_init(c) == EINVAL) { | 288 | if (tea5767_attach(&t->fe, t->i2c.adapter, t->i2c.addr) == NULL) { |
198 | t->type = TUNER_ABSENT; | 289 | t->type = TUNER_ABSENT; |
199 | t->mode_mask = T_UNINITIALIZED; | 290 | t->mode_mask = T_UNINITIALIZED; |
200 | return; | 291 | return; |
@@ -203,7 +294,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
203 | break; | 294 | break; |
204 | #ifdef CONFIG_TUNER_TEA5761 | 295 | #ifdef CONFIG_TUNER_TEA5761 |
205 | case TUNER_TEA5761: | 296 | case TUNER_TEA5761: |
206 | if (tea5761_tuner_init(c) == EINVAL) { | 297 | if (tea5761_attach(&t->fe, t->i2c.adapter, t->i2c.addr) == NULL) { |
207 | t->type = TUNER_ABSENT; | 298 | t->type = TUNER_ABSENT; |
208 | t->mode_mask = T_UNINITIALIZED; | 299 | t->mode_mask = T_UNINITIALIZED; |
209 | return; | 300 | return; |
@@ -221,7 +312,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
221 | buffer[2] = 0x86; | 312 | buffer[2] = 0x86; |
222 | buffer[3] = 0x54; | 313 | buffer[3] = 0x54; |
223 | i2c_master_send(c, buffer, 4); | 314 | i2c_master_send(c, buffer, 4); |
224 | default_tuner_init(c); | 315 | attach_simple_tuner(t); |
225 | break; | 316 | break; |
226 | case TUNER_PHILIPS_TD1316: | 317 | case TUNER_PHILIPS_TD1316: |
227 | buffer[0] = 0x0b; | 318 | buffer[0] = 0x0b; |
@@ -229,16 +320,28 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
229 | buffer[2] = 0x86; | 320 | buffer[2] = 0x86; |
230 | buffer[3] = 0xa4; | 321 | buffer[3] = 0xa4; |
231 | i2c_master_send(c,buffer,4); | 322 | i2c_master_send(c,buffer,4); |
232 | default_tuner_init(c); | 323 | attach_simple_tuner(t); |
233 | break; | 324 | break; |
234 | case TUNER_TDA9887: | 325 | case TUNER_TDA9887: |
235 | tda9887_tuner_init(c); | 326 | tda9887_tuner_init(t); |
236 | break; | 327 | break; |
237 | default: | 328 | default: |
238 | default_tuner_init(c); | 329 | attach_simple_tuner(t); |
239 | break; | 330 | break; |
240 | } | 331 | } |
241 | 332 | ||
333 | if (fe_tuner_ops->set_analog_params) { | ||
334 | strlcpy(t->i2c.name, fe_tuner_ops->info.name, sizeof(t->i2c.name)); | ||
335 | |||
336 | t->ops.set_tv_freq = fe_set_freq; | ||
337 | t->ops.set_radio_freq = fe_set_freq; | ||
338 | t->ops.standby = fe_standby; | ||
339 | t->ops.release = fe_release; | ||
340 | t->ops.has_signal = fe_has_signal; | ||
341 | } | ||
342 | |||
343 | tuner_info("type set to %s\n", t->i2c.name); | ||
344 | |||
242 | if (t->mode_mask == T_UNINITIALIZED) | 345 | if (t->mode_mask == T_UNINITIALIZED) |
243 | t->mode_mask = new_mode_mask; | 346 | t->mode_mask = new_mode_mask; |
244 | 347 | ||
@@ -246,6 +349,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
246 | tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n", | 349 | tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n", |
247 | c->adapter->name, c->driver->driver.name, c->addr << 1, type, | 350 | c->adapter->name, c->driver->driver.name, c->addr << 1, type, |
248 | t->mode_mask); | 351 | t->mode_mask); |
352 | tuner_i2c_address_check(t); | ||
249 | } | 353 | } |
250 | 354 | ||
251 | /* | 355 | /* |
@@ -406,10 +510,10 @@ static int tuner_fixup_std(struct tuner *t) | |||
406 | return 0; | 510 | return 0; |
407 | } | 511 | } |
408 | 512 | ||
409 | static void tuner_status(struct i2c_client *client) | 513 | static void tuner_status(struct tuner *t) |
410 | { | 514 | { |
411 | struct tuner *t = i2c_get_clientdata(client); | ||
412 | unsigned long freq, freq_fraction; | 515 | unsigned long freq, freq_fraction; |
516 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; | ||
413 | const char *p; | 517 | const char *p; |
414 | 518 | ||
415 | switch (t->mode) { | 519 | switch (t->mode) { |
@@ -430,11 +534,20 @@ static void tuner_status(struct i2c_client *client) | |||
430 | tuner_info("Standard: 0x%08lx\n", (unsigned long)t->std); | 534 | tuner_info("Standard: 0x%08lx\n", (unsigned long)t->std); |
431 | if (t->mode != V4L2_TUNER_RADIO) | 535 | if (t->mode != V4L2_TUNER_RADIO) |
432 | return; | 536 | return; |
537 | if (fe_tuner_ops->get_status) { | ||
538 | u32 tuner_status; | ||
539 | |||
540 | fe_tuner_ops->get_status(&t->fe, &tuner_status); | ||
541 | if (tuner_status & TUNER_STATUS_LOCKED) | ||
542 | tuner_info("Tuner is locked.\n"); | ||
543 | if (tuner_status & TUNER_STATUS_STEREO) | ||
544 | tuner_info("Stereo: yes\n"); | ||
545 | } | ||
433 | if (t->ops.has_signal) { | 546 | if (t->ops.has_signal) { |
434 | tuner_info("Signal strength: %d\n", t->ops.has_signal(client)); | 547 | tuner_info("Signal strength: %d\n", t->ops.has_signal(t)); |
435 | } | 548 | } |
436 | if (t->ops.is_stereo) { | 549 | if (t->ops.is_stereo) { |
437 | tuner_info("Stereo: %s\n", t->ops.is_stereo(client) ? "yes" : "no"); | 550 | tuner_info("Stereo: %s\n", t->ops.is_stereo(t) ? "yes" : "no"); |
438 | } | 551 | } |
439 | } | 552 | } |
440 | 553 | ||
@@ -483,7 +596,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
483 | switch (addr) { | 596 | switch (addr) { |
484 | #ifdef CONFIG_TUNER_TEA5761 | 597 | #ifdef CONFIG_TUNER_TEA5761 |
485 | case 0x10: | 598 | case 0x10: |
486 | if (tea5761_autodetection(&t->i2c) != EINVAL) { | 599 | if (tea5761_autodetection(t->i2c.adapter, t->i2c.addr) != EINVAL) { |
487 | t->type = TUNER_TEA5761; | 600 | t->type = TUNER_TEA5761; |
488 | t->mode_mask = T_RADIO; | 601 | t->mode_mask = T_RADIO; |
489 | t->mode = T_STANDBY; | 602 | t->mode = T_STANDBY; |
@@ -500,7 +613,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
500 | case 0x4b: | 613 | case 0x4b: |
501 | /* If chip is not tda8290, don't register. | 614 | /* If chip is not tda8290, don't register. |
502 | since it can be tda9887*/ | 615 | since it can be tda9887*/ |
503 | if (tda8290_probe(&t->i2c) == 0) { | 616 | if (tda8290_probe(t->i2c.adapter, t->i2c.addr) == 0) { |
504 | tuner_dbg("chip at addr %x is a tda8290\n", addr); | 617 | tuner_dbg("chip at addr %x is a tda8290\n", addr); |
505 | } else { | 618 | } else { |
506 | /* Default is being tda9887 */ | 619 | /* Default is being tda9887 */ |
@@ -511,7 +624,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
511 | } | 624 | } |
512 | break; | 625 | break; |
513 | case 0x60: | 626 | case 0x60: |
514 | if (tea5767_autodetection(&t->i2c) != EINVAL) { | 627 | if (tea5767_autodetection(t->i2c.adapter, t->i2c.addr) != EINVAL) { |
515 | t->type = TUNER_TEA5767; | 628 | t->type = TUNER_TEA5767; |
516 | t->mode_mask = T_RADIO; | 629 | t->mode_mask = T_RADIO; |
517 | t->mode = T_STANDBY; | 630 | t->mode = T_STANDBY; |
@@ -548,6 +661,28 @@ static int tuner_probe(struct i2c_adapter *adap) | |||
548 | normal_i2c[1] = I2C_CLIENT_END; | 661 | normal_i2c[1] = I2C_CLIENT_END; |
549 | } | 662 | } |
550 | 663 | ||
664 | /* HACK: Ignore 0x6b and 0x6f on cx88 boards. | ||
665 | * FusionHDTV5 RT Gold has an ir receiver at 0x6b | ||
666 | * and an RTC at 0x6f which can get corrupted if probed. | ||
667 | */ | ||
668 | if ((adap->id == I2C_HW_B_CX2388x) || | ||
669 | (adap->id == I2C_HW_B_CX23885)) { | ||
670 | unsigned int i = 0; | ||
671 | |||
672 | while (i < I2C_CLIENT_MAX_OPTS && ignore[i] != I2C_CLIENT_END) | ||
673 | i += 2; | ||
674 | if (i + 4 < I2C_CLIENT_MAX_OPTS) { | ||
675 | ignore[i+0] = adap->nr; | ||
676 | ignore[i+1] = 0x6b; | ||
677 | ignore[i+2] = adap->nr; | ||
678 | ignore[i+3] = 0x6f; | ||
679 | ignore[i+4] = I2C_CLIENT_END; | ||
680 | } else | ||
681 | printk(KERN_WARNING "tuner: " | ||
682 | "too many options specified " | ||
683 | "in i2c probe ignore list!\n"); | ||
684 | } | ||
685 | |||
551 | default_mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; | 686 | default_mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; |
552 | 687 | ||
553 | if (adap->class & I2C_CLASS_TV_ANALOG) | 688 | if (adap->class & I2C_CLASS_TV_ANALOG) |
@@ -568,7 +703,7 @@ static int tuner_detach(struct i2c_client *client) | |||
568 | } | 703 | } |
569 | 704 | ||
570 | if (t->ops.release) | 705 | if (t->ops.release) |
571 | t->ops.release(client); | 706 | t->ops.release(t); |
572 | else { | 707 | else { |
573 | kfree(t->priv); | 708 | kfree(t->priv); |
574 | } | 709 | } |
@@ -593,7 +728,7 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, | |||
593 | if (check_mode(t, cmd) == EINVAL) { | 728 | if (check_mode(t, cmd) == EINVAL) { |
594 | t->mode = T_STANDBY; | 729 | t->mode = T_STANDBY; |
595 | if (t->ops.standby) | 730 | if (t->ops.standby) |
596 | t->ops.standby (client); | 731 | t->ops.standby(t); |
597 | return EINVAL; | 732 | return EINVAL; |
598 | } | 733 | } |
599 | return 0; | 734 | return 0; |
@@ -615,6 +750,7 @@ static inline int check_v4l2(struct tuner *t) | |||
615 | static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | 750 | static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) |
616 | { | 751 | { |
617 | struct tuner *t = i2c_get_clientdata(client); | 752 | struct tuner *t = i2c_get_clientdata(client); |
753 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; | ||
618 | 754 | ||
619 | if (tuner_debug>1) | 755 | if (tuner_debug>1) |
620 | v4l_i2c_print_ioctl(&(t->i2c),cmd); | 756 | v4l_i2c_print_ioctl(&(t->i2c),cmd); |
@@ -642,7 +778,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
642 | return 0; | 778 | return 0; |
643 | t->mode = T_STANDBY; | 779 | t->mode = T_STANDBY; |
644 | if (t->ops.standby) | 780 | if (t->ops.standby) |
645 | t->ops.standby (client); | 781 | t->ops.standby(t); |
646 | break; | 782 | break; |
647 | #ifdef CONFIG_VIDEO_V4L1 | 783 | #ifdef CONFIG_VIDEO_V4L1 |
648 | case VIDIOCSAUDIO: | 784 | case VIDIOCSAUDIO: |
@@ -701,16 +837,27 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
701 | return 0; | 837 | return 0; |
702 | 838 | ||
703 | if (V4L2_TUNER_RADIO == t->mode) { | 839 | if (V4L2_TUNER_RADIO == t->mode) { |
704 | if (t->ops.has_signal) | 840 | if (fe_tuner_ops->get_status) { |
705 | vt->signal = t->ops.has_signal(client); | 841 | u32 tuner_status; |
706 | if (t->ops.is_stereo) { | 842 | |
707 | if (t->ops.is_stereo(client)) | 843 | fe_tuner_ops->get_status(&t->fe, &tuner_status); |
708 | vt->flags |= | 844 | if (tuner_status & TUNER_STATUS_STEREO) |
709 | VIDEO_TUNER_STEREO_ON; | 845 | vt->flags |= VIDEO_TUNER_STEREO_ON; |
710 | else | 846 | else |
711 | vt->flags &= | 847 | vt->flags &= ~VIDEO_TUNER_STEREO_ON; |
712 | ~VIDEO_TUNER_STEREO_ON; | 848 | } else { |
849 | if (t->ops.is_stereo) { | ||
850 | if (t->ops.is_stereo(t)) | ||
851 | vt->flags |= | ||
852 | VIDEO_TUNER_STEREO_ON; | ||
853 | else | ||
854 | vt->flags &= | ||
855 | ~VIDEO_TUNER_STEREO_ON; | ||
856 | } | ||
713 | } | 857 | } |
858 | if (t->ops.has_signal) | ||
859 | vt->signal = t->ops.has_signal(t); | ||
860 | |||
714 | vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */ | 861 | vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */ |
715 | 862 | ||
716 | vt->rangelow = radio_range[0] * 16000; | 863 | vt->rangelow = radio_range[0] * 16000; |
@@ -732,9 +879,17 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
732 | if (check_v4l2(t) == EINVAL) | 879 | if (check_v4l2(t) == EINVAL) |
733 | return 0; | 880 | return 0; |
734 | 881 | ||
735 | if (V4L2_TUNER_RADIO == t->mode && t->ops.is_stereo) | 882 | if (V4L2_TUNER_RADIO == t->mode) { |
736 | va->mode = t->ops.is_stereo(client) | 883 | if (fe_tuner_ops->get_status) { |
737 | ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; | 884 | u32 tuner_status; |
885 | |||
886 | fe_tuner_ops->get_status(&t->fe, &tuner_status); | ||
887 | va->mode = (tuner_status & TUNER_STATUS_STEREO) | ||
888 | ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; | ||
889 | } else if (t->ops.is_stereo) | ||
890 | va->mode = t->ops.is_stereo(t) | ||
891 | ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; | ||
892 | } | ||
738 | return 0; | 893 | return 0; |
739 | } | 894 | } |
740 | #endif | 895 | #endif |
@@ -785,6 +940,15 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
785 | return 0; | 940 | return 0; |
786 | switch_v4l2(); | 941 | switch_v4l2(); |
787 | f->type = t->mode; | 942 | f->type = t->mode; |
943 | if (fe_tuner_ops->get_frequency) { | ||
944 | u32 abs_freq; | ||
945 | |||
946 | fe_tuner_ops->get_frequency(&t->fe, &abs_freq); | ||
947 | f->frequency = (V4L2_TUNER_RADIO == t->mode) ? | ||
948 | (abs_freq * 2 + 125/2) / 125 : | ||
949 | (abs_freq + 62500/2) / 62500; | ||
950 | break; | ||
951 | } | ||
788 | f->frequency = (V4L2_TUNER_RADIO == t->mode) ? | 952 | f->frequency = (V4L2_TUNER_RADIO == t->mode) ? |
789 | t->radio_freq : t->tv_freq; | 953 | t->radio_freq : t->tv_freq; |
790 | break; | 954 | break; |
@@ -799,7 +963,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
799 | 963 | ||
800 | tuner->type = t->mode; | 964 | tuner->type = t->mode; |
801 | if (t->ops.get_afc) | 965 | if (t->ops.get_afc) |
802 | tuner->afc=t->ops.get_afc(client); | 966 | tuner->afc=t->ops.get_afc(t); |
803 | if (t->mode == V4L2_TUNER_ANALOG_TV) | 967 | if (t->mode == V4L2_TUNER_ANALOG_TV) |
804 | tuner->capability |= V4L2_TUNER_CAP_NORM; | 968 | tuner->capability |= V4L2_TUNER_CAP_NORM; |
805 | if (t->mode != V4L2_TUNER_RADIO) { | 969 | if (t->mode != V4L2_TUNER_RADIO) { |
@@ -809,16 +973,22 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
809 | } | 973 | } |
810 | 974 | ||
811 | /* radio mode */ | 975 | /* radio mode */ |
812 | if (t->ops.has_signal) | ||
813 | tuner->signal = t->ops.has_signal(client); | ||
814 | |||
815 | tuner->rxsubchans = | 976 | tuner->rxsubchans = |
816 | V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | 977 | V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; |
817 | if (t->ops.is_stereo) { | 978 | if (fe_tuner_ops->get_status) { |
818 | tuner->rxsubchans = t->ops.is_stereo(client) ? | 979 | u32 tuner_status; |
980 | |||
981 | fe_tuner_ops->get_status(&t->fe, &tuner_status); | ||
982 | tuner->rxsubchans = (tuner_status & TUNER_STATUS_STEREO) ? | ||
819 | V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; | 983 | V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; |
984 | } else { | ||
985 | if (t->ops.is_stereo) { | ||
986 | tuner->rxsubchans = t->ops.is_stereo(t) ? | ||
987 | V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; | ||
988 | } | ||
820 | } | 989 | } |
821 | 990 | if (t->ops.has_signal) | |
991 | tuner->signal = t->ops.has_signal(t); | ||
822 | tuner->capability |= | 992 | tuner->capability |= |
823 | V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; | 993 | V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; |
824 | tuner->audmode = t->audmode; | 994 | tuner->audmode = t->audmode; |
@@ -844,7 +1014,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
844 | } | 1014 | } |
845 | case VIDIOC_LOG_STATUS: | 1015 | case VIDIOC_LOG_STATUS: |
846 | if (t->ops.tuner_status) | 1016 | if (t->ops.tuner_status) |
847 | t->ops.tuner_status(client); | 1017 | t->ops.tuner_status(t); |
848 | break; | 1018 | break; |
849 | } | 1019 | } |
850 | 1020 | ||
diff --git a/drivers/media/video/tuner-driver.h b/drivers/media/video/tuner-driver.h index 0334a9125077..28a10da76d12 100644 --- a/drivers/media/video/tuner-driver.h +++ b/drivers/media/video/tuner-driver.h | |||
@@ -19,23 +19,27 @@ | |||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #ifndef __TUNER_HW_H__ | 22 | #ifndef __TUNER_DRIVER_H__ |
23 | #define __TUNER_HW_H__ | 23 | #define __TUNER_DRIVER_H__ |
24 | 24 | ||
25 | #include <linux/videodev2.h> | 25 | #include <linux/videodev2.h> |
26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
27 | #include "tuner-i2c.h" | ||
28 | #include "dvb_frontend.h" | ||
27 | 29 | ||
28 | extern unsigned const int tuner_count; | 30 | extern unsigned const int tuner_count; |
29 | 31 | ||
32 | struct tuner; | ||
33 | |||
30 | struct tuner_operations { | 34 | struct tuner_operations { |
31 | void (*set_tv_freq)(struct i2c_client *c, unsigned int freq); | 35 | void (*set_tv_freq)(struct tuner *t, unsigned int freq); |
32 | void (*set_radio_freq)(struct i2c_client *c, unsigned int freq); | 36 | void (*set_radio_freq)(struct tuner *t, unsigned int freq); |
33 | int (*has_signal)(struct i2c_client *c); | 37 | int (*has_signal)(struct tuner *t); |
34 | int (*is_stereo)(struct i2c_client *c); | 38 | int (*is_stereo)(struct tuner *t); |
35 | int (*get_afc)(struct i2c_client *c); | 39 | int (*get_afc)(struct tuner *t); |
36 | void (*tuner_status)(struct i2c_client *c); | 40 | void (*tuner_status)(struct tuner *t); |
37 | void (*standby)(struct i2c_client *c); | 41 | void (*standby)(struct tuner *t); |
38 | void (*release)(struct i2c_client *c); | 42 | void (*release)(struct tuner *t); |
39 | }; | 43 | }; |
40 | 44 | ||
41 | struct tuner { | 45 | struct tuner { |
@@ -49,13 +53,14 @@ struct tuner { | |||
49 | 53 | ||
50 | unsigned int tv_freq; /* keep track of the current settings */ | 54 | unsigned int tv_freq; /* keep track of the current settings */ |
51 | unsigned int radio_freq; | 55 | unsigned int radio_freq; |
52 | u16 last_div; | ||
53 | unsigned int audmode; | 56 | unsigned int audmode; |
54 | v4l2_std_id std; | 57 | v4l2_std_id std; |
55 | 58 | ||
56 | int using_v4l2; | 59 | int using_v4l2; |
57 | void *priv; | 60 | void *priv; |
58 | 61 | ||
62 | struct dvb_frontend fe; | ||
63 | |||
59 | /* used by tda9887 */ | 64 | /* used by tda9887 */ |
60 | unsigned int tda9887_config; | 65 | unsigned int tda9887_config; |
61 | 66 | ||
@@ -67,20 +72,7 @@ struct tuner { | |||
67 | 72 | ||
68 | /* ------------------------------------------------------------------------ */ | 73 | /* ------------------------------------------------------------------------ */ |
69 | 74 | ||
70 | extern int default_tuner_init(struct i2c_client *c); | 75 | extern int tda9887_tuner_init(struct tuner *t); |
71 | |||
72 | extern int tda9887_tuner_init(struct i2c_client *c); | ||
73 | |||
74 | extern int microtune_init(struct i2c_client *c); | ||
75 | |||
76 | extern int tda8290_init(struct i2c_client *c); | ||
77 | extern int tda8290_probe(struct i2c_client *c); | ||
78 | |||
79 | extern int tea5761_tuner_init(struct i2c_client *c); | ||
80 | extern int tea5761_autodetection(struct i2c_client *c); | ||
81 | |||
82 | extern int tea5767_autodetection(struct i2c_client *c); | ||
83 | extern int tea5767_tuner_init(struct i2c_client *c); | ||
84 | 76 | ||
85 | /* ------------------------------------------------------------------------ */ | 77 | /* ------------------------------------------------------------------------ */ |
86 | 78 | ||
@@ -96,7 +88,7 @@ extern int tea5767_tuner_init(struct i2c_client *c); | |||
96 | printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ | 88 | printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ |
97 | i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) | 89 | i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) |
98 | 90 | ||
99 | #endif /* __TUNER_HW_H__ */ | 91 | #endif /* __TUNER_DRIVER_H__ */ |
100 | 92 | ||
101 | /* | 93 | /* |
102 | * Overrides for Emacs so that we follow Linus's tabbing style. | 94 | * Overrides for Emacs so that we follow Linus's tabbing style. |
diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h new file mode 100644 index 000000000000..159019ec3373 --- /dev/null +++ b/drivers/media/video/tuner-i2c.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | tuner-i2c.h - i2c interface for different tuners | ||
3 | |||
4 | Copyright (C) 2007 Michael Krufky (mkrufky@linuxtv.org) | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __TUNER_I2C_H__ | ||
22 | #define __TUNER_I2C_H__ | ||
23 | |||
24 | #include <linux/i2c.h> | ||
25 | |||
26 | struct tuner_i2c_props { | ||
27 | u8 addr; | ||
28 | struct i2c_adapter *adap; | ||
29 | }; | ||
30 | |||
31 | static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len) | ||
32 | { | ||
33 | struct i2c_msg msg = { .addr = props->addr, .flags = 0, | ||
34 | .buf = buf, .len = len }; | ||
35 | int ret = i2c_transfer(props->adap, &msg, 1); | ||
36 | |||
37 | return (ret == 1) ? len : ret; | ||
38 | } | ||
39 | |||
40 | static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, char *buf, int len) | ||
41 | { | ||
42 | struct i2c_msg msg = { .addr = props->addr, .flags = I2C_M_RD, | ||
43 | .buf = buf, .len = len }; | ||
44 | int ret = i2c_transfer(props->adap, &msg, 1); | ||
45 | |||
46 | return (ret == 1) ? len : ret; | ||
47 | } | ||
48 | |||
49 | #ifndef __TUNER_DRIVER_H__ | ||
50 | #define tuner_warn(fmt, arg...) do {\ | ||
51 | printk(KERN_WARNING PREFIX "%d-%04x: " fmt, \ | ||
52 | i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr , ##arg); } while (0) | ||
53 | #define tuner_info(fmt, arg...) do {\ | ||
54 | printk(KERN_INFO PREFIX "%d-%04x: " fmt, \ | ||
55 | i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr , ##arg); } while (0) | ||
56 | #define tuner_dbg(fmt, arg...) do {\ | ||
57 | if ((debug)) \ | ||
58 | printk(KERN_DEBUG PREFIX "%d-%04x: " fmt, \ | ||
59 | i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr , ##arg); } while (0) | ||
60 | #endif /* __TUNER_DRIVER_H__ */ | ||
61 | |||
62 | #endif /* __TUNER_I2C_H__ */ | ||
63 | |||
64 | /* | ||
65 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
66 | * --------------------------------------------------------------------------- | ||
67 | * Local variables: | ||
68 | * c-basic-offset: 8 | ||
69 | * End: | ||
70 | */ | ||
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 2d57e8bc0db3..7b93d3b1f4c6 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * | ||
3 | * i2c tv tuner chip device driver | 2 | * i2c tv tuner chip device driver |
4 | * controls all those simple 4-control-bytes style tuners. | 3 | * controls all those simple 4-control-bytes style tuners. |
4 | * | ||
5 | * This "tuner-simple" module was split apart from the original "tuner" module. | ||
5 | */ | 6 | */ |
6 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
7 | #include <linux/i2c.h> | 8 | #include <linux/i2c.h> |
@@ -9,7 +10,14 @@ | |||
9 | #include <media/tuner.h> | 10 | #include <media/tuner.h> |
10 | #include <media/v4l2-common.h> | 11 | #include <media/v4l2-common.h> |
11 | #include <media/tuner-types.h> | 12 | #include <media/tuner-types.h> |
12 | #include "tuner-driver.h" | 13 | #include "tuner-i2c.h" |
14 | #include "tuner-simple.h" | ||
15 | |||
16 | static int debug = 0; | ||
17 | module_param(debug, int, 0644); | ||
18 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
19 | |||
20 | #define PREFIX "tuner-simple " | ||
13 | 21 | ||
14 | static int offset = 0; | 22 | static int offset = 0; |
15 | module_param(offset, int, 0664); | 23 | module_param(offset, int, 0664); |
@@ -82,59 +90,102 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); | |||
82 | #define TUNER_PLL_LOCKED 0x40 | 90 | #define TUNER_PLL_LOCKED 0x40 |
83 | #define TUNER_STEREO_MK3 0x04 | 91 | #define TUNER_STEREO_MK3 0x04 |
84 | 92 | ||
93 | struct tuner_simple_priv { | ||
94 | u16 last_div; | ||
95 | struct tuner_i2c_props i2c_props; | ||
96 | |||
97 | unsigned int type; | ||
98 | struct tunertype *tun; | ||
99 | |||
100 | u32 frequency; | ||
101 | }; | ||
102 | |||
85 | /* ---------------------------------------------------------------------- */ | 103 | /* ---------------------------------------------------------------------- */ |
86 | 104 | ||
87 | static int tuner_getstatus(struct i2c_client *c) | 105 | static int tuner_read_status(struct dvb_frontend *fe) |
88 | { | 106 | { |
107 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
89 | unsigned char byte; | 108 | unsigned char byte; |
90 | 109 | ||
91 | if (1 != i2c_master_recv(c,&byte,1)) | 110 | if (1 != tuner_i2c_xfer_recv(&priv->i2c_props,&byte,1)) |
92 | return 0; | 111 | return 0; |
93 | 112 | ||
94 | return byte; | 113 | return byte; |
95 | } | 114 | } |
96 | 115 | ||
97 | static int tuner_signal(struct i2c_client *c) | 116 | static inline int tuner_signal(const int status) |
98 | { | 117 | { |
99 | return (tuner_getstatus(c) & TUNER_SIGNAL) << 13; | 118 | return (status & TUNER_SIGNAL) << 13; |
100 | } | 119 | } |
101 | 120 | ||
102 | static int tuner_stereo(struct i2c_client *c) | 121 | static inline int tuner_stereo(const int type, const int status) |
103 | { | 122 | { |
104 | int stereo, status; | 123 | switch (type) { |
105 | struct tuner *t = i2c_get_clientdata(c); | ||
106 | |||
107 | status = tuner_getstatus (c); | ||
108 | |||
109 | switch (t->type) { | ||
110 | case TUNER_PHILIPS_FM1216ME_MK3: | 124 | case TUNER_PHILIPS_FM1216ME_MK3: |
111 | case TUNER_PHILIPS_FM1236_MK3: | 125 | case TUNER_PHILIPS_FM1236_MK3: |
112 | case TUNER_PHILIPS_FM1256_IH3: | 126 | case TUNER_PHILIPS_FM1256_IH3: |
113 | case TUNER_LG_NTSC_TAPE: | 127 | case TUNER_LG_NTSC_TAPE: |
114 | stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); | 128 | return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); |
115 | break; | ||
116 | default: | 129 | default: |
117 | stereo = status & TUNER_STEREO; | 130 | return status & TUNER_STEREO; |
118 | } | 131 | } |
132 | } | ||
133 | |||
134 | static inline int tuner_islocked(const int status) | ||
135 | { | ||
136 | return (status & TUNER_FL); | ||
137 | } | ||
119 | 138 | ||
120 | return stereo; | 139 | static inline int tuner_afcstatus(const int status) |
140 | { | ||
141 | return (status & TUNER_AFC) - 2; | ||
121 | } | 142 | } |
122 | 143 | ||
123 | 144 | ||
145 | static int simple_get_status(struct dvb_frontend *fe, u32 *status) | ||
146 | { | ||
147 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
148 | int tuner_status = tuner_read_status(fe); | ||
149 | |||
150 | *status = 0; | ||
151 | |||
152 | if (tuner_islocked(tuner_status)) | ||
153 | *status = TUNER_STATUS_LOCKED; | ||
154 | if (tuner_stereo(priv->type, tuner_status)) | ||
155 | *status |= TUNER_STATUS_STEREO; | ||
156 | |||
157 | tuner_dbg("AFC Status: %d\n", tuner_afcstatus(tuner_status)); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength) | ||
163 | { | ||
164 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
165 | int signal = tuner_signal(tuner_read_status(fe)); | ||
166 | |||
167 | *strength = signal; | ||
168 | |||
169 | tuner_dbg("Signal strength: %d\n", signal); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
124 | /* ---------------------------------------------------------------------- */ | 174 | /* ---------------------------------------------------------------------- */ |
125 | 175 | ||
126 | static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) | 176 | static int simple_set_tv_freq(struct dvb_frontend *fe, |
177 | struct analog_parameters *params) | ||
127 | { | 178 | { |
128 | struct tuner *t = i2c_get_clientdata(c); | 179 | struct tuner_simple_priv *priv = fe->tuner_priv; |
129 | u8 config, cb, tuneraddr; | 180 | u8 config, cb, tuneraddr; |
130 | u16 div; | 181 | u16 div; |
131 | struct tunertype *tun; | 182 | struct tunertype *tun; |
132 | u8 buffer[4]; | 183 | u8 buffer[4]; |
133 | int rc, IFPCoff, i, j; | 184 | int rc, IFPCoff, i, j; |
134 | enum param_type desired_type; | 185 | enum param_type desired_type; |
135 | struct tuner_params *params; | 186 | struct tuner_params *t_params; |
136 | 187 | ||
137 | tun = &tuners[t->type]; | 188 | tun = priv->tun; |
138 | 189 | ||
139 | /* IFPCoff = Video Intermediate Frequency - Vif: | 190 | /* IFPCoff = Video Intermediate Frequency - Vif: |
140 | 940 =16*58.75 NTSC/J (Japan) | 191 | 940 =16*58.75 NTSC/J (Japan) |
@@ -148,14 +199,14 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
148 | 171.2=16*10.70 FM Radio (at set_radio_freq) | 199 | 171.2=16*10.70 FM Radio (at set_radio_freq) |
149 | */ | 200 | */ |
150 | 201 | ||
151 | if (t->std == V4L2_STD_NTSC_M_JP) { | 202 | if (params->std == V4L2_STD_NTSC_M_JP) { |
152 | IFPCoff = 940; | 203 | IFPCoff = 940; |
153 | desired_type = TUNER_PARAM_TYPE_NTSC; | 204 | desired_type = TUNER_PARAM_TYPE_NTSC; |
154 | } else if ((t->std & V4L2_STD_MN) && | 205 | } else if ((params->std & V4L2_STD_MN) && |
155 | !(t->std & ~V4L2_STD_MN)) { | 206 | !(params->std & ~V4L2_STD_MN)) { |
156 | IFPCoff = 732; | 207 | IFPCoff = 732; |
157 | desired_type = TUNER_PARAM_TYPE_NTSC; | 208 | desired_type = TUNER_PARAM_TYPE_NTSC; |
158 | } else if (t->std == V4L2_STD_SECAM_LC) { | 209 | } else if (params->std == V4L2_STD_SECAM_LC) { |
159 | IFPCoff = 543; | 210 | IFPCoff = 543; |
160 | desired_type = TUNER_PARAM_TYPE_SECAM; | 211 | desired_type = TUNER_PARAM_TYPE_SECAM; |
161 | } else { | 212 | } else { |
@@ -168,49 +219,49 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
168 | continue; | 219 | continue; |
169 | break; | 220 | break; |
170 | } | 221 | } |
171 | /* use default tuner_params if desired_type not available */ | 222 | /* use default tuner_t_params if desired_type not available */ |
172 | if (desired_type != tun->params[j].type) { | 223 | if (desired_type != tun->params[j].type) { |
173 | tuner_dbg("IFPCoff = %d: tuner_params undefined for tuner %d\n", | 224 | tuner_dbg("IFPCoff = %d: tuner_t_params undefined for tuner %d\n", |
174 | IFPCoff,t->type); | 225 | IFPCoff, priv->type); |
175 | j = 0; | 226 | j = 0; |
176 | } | 227 | } |
177 | params = &tun->params[j]; | 228 | t_params = &tun->params[j]; |
178 | 229 | ||
179 | for (i = 0; i < params->count; i++) { | 230 | for (i = 0; i < t_params->count; i++) { |
180 | if (freq > params->ranges[i].limit) | 231 | if (params->frequency > t_params->ranges[i].limit) |
181 | continue; | 232 | continue; |
182 | break; | 233 | break; |
183 | } | 234 | } |
184 | if (i == params->count) { | 235 | if (i == t_params->count) { |
185 | tuner_dbg("TV frequency out of range (%d > %d)", | 236 | tuner_dbg("TV frequency out of range (%d > %d)", |
186 | freq, params->ranges[i - 1].limit); | 237 | params->frequency, t_params->ranges[i - 1].limit); |
187 | freq = params->ranges[--i].limit; | 238 | params->frequency = t_params->ranges[--i].limit; |
188 | } | 239 | } |
189 | config = params->ranges[i].config; | 240 | config = t_params->ranges[i].config; |
190 | cb = params->ranges[i].cb; | 241 | cb = t_params->ranges[i].cb; |
191 | /* i == 0 -> VHF_LO | 242 | /* i == 0 -> VHF_LO |
192 | * i == 1 -> VHF_HI | 243 | * i == 1 -> VHF_HI |
193 | * i == 2 -> UHF */ | 244 | * i == 2 -> UHF */ |
194 | tuner_dbg("tv: param %d, range %d\n",j,i); | 245 | tuner_dbg("tv: param %d, range %d\n",j,i); |
195 | 246 | ||
196 | div=freq + IFPCoff + offset; | 247 | div=params->frequency + IFPCoff + offset; |
197 | 248 | ||
198 | tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n", | 249 | tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n", |
199 | freq / 16, freq % 16 * 100 / 16, | 250 | params->frequency / 16, params->frequency % 16 * 100 / 16, |
200 | IFPCoff / 16, IFPCoff % 16 * 100 / 16, | 251 | IFPCoff / 16, IFPCoff % 16 * 100 / 16, |
201 | offset / 16, offset % 16 * 100 / 16, | 252 | offset / 16, offset % 16 * 100 / 16, |
202 | div); | 253 | div); |
203 | 254 | ||
204 | /* tv norm specific stuff for multi-norm tuners */ | 255 | /* tv norm specific stuff for multi-norm tuners */ |
205 | switch (t->type) { | 256 | switch (priv->type) { |
206 | case TUNER_PHILIPS_SECAM: // FI1216MF | 257 | case TUNER_PHILIPS_SECAM: // FI1216MF |
207 | /* 0x01 -> ??? no change ??? */ | 258 | /* 0x01 -> ??? no change ??? */ |
208 | /* 0x02 -> PAL BDGHI / SECAM L */ | 259 | /* 0x02 -> PAL BDGHI / SECAM L */ |
209 | /* 0x04 -> ??? PAL others / SECAM others ??? */ | 260 | /* 0x04 -> ??? PAL others / SECAM others ??? */ |
210 | cb &= ~0x03; | 261 | cb &= ~0x03; |
211 | if (t->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM | 262 | if (params->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM |
212 | cb |= PHILIPS_MF_SET_STD_L; | 263 | cb |= PHILIPS_MF_SET_STD_L; |
213 | else if (t->std & V4L2_STD_SECAM_LC) | 264 | else if (params->std & V4L2_STD_SECAM_LC) |
214 | cb |= PHILIPS_MF_SET_STD_LC; | 265 | cb |= PHILIPS_MF_SET_STD_LC; |
215 | else /* V4L2_STD_B|V4L2_STD_GH */ | 266 | else /* V4L2_STD_B|V4L2_STD_GH */ |
216 | cb |= PHILIPS_MF_SET_STD_BG; | 267 | cb |= PHILIPS_MF_SET_STD_BG; |
@@ -219,16 +270,16 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
219 | case TUNER_TEMIC_4046FM5: | 270 | case TUNER_TEMIC_4046FM5: |
220 | cb &= ~0x0f; | 271 | cb &= ~0x0f; |
221 | 272 | ||
222 | if (t->std & V4L2_STD_PAL_BG) { | 273 | if (params->std & V4L2_STD_PAL_BG) { |
223 | cb |= TEMIC_SET_PAL_BG; | 274 | cb |= TEMIC_SET_PAL_BG; |
224 | 275 | ||
225 | } else if (t->std & V4L2_STD_PAL_I) { | 276 | } else if (params->std & V4L2_STD_PAL_I) { |
226 | cb |= TEMIC_SET_PAL_I; | 277 | cb |= TEMIC_SET_PAL_I; |
227 | 278 | ||
228 | } else if (t->std & V4L2_STD_PAL_DK) { | 279 | } else if (params->std & V4L2_STD_PAL_DK) { |
229 | cb |= TEMIC_SET_PAL_DK; | 280 | cb |= TEMIC_SET_PAL_DK; |
230 | 281 | ||
231 | } else if (t->std & V4L2_STD_SECAM_L) { | 282 | } else if (params->std & V4L2_STD_SECAM_L) { |
232 | cb |= TEMIC_SET_PAL_L; | 283 | cb |= TEMIC_SET_PAL_L; |
233 | 284 | ||
234 | } | 285 | } |
@@ -237,13 +288,13 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
237 | case TUNER_PHILIPS_FQ1216ME: | 288 | case TUNER_PHILIPS_FQ1216ME: |
238 | cb &= ~0x0f; | 289 | cb &= ~0x0f; |
239 | 290 | ||
240 | if (t->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { | 291 | if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { |
241 | cb |= PHILIPS_SET_PAL_BGDK; | 292 | cb |= PHILIPS_SET_PAL_BGDK; |
242 | 293 | ||
243 | } else if (t->std & V4L2_STD_PAL_I) { | 294 | } else if (params->std & V4L2_STD_PAL_I) { |
244 | cb |= PHILIPS_SET_PAL_I; | 295 | cb |= PHILIPS_SET_PAL_I; |
245 | 296 | ||
246 | } else if (t->std & V4L2_STD_SECAM_L) { | 297 | } else if (params->std & V4L2_STD_SECAM_L) { |
247 | cb |= PHILIPS_SET_PAL_L; | 298 | cb |= PHILIPS_SET_PAL_L; |
248 | 299 | ||
249 | } | 300 | } |
@@ -255,7 +306,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
255 | /* 0x02 -> NTSC antenna input 1 */ | 306 | /* 0x02 -> NTSC antenna input 1 */ |
256 | /* 0x03 -> NTSC antenna input 2 */ | 307 | /* 0x03 -> NTSC antenna input 2 */ |
257 | cb &= ~0x03; | 308 | cb &= ~0x03; |
258 | if (!(t->std & V4L2_STD_ATSC)) | 309 | if (!(params->std & V4L2_STD_ATSC)) |
259 | cb |= 2; | 310 | cb |= 2; |
260 | /* FIXME: input */ | 311 | /* FIXME: input */ |
261 | break; | 312 | break; |
@@ -275,23 +326,23 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
275 | buffer[2] = 0x17; | 326 | buffer[2] = 0x17; |
276 | buffer[3] = 0x00; | 327 | buffer[3] = 0x00; |
277 | cb &= ~0x40; | 328 | cb &= ~0x40; |
278 | if (t->std & V4L2_STD_ATSC) { | 329 | if (params->std & V4L2_STD_ATSC) { |
279 | cb |= 0x40; | 330 | cb |= 0x40; |
280 | buffer[1] = 0x04; | 331 | buffer[1] = 0x04; |
281 | } | 332 | } |
282 | /* set to the correct mode (analog or digital) */ | 333 | /* set to the correct mode (analog or digital) */ |
283 | tuneraddr = c->addr; | 334 | tuneraddr = priv->i2c_props.addr; |
284 | c->addr = 0x0a; | 335 | priv->i2c_props.addr = 0x0a; |
285 | if (2 != (rc = i2c_master_send(c,&buffer[0],2))) | 336 | if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[0],2))) |
286 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); | 337 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); |
287 | if (2 != (rc = i2c_master_send(c,&buffer[2],2))) | 338 | if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[2],2))) |
288 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); | 339 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); |
289 | c->addr = tuneraddr; | 340 | priv->i2c_props.addr = tuneraddr; |
290 | /* FIXME: input */ | 341 | /* FIXME: input */ |
291 | break; | 342 | break; |
292 | } | 343 | } |
293 | 344 | ||
294 | if (params->cb_first_if_lower_freq && div < t->last_div) { | 345 | if (t_params->cb_first_if_lower_freq && div < priv->last_div) { |
295 | buffer[0] = config; | 346 | buffer[0] = config; |
296 | buffer[1] = cb; | 347 | buffer[1] = cb; |
297 | buffer[2] = (div>>8) & 0x7f; | 348 | buffer[2] = (div>>8) & 0x7f; |
@@ -302,53 +353,53 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
302 | buffer[2] = config; | 353 | buffer[2] = config; |
303 | buffer[3] = cb; | 354 | buffer[3] = cb; |
304 | } | 355 | } |
305 | t->last_div = div; | 356 | priv->last_div = div; |
306 | if (params->has_tda9887) { | 357 | if (t_params->has_tda9887) { |
307 | int config = 0; | 358 | int config = 0; |
308 | int is_secam_l = (t->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) && | 359 | int is_secam_l = (params->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) && |
309 | !(t->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)); | 360 | !(params->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)); |
310 | 361 | ||
311 | if (t->std == V4L2_STD_SECAM_LC) { | 362 | if (params->std == V4L2_STD_SECAM_LC) { |
312 | if (params->port1_active ^ params->port1_invert_for_secam_lc) | 363 | if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc) |
313 | config |= TDA9887_PORT1_ACTIVE; | 364 | config |= TDA9887_PORT1_ACTIVE; |
314 | if (params->port2_active ^ params->port2_invert_for_secam_lc) | 365 | if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc) |
315 | config |= TDA9887_PORT2_ACTIVE; | 366 | config |= TDA9887_PORT2_ACTIVE; |
316 | } | 367 | } |
317 | else { | 368 | else { |
318 | if (params->port1_active) | 369 | if (t_params->port1_active) |
319 | config |= TDA9887_PORT1_ACTIVE; | 370 | config |= TDA9887_PORT1_ACTIVE; |
320 | if (params->port2_active) | 371 | if (t_params->port2_active) |
321 | config |= TDA9887_PORT2_ACTIVE; | 372 | config |= TDA9887_PORT2_ACTIVE; |
322 | } | 373 | } |
323 | if (params->intercarrier_mode) | 374 | if (t_params->intercarrier_mode) |
324 | config |= TDA9887_INTERCARRIER; | 375 | config |= TDA9887_INTERCARRIER; |
325 | if (is_secam_l) { | 376 | if (is_secam_l) { |
326 | if (i == 0 && params->default_top_secam_low) | 377 | if (i == 0 && t_params->default_top_secam_low) |
327 | config |= TDA9887_TOP(params->default_top_secam_low); | 378 | config |= TDA9887_TOP(t_params->default_top_secam_low); |
328 | else if (i == 1 && params->default_top_secam_mid) | 379 | else if (i == 1 && t_params->default_top_secam_mid) |
329 | config |= TDA9887_TOP(params->default_top_secam_mid); | 380 | config |= TDA9887_TOP(t_params->default_top_secam_mid); |
330 | else if (params->default_top_secam_high) | 381 | else if (t_params->default_top_secam_high) |
331 | config |= TDA9887_TOP(params->default_top_secam_high); | 382 | config |= TDA9887_TOP(t_params->default_top_secam_high); |
332 | } | 383 | } |
333 | else { | 384 | else { |
334 | if (i == 0 && params->default_top_low) | 385 | if (i == 0 && t_params->default_top_low) |
335 | config |= TDA9887_TOP(params->default_top_low); | 386 | config |= TDA9887_TOP(t_params->default_top_low); |
336 | else if (i == 1 && params->default_top_mid) | 387 | else if (i == 1 && t_params->default_top_mid) |
337 | config |= TDA9887_TOP(params->default_top_mid); | 388 | config |= TDA9887_TOP(t_params->default_top_mid); |
338 | else if (params->default_top_high) | 389 | else if (t_params->default_top_high) |
339 | config |= TDA9887_TOP(params->default_top_high); | 390 | config |= TDA9887_TOP(t_params->default_top_high); |
340 | } | 391 | } |
341 | if (params->default_pll_gating_18) | 392 | if (t_params->default_pll_gating_18) |
342 | config |= TDA9887_GATING_18; | 393 | config |= TDA9887_GATING_18; |
343 | i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config); | 394 | i2c_clients_command(priv->i2c_props.adap, TDA9887_SET_CONFIG, &config); |
344 | } | 395 | } |
345 | tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", | 396 | tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", |
346 | buffer[0],buffer[1],buffer[2],buffer[3]); | 397 | buffer[0],buffer[1],buffer[2],buffer[3]); |
347 | 398 | ||
348 | if (4 != (rc = i2c_master_send(c,buffer,4))) | 399 | if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) |
349 | tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); | 400 | tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); |
350 | 401 | ||
351 | switch (t->type) { | 402 | switch (priv->type) { |
352 | case TUNER_LG_TDVS_H06XF: | 403 | case TUNER_LG_TDVS_H06XF: |
353 | /* Set the Auxiliary Byte. */ | 404 | /* Set the Auxiliary Byte. */ |
354 | buffer[0] = buffer[2]; | 405 | buffer[0] = buffer[2]; |
@@ -357,7 +408,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
357 | buffer[1] = 0x20; | 408 | buffer[1] = 0x20; |
358 | tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]); | 409 | tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]); |
359 | 410 | ||
360 | if (2 != (rc = i2c_master_send(c,buffer,2))) | 411 | if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,2))) |
361 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); | 412 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); |
362 | break; | 413 | break; |
363 | case TUNER_MICROTUNE_4042FI5: | 414 | case TUNER_MICROTUNE_4042FI5: |
@@ -369,8 +420,8 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
369 | /* Wait until the PLL locks */ | 420 | /* Wait until the PLL locks */ |
370 | for (;;) { | 421 | for (;;) { |
371 | if (time_after(jiffies,timeout)) | 422 | if (time_after(jiffies,timeout)) |
372 | return; | 423 | return 0; |
373 | if (1 != (rc = i2c_master_recv(c,&status_byte,1))) { | 424 | if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,&status_byte,1))) { |
374 | tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc); | 425 | tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc); |
375 | break; | 426 | break; |
376 | } | 427 | } |
@@ -388,68 +439,86 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
388 | tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", | 439 | tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", |
389 | buffer[0],buffer[1],buffer[2],buffer[3]); | 440 | buffer[0],buffer[1],buffer[2],buffer[3]); |
390 | 441 | ||
391 | if (4 != (rc = i2c_master_send(c,buffer,4))) | 442 | if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) |
392 | tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); | 443 | tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); |
393 | break; | 444 | break; |
394 | } | 445 | } |
395 | } | 446 | } |
447 | return 0; | ||
396 | } | 448 | } |
397 | 449 | ||
398 | static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) | 450 | static int simple_set_radio_freq(struct dvb_frontend *fe, |
451 | struct analog_parameters *params) | ||
399 | { | 452 | { |
400 | struct tunertype *tun; | 453 | struct tunertype *tun; |
401 | struct tuner *t = i2c_get_clientdata(c); | 454 | struct tuner_simple_priv *priv = fe->tuner_priv; |
402 | u8 buffer[4]; | 455 | u8 buffer[4]; |
403 | u16 div; | 456 | u16 div; |
404 | int rc, j; | 457 | int rc, j; |
405 | enum param_type desired_type = TUNER_PARAM_TYPE_RADIO; | 458 | struct tuner_params *t_params; |
406 | struct tuner_params *params; | 459 | unsigned int freq = params->frequency; |
407 | 460 | ||
408 | tun = &tuners[t->type]; | 461 | tun = priv->tun; |
409 | 462 | ||
410 | for (j = 0; j < tun->count-1; j++) { | 463 | for (j = tun->count-1; j > 0; j--) |
411 | if (desired_type != tun->params[j].type) | 464 | if (tun->params[j].type == TUNER_PARAM_TYPE_RADIO) |
412 | continue; | 465 | break; |
466 | /* default t_params (j=0) will be used if desired type wasn't found */ | ||
467 | t_params = &tun->params[j]; | ||
468 | |||
469 | /* Select Radio 1st IF used */ | ||
470 | switch (t_params->radio_if) { | ||
471 | case 0: /* 10.7 MHz */ | ||
472 | freq += (unsigned int)(10.7*16000); | ||
473 | break; | ||
474 | case 1: /* 33.3 MHz */ | ||
475 | freq += (unsigned int)(33.3*16000); | ||
413 | break; | 476 | break; |
477 | case 2: /* 41.3 MHz */ | ||
478 | freq += (unsigned int)(41.3*16000); | ||
479 | break; | ||
480 | default: | ||
481 | tuner_warn("Unsupported radio_if value %d\n", t_params->radio_if); | ||
482 | return 0; | ||
414 | } | 483 | } |
415 | /* use default tuner_params if desired_type not available */ | ||
416 | if (desired_type != tun->params[j].type) | ||
417 | j = 0; | ||
418 | |||
419 | div = (20 * freq / 16000) + (int)(20*10.7); /* IF 10.7 MHz */ | ||
420 | params = &tun->params[j]; | ||
421 | buffer[2] = (params->ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ | ||
422 | 484 | ||
423 | switch (t->type) { | 485 | /* Bandswitch byte */ |
486 | switch (priv->type) { | ||
424 | case TUNER_TENA_9533_DI: | 487 | case TUNER_TENA_9533_DI: |
425 | case TUNER_YMEC_TVF_5533MF: | 488 | case TUNER_YMEC_TVF_5533MF: |
426 | tuner_dbg ("This tuner doesn't have FM. Most cards has a TEA5767 for FM\n"); | 489 | tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n"); |
427 | return; | 490 | return 0; |
428 | case TUNER_PHILIPS_FM1216ME_MK3: | 491 | case TUNER_PHILIPS_FM1216ME_MK3: |
429 | case TUNER_PHILIPS_FM1236_MK3: | 492 | case TUNER_PHILIPS_FM1236_MK3: |
430 | case TUNER_PHILIPS_FMD1216ME_MK3: | 493 | case TUNER_PHILIPS_FMD1216ME_MK3: |
431 | case TUNER_LG_NTSC_TAPE: | 494 | case TUNER_LG_NTSC_TAPE: |
495 | case TUNER_PHILIPS_FM1256_IH3: | ||
432 | buffer[3] = 0x19; | 496 | buffer[3] = 0x19; |
433 | break; | 497 | break; |
434 | case TUNER_TNF_5335MF: | 498 | case TUNER_TNF_5335MF: |
435 | buffer[3] = 0x11; | 499 | buffer[3] = 0x11; |
436 | break; | 500 | break; |
437 | case TUNER_PHILIPS_FM1256_IH3: | ||
438 | div = (20 * freq) / 16000 + (int)(33.3 * 20); /* IF 33.3 MHz */ | ||
439 | buffer[3] = 0x19; | ||
440 | break; | ||
441 | case TUNER_LG_PAL_FM: | 501 | case TUNER_LG_PAL_FM: |
442 | buffer[3] = 0xa5; | 502 | buffer[3] = 0xa5; |
443 | break; | 503 | break; |
444 | case TUNER_MICROTUNE_4049FM5: | 504 | case TUNER_THOMSON_DTT761X: |
445 | div = (20 * freq) / 16000 + (int)(33.3 * 20); /* IF 33.3 MHz */ | 505 | buffer[3] = 0x39; |
446 | buffer[3] = 0xa4; | ||
447 | break; | 506 | break; |
507 | case TUNER_MICROTUNE_4049FM5: | ||
448 | default: | 508 | default: |
449 | buffer[3] = 0xa4; | 509 | buffer[3] = 0xa4; |
450 | break; | 510 | break; |
451 | } | 511 | } |
452 | if (params->cb_first_if_lower_freq && div < t->last_div) { | 512 | |
513 | buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) | | ||
514 | TUNER_RATIO_SELECT_50; /* 50 kHz step */ | ||
515 | |||
516 | /* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps | ||
517 | freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) = | ||
518 | freq * (1/800) */ | ||
519 | div = (freq + 400) / 800; | ||
520 | |||
521 | if (t_params->cb_first_if_lower_freq && div < priv->last_div) { | ||
453 | buffer[0] = buffer[2]; | 522 | buffer[0] = buffer[2]; |
454 | buffer[1] = buffer[3]; | 523 | buffer[1] = buffer[3]; |
455 | buffer[2] = (div>>8) & 0x7f; | 524 | buffer[2] = (div>>8) & 0x7f; |
@@ -461,46 +530,108 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) | |||
461 | 530 | ||
462 | tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n", | 531 | tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n", |
463 | buffer[0],buffer[1],buffer[2],buffer[3]); | 532 | buffer[0],buffer[1],buffer[2],buffer[3]); |
464 | t->last_div = div; | 533 | priv->last_div = div; |
465 | 534 | ||
466 | if (params->has_tda9887) { | 535 | if (t_params->has_tda9887) { |
467 | int config = 0; | 536 | int config = 0; |
468 | if (params->port1_active && !params->port1_fm_high_sensitivity) | 537 | if (t_params->port1_active && !t_params->port1_fm_high_sensitivity) |
469 | config |= TDA9887_PORT1_ACTIVE; | 538 | config |= TDA9887_PORT1_ACTIVE; |
470 | if (params->port2_active && !params->port2_fm_high_sensitivity) | 539 | if (t_params->port2_active && !t_params->port2_fm_high_sensitivity) |
471 | config |= TDA9887_PORT2_ACTIVE; | 540 | config |= TDA9887_PORT2_ACTIVE; |
472 | if (params->intercarrier_mode) | 541 | if (t_params->intercarrier_mode) |
473 | config |= TDA9887_INTERCARRIER; | 542 | config |= TDA9887_INTERCARRIER; |
474 | /* if (params->port1_set_for_fm_mono) | 543 | /* if (t_params->port1_set_for_fm_mono) |
475 | config &= ~TDA9887_PORT1_ACTIVE;*/ | 544 | config &= ~TDA9887_PORT1_ACTIVE;*/ |
476 | if (params->fm_gain_normal) | 545 | if (t_params->fm_gain_normal) |
477 | config |= TDA9887_GAIN_NORMAL; | 546 | config |= TDA9887_GAIN_NORMAL; |
478 | i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config); | 547 | if (t_params->radio_if == 2) |
548 | config |= TDA9887_RIF_41_3; | ||
549 | i2c_clients_command(priv->i2c_props.adap, TDA9887_SET_CONFIG, &config); | ||
479 | } | 550 | } |
480 | if (4 != (rc = i2c_master_send(c,buffer,4))) | 551 | if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) |
481 | tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); | 552 | tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); |
553 | |||
554 | return 0; | ||
482 | } | 555 | } |
483 | 556 | ||
484 | static struct tuner_operations simple_tuner_ops = { | 557 | static int simple_set_params(struct dvb_frontend *fe, |
485 | .set_tv_freq = default_set_tv_freq, | 558 | struct analog_parameters *params) |
486 | .set_radio_freq = default_set_radio_freq, | 559 | { |
487 | .has_signal = tuner_signal, | 560 | struct tuner_simple_priv *priv = fe->tuner_priv; |
488 | .is_stereo = tuner_stereo, | 561 | int ret = -EINVAL; |
562 | |||
563 | switch (params->mode) { | ||
564 | case V4L2_TUNER_RADIO: | ||
565 | ret = simple_set_radio_freq(fe, params); | ||
566 | priv->frequency = params->frequency * 125 / 2; | ||
567 | break; | ||
568 | case V4L2_TUNER_ANALOG_TV: | ||
569 | case V4L2_TUNER_DIGITAL_TV: | ||
570 | ret = simple_set_tv_freq(fe, params); | ||
571 | priv->frequency = params->frequency * 62500; | ||
572 | break; | ||
573 | } | ||
574 | |||
575 | return ret; | ||
576 | } | ||
577 | |||
578 | |||
579 | static int simple_release(struct dvb_frontend *fe) | ||
580 | { | ||
581 | kfree(fe->tuner_priv); | ||
582 | fe->tuner_priv = NULL; | ||
583 | |||
584 | return 0; | ||
585 | } | ||
586 | |||
587 | static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
588 | { | ||
589 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
590 | *frequency = priv->frequency; | ||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | static struct dvb_tuner_ops simple_tuner_ops = { | ||
595 | .set_analog_params = simple_set_params, | ||
596 | .release = simple_release, | ||
597 | .get_frequency = simple_get_frequency, | ||
598 | .get_status = simple_get_status, | ||
599 | .get_rf_strength = simple_get_rf_strength, | ||
489 | }; | 600 | }; |
490 | 601 | ||
491 | int default_tuner_init(struct i2c_client *c) | 602 | struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, |
603 | struct i2c_adapter *i2c_adap, | ||
604 | u8 i2c_addr, | ||
605 | struct simple_tuner_config *cfg) | ||
492 | { | 606 | { |
493 | struct tuner *t = i2c_get_clientdata(c); | 607 | struct tuner_simple_priv *priv = NULL; |
494 | 608 | ||
495 | tuner_info("type set to %d (%s)\n", | 609 | priv = kzalloc(sizeof(struct tuner_simple_priv), GFP_KERNEL); |
496 | t->type, tuners[t->type].name); | 610 | if (priv == NULL) |
497 | strlcpy(c->name, tuners[t->type].name, sizeof(c->name)); | 611 | return NULL; |
612 | fe->tuner_priv = priv; | ||
498 | 613 | ||
499 | memcpy(&t->ops, &simple_tuner_ops, sizeof(struct tuner_operations)); | 614 | priv->i2c_props.addr = i2c_addr; |
615 | priv->i2c_props.adap = i2c_adap; | ||
616 | priv->type = cfg->type; | ||
617 | priv->tun = cfg->tun; | ||
500 | 618 | ||
501 | return 0; | 619 | memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops)); |
620 | |||
621 | tuner_info("type set to %d (%s)\n", cfg->type, cfg->tun->name); | ||
622 | |||
623 | strlcpy(fe->ops.tuner_ops.info.name, cfg->tun->name, sizeof(fe->ops.tuner_ops.info.name)); | ||
624 | |||
625 | return fe; | ||
502 | } | 626 | } |
503 | 627 | ||
628 | |||
629 | EXPORT_SYMBOL_GPL(simple_tuner_attach); | ||
630 | |||
631 | MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver"); | ||
632 | MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); | ||
633 | MODULE_LICENSE("GPL"); | ||
634 | |||
504 | /* | 635 | /* |
505 | * Overrides for Emacs so that we follow Linus's tabbing style. | 636 | * Overrides for Emacs so that we follow Linus's tabbing style. |
506 | * --------------------------------------------------------------------------- | 637 | * --------------------------------------------------------------------------- |
diff --git a/drivers/media/video/tuner-simple.h b/drivers/media/video/tuner-simple.h new file mode 100644 index 000000000000..9089939a8c02 --- /dev/null +++ b/drivers/media/video/tuner-simple.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | This program is free software; you can redistribute it and/or modify | ||
3 | it under the terms of the GNU General Public License as published by | ||
4 | the Free Software Foundation; either version 2 of the License, or | ||
5 | (at your option) any later version. | ||
6 | |||
7 | This program is distributed in the hope that it will be useful, | ||
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | GNU General Public License for more details. | ||
11 | |||
12 | You should have received a copy of the GNU General Public License | ||
13 | along with this program; if not, write to the Free Software | ||
14 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
15 | */ | ||
16 | |||
17 | #ifndef __TUNER_SIMPLE_H__ | ||
18 | #define __TUNER_SIMPLE_H__ | ||
19 | |||
20 | #include <linux/i2c.h> | ||
21 | #include "dvb_frontend.h" | ||
22 | |||
23 | struct simple_tuner_config | ||
24 | { | ||
25 | /* chip type */ | ||
26 | unsigned int type; | ||
27 | struct tunertype *tun; | ||
28 | }; | ||
29 | |||
30 | #if defined(CONFIG_TUNER_SIMPLE) || (defined(CONFIG_TUNER_SIMPLE_MODULE) && defined(MODULE)) | ||
31 | extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, | ||
32 | struct i2c_adapter *i2c_adap, | ||
33 | u8 i2c_addr, | ||
34 | struct simple_tuner_config *cfg); | ||
35 | #else | ||
36 | static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, | ||
37 | struct i2c_adapter *i2c_adap, | ||
38 | u8 i2c_addr, | ||
39 | struct simple_tuner_config *cfg) | ||
40 | { | ||
41 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | ||
42 | return NULL; | ||
43 | } | ||
44 | #endif | ||
45 | |||
46 | #endif /* __TUNER_SIMPLE_H__ */ | ||
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 417f642b4359..c6a7934bd5a6 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c | |||
@@ -652,6 +652,7 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = { | |||
652 | .port1_invert_for_secam_lc = 1, | 652 | .port1_invert_for_secam_lc = 1, |
653 | .default_pll_gating_18 = 1, | 653 | .default_pll_gating_18 = 1, |
654 | .fm_gain_normal=1, | 654 | .fm_gain_normal=1, |
655 | .radio_if = 1, /* 33.3 MHz */ | ||
655 | }, | 656 | }, |
656 | }; | 657 | }; |
657 | 658 | ||
@@ -670,6 +671,9 @@ static struct tuner_params tuner_panasonic_vp27_params[] = { | |||
670 | .count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges), | 671 | .count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges), |
671 | .has_tda9887 = 1, | 672 | .has_tda9887 = 1, |
672 | .intercarrier_mode = 1, | 673 | .intercarrier_mode = 1, |
674 | .default_top_low = -3, | ||
675 | .default_top_mid = -3, | ||
676 | .default_top_high = -3, | ||
673 | }, | 677 | }, |
674 | }; | 678 | }; |
675 | 679 | ||
@@ -730,6 +734,7 @@ static struct tuner_params tuner_philips_fm1256_ih3_params[] = { | |||
730 | .type = TUNER_PARAM_TYPE_PAL, | 734 | .type = TUNER_PARAM_TYPE_PAL, |
731 | .ranges = tuner_fm1236_mk3_ntsc_ranges, | 735 | .ranges = tuner_fm1236_mk3_ntsc_ranges, |
732 | .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), | 736 | .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), |
737 | .radio_if = 1, /* 33.3 MHz */ | ||
733 | }, | 738 | }, |
734 | }; | 739 | }; |
735 | 740 | ||
@@ -856,6 +861,9 @@ static struct tuner_params tuner_thomson_dtt761x_params[] = { | |||
856 | .type = TUNER_PARAM_TYPE_NTSC, | 861 | .type = TUNER_PARAM_TYPE_NTSC, |
857 | .ranges = tuner_thomson_dtt761x_ntsc_ranges, | 862 | .ranges = tuner_thomson_dtt761x_ntsc_ranges, |
858 | .count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges), | 863 | .count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges), |
864 | .has_tda9887 = 1, | ||
865 | .fm_gain_normal = 1, | ||
866 | .radio_if = 2, /* 41.3 MHz */ | ||
859 | }, | 867 | }, |
860 | }; | 868 | }; |
861 | 869 | ||
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index cffb011590e3..a19cdcc17ef7 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c | |||
@@ -15,7 +15,6 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/moduleparam.h> | ||
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
20 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
21 | #include <linux/string.h> | 20 | #include <linux/string.h> |
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index fdc3def437b1..4b2c4034f5b3 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c | |||
@@ -30,7 +30,6 @@ | |||
30 | 30 | ||
31 | 31 | ||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/moduleparam.h> | ||
34 | #include <linux/errno.h> | 33 | #include <linux/errno.h> |
35 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
36 | #include <linux/init.h> | 35 | #include <linux/init.h> |
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c index 3ae5a9cd2e28..9fa5b702e073 100644 --- a/drivers/media/video/tvmixer.c +++ b/drivers/media/video/tvmixer.c | |||
@@ -2,7 +2,6 @@ | |||
2 | */ | 2 | */ |
3 | 3 | ||
4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
5 | #include <linux/moduleparam.h> | ||
6 | #include <linux/kernel.h> | 5 | #include <linux/kernel.h> |
7 | #include <linux/string.h> | 6 | #include <linux/string.h> |
8 | #include <linux/timer.h> | 7 | #include <linux/timer.h> |
@@ -238,13 +237,10 @@ static const struct file_operations tvmixer_fops = { | |||
238 | 237 | ||
239 | static int tvmixer_adapters(struct i2c_adapter *adap) | 238 | static int tvmixer_adapters(struct i2c_adapter *adap) |
240 | { | 239 | { |
241 | struct list_head *item; | ||
242 | struct i2c_client *client; | 240 | struct i2c_client *client; |
243 | 241 | ||
244 | list_for_each(item,&adap->clients) { | 242 | list_for_each_entry(client, &adap->clients, list) |
245 | client = list_entry(item, struct i2c_client, list); | ||
246 | tvmixer_clients(client); | 243 | tvmixer_clients(client); |
247 | } | ||
248 | return 0; | 244 | return 0; |
249 | } | 245 | } |
250 | 246 | ||
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 5b1e346df206..c7d5f9ed22d7 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <media/tuner.h> | 45 | #include <media/tuner.h> |
46 | #include <media/audiochip.h> | 46 | #include <media/audiochip.h> |
47 | 47 | ||
48 | #include <linux/moduleparam.h> | ||
49 | #include <linux/workqueue.h> | 48 | #include <linux/workqueue.h> |
50 | 49 | ||
51 | #ifdef CONFIG_KMOD | 50 | #ifdef CONFIG_KMOD |
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 025be555194f..c66aef63916f 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
@@ -134,8 +134,6 @@ static inline int usb_find_address(struct i2c_adapter *i2c_adap, | |||
134 | addr = (msg->addr << 1); | 134 | addr = (msg->addr << 1); |
135 | if (flags & I2C_M_RD) | 135 | if (flags & I2C_M_RD) |
136 | addr |= 1; | 136 | addr |= 1; |
137 | if (flags & I2C_M_REV_DIR_ADDR) | ||
138 | addr ^= 1; | ||
139 | 137 | ||
140 | add[0] = addr; | 138 | add[0] = addr; |
141 | if (flags & I2C_M_RD) | 139 | if (flags & I2C_M_RD) |
@@ -192,7 +190,7 @@ static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned | |||
192 | 190 | ||
193 | static u32 functionality(struct i2c_adapter *adap) | 191 | static u32 functionality(struct i2c_adapter *adap) |
194 | { | 192 | { |
195 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; | 193 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; |
196 | } | 194 | } |
197 | 195 | ||
198 | 196 | ||
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 0cb006f2943d..e2f3c01cfa13 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -68,7 +68,6 @@ | |||
68 | #include <media/tuner.h> | 68 | #include <media/tuner.h> |
69 | #include <media/audiochip.h> | 69 | #include <media/audiochip.h> |
70 | 70 | ||
71 | #include <linux/moduleparam.h> | ||
72 | #include <linux/workqueue.h> | 71 | #include <linux/workqueue.h> |
73 | 72 | ||
74 | #ifdef CONFIG_KMOD | 73 | #ifdef CONFIG_KMOD |
@@ -183,20 +182,22 @@ MODULE_ALIAS(DRIVER_ALIAS); | |||
183 | 182 | ||
184 | #define YES_NO(x) ((x) ? "Yes" : "No") | 183 | #define YES_NO(x) ((x) ? "Yes" : "No") |
185 | 184 | ||
186 | static inline struct usb_usbvision *cd_to_usbvision(struct class_device *cd) | 185 | static inline struct usb_usbvision *cd_to_usbvision(struct device *cd) |
187 | { | 186 | { |
188 | struct video_device *vdev = | 187 | struct video_device *vdev = |
189 | container_of(cd, struct video_device, class_dev); | 188 | container_of(cd, struct video_device, class_dev); |
190 | return video_get_drvdata(vdev); | 189 | return video_get_drvdata(vdev); |
191 | } | 190 | } |
192 | 191 | ||
193 | static ssize_t show_version(struct class_device *cd, char *buf) | 192 | static ssize_t show_version(struct device *cd, |
193 | struct device_attribute *attr, char *buf) | ||
194 | { | 194 | { |
195 | return sprintf(buf, "%s\n", USBVISION_VERSION_STRING); | 195 | return sprintf(buf, "%s\n", USBVISION_VERSION_STRING); |
196 | } | 196 | } |
197 | static CLASS_DEVICE_ATTR(version, S_IRUGO, show_version, NULL); | 197 | static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); |
198 | 198 | ||
199 | static ssize_t show_model(struct class_device *cd, char *buf) | 199 | static ssize_t show_model(struct device *cd, |
200 | struct device_attribute *attr, char *buf) | ||
200 | { | 201 | { |
201 | struct video_device *vdev = | 202 | struct video_device *vdev = |
202 | container_of(cd, struct video_device, class_dev); | 203 | container_of(cd, struct video_device, class_dev); |
@@ -204,9 +205,10 @@ static ssize_t show_model(struct class_device *cd, char *buf) | |||
204 | return sprintf(buf, "%s\n", | 205 | return sprintf(buf, "%s\n", |
205 | usbvision_device_data[usbvision->DevModel].ModelString); | 206 | usbvision_device_data[usbvision->DevModel].ModelString); |
206 | } | 207 | } |
207 | static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL); | 208 | static DEVICE_ATTR(model, S_IRUGO, show_model, NULL); |
208 | 209 | ||
209 | static ssize_t show_hue(struct class_device *cd, char *buf) | 210 | static ssize_t show_hue(struct device *cd, |
211 | struct device_attribute *attr, char *buf) | ||
210 | { | 212 | { |
211 | struct video_device *vdev = | 213 | struct video_device *vdev = |
212 | container_of(cd, struct video_device, class_dev); | 214 | container_of(cd, struct video_device, class_dev); |
@@ -218,9 +220,10 @@ static ssize_t show_hue(struct class_device *cd, char *buf) | |||
218 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | 220 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); |
219 | return sprintf(buf, "%d\n", ctrl.value); | 221 | return sprintf(buf, "%d\n", ctrl.value); |
220 | } | 222 | } |
221 | static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); | 223 | static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); |
222 | 224 | ||
223 | static ssize_t show_contrast(struct class_device *cd, char *buf) | 225 | static ssize_t show_contrast(struct device *cd, |
226 | struct device_attribute *attr, char *buf) | ||
224 | { | 227 | { |
225 | struct video_device *vdev = | 228 | struct video_device *vdev = |
226 | container_of(cd, struct video_device, class_dev); | 229 | container_of(cd, struct video_device, class_dev); |
@@ -232,9 +235,10 @@ static ssize_t show_contrast(struct class_device *cd, char *buf) | |||
232 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | 235 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); |
233 | return sprintf(buf, "%d\n", ctrl.value); | 236 | return sprintf(buf, "%d\n", ctrl.value); |
234 | } | 237 | } |
235 | static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); | 238 | static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); |
236 | 239 | ||
237 | static ssize_t show_brightness(struct class_device *cd, char *buf) | 240 | static ssize_t show_brightness(struct device *cd, |
241 | struct device_attribute *attr, char *buf) | ||
238 | { | 242 | { |
239 | struct video_device *vdev = | 243 | struct video_device *vdev = |
240 | container_of(cd, struct video_device, class_dev); | 244 | container_of(cd, struct video_device, class_dev); |
@@ -246,9 +250,10 @@ static ssize_t show_brightness(struct class_device *cd, char *buf) | |||
246 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | 250 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); |
247 | return sprintf(buf, "%d\n", ctrl.value); | 251 | return sprintf(buf, "%d\n", ctrl.value); |
248 | } | 252 | } |
249 | static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); | 253 | static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); |
250 | 254 | ||
251 | static ssize_t show_saturation(struct class_device *cd, char *buf) | 255 | static ssize_t show_saturation(struct device *cd, |
256 | struct device_attribute *attr, char *buf) | ||
252 | { | 257 | { |
253 | struct video_device *vdev = | 258 | struct video_device *vdev = |
254 | container_of(cd, struct video_device, class_dev); | 259 | container_of(cd, struct video_device, class_dev); |
@@ -260,9 +265,10 @@ static ssize_t show_saturation(struct class_device *cd, char *buf) | |||
260 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | 265 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); |
261 | return sprintf(buf, "%d\n", ctrl.value); | 266 | return sprintf(buf, "%d\n", ctrl.value); |
262 | } | 267 | } |
263 | static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); | 268 | static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); |
264 | 269 | ||
265 | static ssize_t show_streaming(struct class_device *cd, char *buf) | 270 | static ssize_t show_streaming(struct device *cd, |
271 | struct device_attribute *attr, char *buf) | ||
266 | { | 272 | { |
267 | struct video_device *vdev = | 273 | struct video_device *vdev = |
268 | container_of(cd, struct video_device, class_dev); | 274 | container_of(cd, struct video_device, class_dev); |
@@ -270,9 +276,10 @@ static ssize_t show_streaming(struct class_device *cd, char *buf) | |||
270 | return sprintf(buf, "%s\n", | 276 | return sprintf(buf, "%s\n", |
271 | YES_NO(usbvision->streaming==Stream_On?1:0)); | 277 | YES_NO(usbvision->streaming==Stream_On?1:0)); |
272 | } | 278 | } |
273 | static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); | 279 | static DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); |
274 | 280 | ||
275 | static ssize_t show_compression(struct class_device *cd, char *buf) | 281 | static ssize_t show_compression(struct device *cd, |
282 | struct device_attribute *attr, char *buf) | ||
276 | { | 283 | { |
277 | struct video_device *vdev = | 284 | struct video_device *vdev = |
278 | container_of(cd, struct video_device, class_dev); | 285 | container_of(cd, struct video_device, class_dev); |
@@ -280,16 +287,17 @@ static ssize_t show_compression(struct class_device *cd, char *buf) | |||
280 | return sprintf(buf, "%s\n", | 287 | return sprintf(buf, "%s\n", |
281 | YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS)); | 288 | YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS)); |
282 | } | 289 | } |
283 | static CLASS_DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); | 290 | static DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); |
284 | 291 | ||
285 | static ssize_t show_device_bridge(struct class_device *cd, char *buf) | 292 | static ssize_t show_device_bridge(struct device *cd, |
293 | struct device_attribute *attr, char *buf) | ||
286 | { | 294 | { |
287 | struct video_device *vdev = | 295 | struct video_device *vdev = |
288 | container_of(cd, struct video_device, class_dev); | 296 | container_of(cd, struct video_device, class_dev); |
289 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | 297 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); |
290 | return sprintf(buf, "%d\n", usbvision->bridgeType); | 298 | return sprintf(buf, "%d\n", usbvision->bridgeType); |
291 | } | 299 | } |
292 | static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL); | 300 | static DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL); |
293 | 301 | ||
294 | static void usbvision_create_sysfs(struct video_device *vdev) | 302 | static void usbvision_create_sysfs(struct video_device *vdev) |
295 | { | 303 | { |
@@ -297,40 +305,40 @@ static void usbvision_create_sysfs(struct video_device *vdev) | |||
297 | if (!vdev) | 305 | if (!vdev) |
298 | return; | 306 | return; |
299 | do { | 307 | do { |
300 | res=class_device_create_file(&vdev->class_dev, | 308 | res = device_create_file(&vdev->class_dev, |
301 | &class_device_attr_version); | 309 | &dev_attr_version); |
302 | if (res<0) | 310 | if (res<0) |
303 | break; | 311 | break; |
304 | res=class_device_create_file(&vdev->class_dev, | 312 | res = device_create_file(&vdev->class_dev, |
305 | &class_device_attr_model); | 313 | &dev_attr_model); |
306 | if (res<0) | 314 | if (res<0) |
307 | break; | 315 | break; |
308 | res=class_device_create_file(&vdev->class_dev, | 316 | res = device_create_file(&vdev->class_dev, |
309 | &class_device_attr_hue); | 317 | &dev_attr_hue); |
310 | if (res<0) | 318 | if (res<0) |
311 | break; | 319 | break; |
312 | res=class_device_create_file(&vdev->class_dev, | 320 | res = device_create_file(&vdev->class_dev, |
313 | &class_device_attr_contrast); | 321 | &dev_attr_contrast); |
314 | if (res<0) | 322 | if (res<0) |
315 | break; | 323 | break; |
316 | res=class_device_create_file(&vdev->class_dev, | 324 | res = device_create_file(&vdev->class_dev, |
317 | &class_device_attr_brightness); | 325 | &dev_attr_brightness); |
318 | if (res<0) | 326 | if (res<0) |
319 | break; | 327 | break; |
320 | res=class_device_create_file(&vdev->class_dev, | 328 | res = device_create_file(&vdev->class_dev, |
321 | &class_device_attr_saturation); | 329 | &dev_attr_saturation); |
322 | if (res<0) | 330 | if (res<0) |
323 | break; | 331 | break; |
324 | res=class_device_create_file(&vdev->class_dev, | 332 | res = device_create_file(&vdev->class_dev, |
325 | &class_device_attr_streaming); | 333 | &dev_attr_streaming); |
326 | if (res<0) | 334 | if (res<0) |
327 | break; | 335 | break; |
328 | res=class_device_create_file(&vdev->class_dev, | 336 | res = device_create_file(&vdev->class_dev, |
329 | &class_device_attr_compression); | 337 | &dev_attr_compression); |
330 | if (res<0) | 338 | if (res<0) |
331 | break; | 339 | break; |
332 | res=class_device_create_file(&vdev->class_dev, | 340 | res = device_create_file(&vdev->class_dev, |
333 | &class_device_attr_bridge); | 341 | &dev_attr_bridge); |
334 | if (res>=0) | 342 | if (res>=0) |
335 | return; | 343 | return; |
336 | } while (0); | 344 | } while (0); |
@@ -341,24 +349,24 @@ static void usbvision_create_sysfs(struct video_device *vdev) | |||
341 | static void usbvision_remove_sysfs(struct video_device *vdev) | 349 | static void usbvision_remove_sysfs(struct video_device *vdev) |
342 | { | 350 | { |
343 | if (vdev) { | 351 | if (vdev) { |
344 | class_device_remove_file(&vdev->class_dev, | 352 | device_remove_file(&vdev->class_dev, |
345 | &class_device_attr_version); | 353 | &dev_attr_version); |
346 | class_device_remove_file(&vdev->class_dev, | 354 | device_remove_file(&vdev->class_dev, |
347 | &class_device_attr_model); | 355 | &dev_attr_model); |
348 | class_device_remove_file(&vdev->class_dev, | 356 | device_remove_file(&vdev->class_dev, |
349 | &class_device_attr_hue); | 357 | &dev_attr_hue); |
350 | class_device_remove_file(&vdev->class_dev, | 358 | device_remove_file(&vdev->class_dev, |
351 | &class_device_attr_contrast); | 359 | &dev_attr_contrast); |
352 | class_device_remove_file(&vdev->class_dev, | 360 | device_remove_file(&vdev->class_dev, |
353 | &class_device_attr_brightness); | 361 | &dev_attr_brightness); |
354 | class_device_remove_file(&vdev->class_dev, | 362 | device_remove_file(&vdev->class_dev, |
355 | &class_device_attr_saturation); | 363 | &dev_attr_saturation); |
356 | class_device_remove_file(&vdev->class_dev, | 364 | device_remove_file(&vdev->class_dev, |
357 | &class_device_attr_streaming); | 365 | &dev_attr_streaming); |
358 | class_device_remove_file(&vdev->class_dev, | 366 | device_remove_file(&vdev->class_dev, |
359 | &class_device_attr_compression); | 367 | &dev_attr_compression); |
360 | class_device_remove_file(&vdev->class_dev, | 368 | device_remove_file(&vdev->class_dev, |
361 | &class_device_attr_bridge); | 369 | &dev_attr_bridge); |
362 | } | 370 | } |
363 | } | 371 | } |
364 | 372 | ||
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index ede8543818bf..9eac65f34bff 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c | |||
@@ -19,7 +19,6 @@ | |||
19 | 19 | ||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/types.h> | 22 | #include <linux/types.h> |
24 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
25 | #include <linux/sched.h> | 24 | #include <linux/sched.h> |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index d2915d3530ea..c3440b280d20 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -65,11 +65,6 @@ | |||
65 | #include <linux/kmod.h> | 65 | #include <linux/kmod.h> |
66 | #endif | 66 | #endif |
67 | 67 | ||
68 | #if defined(CONFIG_UST) || defined(CONFIG_UST_MODULE) | ||
69 | #include <linux/ust.h> | ||
70 | #endif | ||
71 | |||
72 | |||
73 | #include <linux/videodev.h> | 68 | #include <linux/videodev.h> |
74 | 69 | ||
75 | MODULE_AUTHOR("Bill Dirks, Justin Schoeman, Gerd Knorr"); | 70 | MODULE_AUTHOR("Bill Dirks, Justin Schoeman, Gerd Knorr"); |
@@ -716,6 +711,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste | |||
716 | case V4L2_CID_AUDIO_MUTE: | 711 | case V4L2_CID_AUDIO_MUTE: |
717 | case V4L2_CID_AUDIO_LOUDNESS: | 712 | case V4L2_CID_AUDIO_LOUDNESS: |
718 | case V4L2_CID_MPEG_AUDIO_MUTE: | 713 | case V4L2_CID_MPEG_AUDIO_MUTE: |
714 | case V4L2_CID_MPEG_VIDEO_MUTE: | ||
719 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: | 715 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: |
720 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: | 716 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: |
721 | qctrl->type = V4L2_CTRL_TYPE_BOOLEAN; | 717 | qctrl->type = V4L2_CTRL_TYPE_BOOLEAN; |
diff --git a/drivers/media/video/v4l2-int-device.c b/drivers/media/video/v4l2-int-device.c new file mode 100644 index 000000000000..8b4ef530a3a8 --- /dev/null +++ b/drivers/media/video/v4l2-int-device.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * drivers/media/video/v4l2-int-device.c | ||
3 | * | ||
4 | * V4L2 internal ioctl interface. | ||
5 | * | ||
6 | * Copyright (C) 2007 Nokia Corporation. | ||
7 | * | ||
8 | * Contact: Sakari Ailus <sakari.ailus@nokia.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
22 | * 02110-1301 USA | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/list.h> | ||
27 | #include <linux/sort.h> | ||
28 | #include <linux/string.h> | ||
29 | |||
30 | #include <media/v4l2-int-device.h> | ||
31 | |||
32 | static DEFINE_MUTEX(mutex); | ||
33 | static LIST_HEAD(int_list); | ||
34 | |||
35 | static void v4l2_int_device_try_attach_all(void) | ||
36 | { | ||
37 | struct v4l2_int_device *m, *s; | ||
38 | |||
39 | list_for_each_entry(m, &int_list, head) { | ||
40 | if (m->type != v4l2_int_type_master) | ||
41 | continue; | ||
42 | |||
43 | list_for_each_entry(s, &int_list, head) { | ||
44 | if (s->type != v4l2_int_type_slave) | ||
45 | continue; | ||
46 | |||
47 | /* Slave is connected? */ | ||
48 | if (s->u.slave->master) | ||
49 | continue; | ||
50 | |||
51 | /* Slave wants to attach to master? */ | ||
52 | if (s->u.slave->attach_to[0] != 0 | ||
53 | && strncmp(m->name, s->u.slave->attach_to, | ||
54 | V4L2NAMESIZE)) | ||
55 | continue; | ||
56 | |||
57 | if (!try_module_get(m->module)) | ||
58 | continue; | ||
59 | |||
60 | if (m->u.master->attach(m, s)) { | ||
61 | module_put(m->module); | ||
62 | continue; | ||
63 | } | ||
64 | |||
65 | s->u.slave->master = m; | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | static int ioctl_sort_cmp(const void *a, const void *b) | ||
71 | { | ||
72 | const struct v4l2_int_ioctl_desc *d1 = a, *d2 = b; | ||
73 | |||
74 | if (d1->num > d2->num) | ||
75 | return 1; | ||
76 | |||
77 | if (d1->num < d2->num) | ||
78 | return -1; | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | int v4l2_int_device_register(struct v4l2_int_device *d) | ||
84 | { | ||
85 | if (d->type == v4l2_int_type_slave) | ||
86 | sort(d->u.slave->ioctls, d->u.slave->num_ioctls, | ||
87 | sizeof(struct v4l2_int_ioctl_desc), | ||
88 | &ioctl_sort_cmp, NULL); | ||
89 | mutex_lock(&mutex); | ||
90 | list_add(&d->head, &int_list); | ||
91 | v4l2_int_device_try_attach_all(); | ||
92 | mutex_unlock(&mutex); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | EXPORT_SYMBOL_GPL(v4l2_int_device_register); | ||
97 | |||
98 | void v4l2_int_device_unregister(struct v4l2_int_device *d) | ||
99 | { | ||
100 | mutex_lock(&mutex); | ||
101 | list_del(&d->head); | ||
102 | if (d->type == v4l2_int_type_slave | ||
103 | && d->u.slave->master != NULL) { | ||
104 | d->u.slave->master->u.master->detach(d); | ||
105 | module_put(d->u.slave->master->module); | ||
106 | d->u.slave->master = NULL; | ||
107 | } | ||
108 | mutex_unlock(&mutex); | ||
109 | } | ||
110 | EXPORT_SYMBOL_GPL(v4l2_int_device_unregister); | ||
111 | |||
112 | /* Adapted from search_extable in extable.c. */ | ||
113 | static v4l2_int_ioctl_func *find_ioctl(struct v4l2_int_slave *slave, int cmd, | ||
114 | v4l2_int_ioctl_func *no_such_ioctl) | ||
115 | { | ||
116 | const struct v4l2_int_ioctl_desc *first = slave->ioctls; | ||
117 | const struct v4l2_int_ioctl_desc *last = | ||
118 | first + slave->num_ioctls - 1; | ||
119 | |||
120 | while (first <= last) { | ||
121 | const struct v4l2_int_ioctl_desc *mid; | ||
122 | |||
123 | mid = (last - first) / 2 + first; | ||
124 | |||
125 | if (mid->num < cmd) | ||
126 | first = mid + 1; | ||
127 | else if (mid->num > cmd) | ||
128 | last = mid - 1; | ||
129 | else | ||
130 | return mid->func; | ||
131 | } | ||
132 | |||
133 | return no_such_ioctl; | ||
134 | } | ||
135 | |||
136 | static int no_such_ioctl_0(struct v4l2_int_device *d) | ||
137 | { | ||
138 | return -ENOIOCTLCMD; | ||
139 | } | ||
140 | |||
141 | int v4l2_int_ioctl_0(struct v4l2_int_device *d, int cmd) | ||
142 | { | ||
143 | return ((v4l2_int_ioctl_func_0 *) | ||
144 | find_ioctl(d->u.slave, cmd, | ||
145 | (v4l2_int_ioctl_func *)no_such_ioctl_0))(d); | ||
146 | } | ||
147 | |||
148 | static int no_such_ioctl_1(struct v4l2_int_device *d, void *arg) | ||
149 | { | ||
150 | return -ENOIOCTLCMD; | ||
151 | } | ||
152 | |||
153 | int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg) | ||
154 | { | ||
155 | return ((v4l2_int_ioctl_func_1 *) | ||
156 | find_ioctl(d->u.slave, cmd, | ||
157 | (v4l2_int_ioctl_func *)no_such_ioctl_1))(d, arg); | ||
158 | } | ||
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/videobuf-core.c index a32dfbe0585a..c606332512b6 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/videobuf-core.c | |||
@@ -1,313 +1,63 @@ | |||
1 | /* | 1 | /* |
2 | * generic helper functions for handling video4linux capture buffers | ||
2 | * | 3 | * |
3 | * generic helper functions for video4linux capture buffers, to handle | 4 | * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org> |
4 | * memory management and PCI DMA. | ||
5 | * Right now, bttv, saa7134, saa7146 and cx88 use it. | ||
6 | * | 5 | * |
7 | * The functions expect the hardware being able to scatter gatter | 6 | * Highly based on video-buf written originally by: |
8 | * (i.e. the buffers are not linear in physical memory, but fragmented | 7 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> |
9 | * into PAGE_SIZE chunks). They also assume the driver does not need | 8 | * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org> |
10 | * to touch the video data. | ||
11 | * | ||
12 | * device specific map/unmap/sync stuff now are mapped as operations | ||
13 | * to allow its usage by USB and virtual devices. | ||
14 | * | ||
15 | * (c) 2001-2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs] | ||
16 | * (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org> | ||
17 | * (c) 2006 Ted Walther and John Sokol | 9 | * (c) 2006 Ted Walther and John Sokol |
18 | * | 10 | * |
19 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
20 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
21 | * the Free Software Foundation; either version 2 of the License, or | 13 | * the Free Software Foundation; either version 2 |
22 | * (at your option) any later version. | ||
23 | */ | 14 | */ |
24 | 15 | ||
25 | #include <linux/init.h> | 16 | #include <linux/init.h> |
26 | #include <linux/module.h> | 17 | #include <linux/module.h> |
27 | #include <linux/moduleparam.h> | 18 | #include <linux/moduleparam.h> |
28 | #include <linux/vmalloc.h> | ||
29 | #include <linux/pagemap.h> | ||
30 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
31 | #include <linux/pci.h> | ||
32 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
33 | #include <asm/page.h> | ||
34 | #include <asm/pgtable.h> | ||
35 | 21 | ||
36 | #include <media/video-buf.h> | 22 | #include <media/videobuf-core.h> |
37 | 23 | ||
38 | #define MAGIC_DMABUF 0x19721112 | 24 | #define MAGIC_BUFFER 0x20070728 |
39 | #define MAGIC_BUFFER 0x20040302 | ||
40 | #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ | 25 | #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ |
41 | { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } | 26 | { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } |
42 | 27 | ||
43 | static int debug = 0; | 28 | static int debug = 0; |
44 | module_param(debug, int, 0644); | 29 | module_param(debug, int, 0644); |
45 | 30 | ||
46 | MODULE_DESCRIPTION("helper module to manage video4linux pci dma buffers"); | 31 | MODULE_DESCRIPTION("helper module to manage video4linux buffers"); |
47 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | 32 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); |
48 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
49 | 34 | ||
50 | #define dprintk(level, fmt, arg...) if (debug >= level) \ | 35 | #define dprintk(level, fmt, arg...) if (debug >= level) \ |
51 | printk(KERN_DEBUG "vbuf: " fmt , ## arg) | 36 | printk(KERN_DEBUG "vbuf: " fmt , ## arg) |
52 | 37 | ||
53 | struct scatterlist* | ||
54 | videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) | ||
55 | { | ||
56 | struct scatterlist *sglist; | ||
57 | struct page *pg; | ||
58 | int i; | ||
59 | |||
60 | sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL); | ||
61 | if (NULL == sglist) | ||
62 | return NULL; | ||
63 | for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) { | ||
64 | pg = vmalloc_to_page(virt); | ||
65 | if (NULL == pg) | ||
66 | goto err; | ||
67 | BUG_ON(PageHighMem(pg)); | ||
68 | sglist[i].page = pg; | ||
69 | sglist[i].length = PAGE_SIZE; | ||
70 | } | ||
71 | return sglist; | ||
72 | |||
73 | err: | ||
74 | kfree(sglist); | ||
75 | return NULL; | ||
76 | } | ||
77 | |||
78 | struct scatterlist* | ||
79 | videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) | ||
80 | { | ||
81 | struct scatterlist *sglist; | ||
82 | int i = 0; | ||
83 | |||
84 | if (NULL == pages[0]) | ||
85 | return NULL; | ||
86 | sglist = kcalloc(nr_pages, sizeof(*sglist), GFP_KERNEL); | ||
87 | if (NULL == sglist) | ||
88 | return NULL; | ||
89 | |||
90 | if (NULL == pages[0]) | ||
91 | goto nopage; | ||
92 | if (PageHighMem(pages[0])) | ||
93 | /* DMA to highmem pages might not work */ | ||
94 | goto highmem; | ||
95 | sglist[0].page = pages[0]; | ||
96 | sglist[0].offset = offset; | ||
97 | sglist[0].length = PAGE_SIZE - offset; | ||
98 | for (i = 1; i < nr_pages; i++) { | ||
99 | if (NULL == pages[i]) | ||
100 | goto nopage; | ||
101 | if (PageHighMem(pages[i])) | ||
102 | goto highmem; | ||
103 | sglist[i].page = pages[i]; | ||
104 | sglist[i].length = PAGE_SIZE; | ||
105 | } | ||
106 | return sglist; | ||
107 | |||
108 | nopage: | ||
109 | dprintk(2,"sgl: oops - no page\n"); | ||
110 | kfree(sglist); | ||
111 | return NULL; | ||
112 | |||
113 | highmem: | ||
114 | dprintk(2,"sgl: oops - highmem page\n"); | ||
115 | kfree(sglist); | ||
116 | return NULL; | ||
117 | } | ||
118 | |||
119 | /* --------------------------------------------------------------------- */ | 38 | /* --------------------------------------------------------------------- */ |
120 | 39 | ||
121 | void videobuf_dma_init(struct videobuf_dmabuf *dma) | 40 | #define CALL(q, f, arg...) \ |
122 | { | 41 | ( (q->int_ops->f)? q->int_ops->f(arg) : 0) |
123 | memset(dma,0,sizeof(*dma)); | ||
124 | dma->magic = MAGIC_DMABUF; | ||
125 | } | ||
126 | 42 | ||
127 | int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, | 43 | void* videobuf_alloc(struct videobuf_queue* q) |
128 | unsigned long data, unsigned long size) | ||
129 | { | 44 | { |
130 | unsigned long first,last; | 45 | struct videobuf_buffer *vb; |
131 | int err, rw = 0; | ||
132 | |||
133 | dma->direction = direction; | ||
134 | switch (dma->direction) { | ||
135 | case PCI_DMA_FROMDEVICE: rw = READ; break; | ||
136 | case PCI_DMA_TODEVICE: rw = WRITE; break; | ||
137 | default: BUG(); | ||
138 | } | ||
139 | |||
140 | first = (data & PAGE_MASK) >> PAGE_SHIFT; | ||
141 | last = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT; | ||
142 | dma->offset = data & ~PAGE_MASK; | ||
143 | dma->nr_pages = last-first+1; | ||
144 | dma->pages = kmalloc(dma->nr_pages * sizeof(struct page*), | ||
145 | GFP_KERNEL); | ||
146 | if (NULL == dma->pages) | ||
147 | return -ENOMEM; | ||
148 | dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n", | ||
149 | data,size,dma->nr_pages); | ||
150 | |||
151 | dma->varea = (void *) data; | ||
152 | |||
153 | down_read(¤t->mm->mmap_sem); | ||
154 | err = get_user_pages(current,current->mm, | ||
155 | data & PAGE_MASK, dma->nr_pages, | ||
156 | rw == READ, 1, /* force */ | ||
157 | dma->pages, NULL); | ||
158 | up_read(¤t->mm->mmap_sem); | ||
159 | if (err != dma->nr_pages) { | ||
160 | dma->nr_pages = (err >= 0) ? err : 0; | ||
161 | dprintk(1,"get_user_pages: err=%d [%d]\n",err,dma->nr_pages); | ||
162 | return err < 0 ? err : -EINVAL; | ||
163 | } | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, | ||
168 | int nr_pages) | ||
169 | { | ||
170 | dprintk(1,"init kernel [%d pages]\n",nr_pages); | ||
171 | dma->direction = direction; | ||
172 | dma->vmalloc = vmalloc_32(nr_pages << PAGE_SHIFT); | ||
173 | if (NULL == dma->vmalloc) { | ||
174 | dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages); | ||
175 | return -ENOMEM; | ||
176 | } | ||
177 | dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n", | ||
178 | (unsigned long)dma->vmalloc, | ||
179 | nr_pages << PAGE_SHIFT); | ||
180 | memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT); | ||
181 | dma->nr_pages = nr_pages; | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, | ||
186 | dma_addr_t addr, int nr_pages) | ||
187 | { | ||
188 | dprintk(1,"init overlay [%d pages @ bus 0x%lx]\n", | ||
189 | nr_pages,(unsigned long)addr); | ||
190 | dma->direction = direction; | ||
191 | if (0 == addr) | ||
192 | return -EINVAL; | ||
193 | |||
194 | dma->bus_addr = addr; | ||
195 | dma->nr_pages = nr_pages; | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) | ||
200 | { | ||
201 | void *dev=q->dev; | ||
202 | |||
203 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); | ||
204 | BUG_ON(0 == dma->nr_pages); | ||
205 | |||
206 | if (dma->pages) { | ||
207 | dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages, | ||
208 | dma->offset); | ||
209 | } | ||
210 | if (dma->vmalloc) { | ||
211 | dma->sglist = videobuf_vmalloc_to_sg | ||
212 | (dma->vmalloc,dma->nr_pages); | ||
213 | } | ||
214 | if (dma->bus_addr) { | ||
215 | dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL); | ||
216 | if (NULL != dma->sglist) { | ||
217 | dma->sglen = 1; | ||
218 | sg_dma_address(&dma->sglist[0]) = dma->bus_addr & PAGE_MASK; | ||
219 | dma->sglist[0].offset = dma->bus_addr & ~PAGE_MASK; | ||
220 | sg_dma_len(&dma->sglist[0]) = dma->nr_pages * PAGE_SIZE; | ||
221 | } | ||
222 | } | ||
223 | if (NULL == dma->sglist) { | ||
224 | dprintk(1,"scatterlist is NULL\n"); | ||
225 | return -ENOMEM; | ||
226 | } | ||
227 | if (!dma->bus_addr) { | ||
228 | if (q->ops->vb_map_sg) { | ||
229 | dma->sglen = q->ops->vb_map_sg(dev,dma->sglist, | ||
230 | dma->nr_pages, dma->direction); | ||
231 | } | ||
232 | if (0 == dma->sglen) { | ||
233 | printk(KERN_WARNING | ||
234 | "%s: videobuf_map_sg failed\n",__FUNCTION__); | ||
235 | kfree(dma->sglist); | ||
236 | dma->sglist = NULL; | ||
237 | dma->sglen = 0; | ||
238 | return -EIO; | ||
239 | } | ||
240 | } | ||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma) | ||
245 | { | ||
246 | void *dev=q->dev; | ||
247 | |||
248 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); | ||
249 | BUG_ON(!dma->sglen); | ||
250 | |||
251 | if (!dma->bus_addr && q->ops->vb_dma_sync_sg) | ||
252 | q->ops->vb_dma_sync_sg(dev,dma->sglist,dma->nr_pages, | ||
253 | dma->direction); | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) | ||
259 | { | ||
260 | void *dev=q->dev; | ||
261 | |||
262 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); | ||
263 | if (!dma->sglen) | ||
264 | return 0; | ||
265 | |||
266 | if (!dma->bus_addr && q->ops->vb_unmap_sg) | ||
267 | q->ops->vb_unmap_sg(dev,dma->sglist,dma->nr_pages, | ||
268 | dma->direction); | ||
269 | kfree(dma->sglist); | ||
270 | dma->sglist = NULL; | ||
271 | dma->sglen = 0; | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | int videobuf_dma_free(struct videobuf_dmabuf *dma) | ||
276 | { | ||
277 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); | ||
278 | BUG_ON(dma->sglen); | ||
279 | |||
280 | if (dma->pages) { | ||
281 | int i; | ||
282 | for (i=0; i < dma->nr_pages; i++) | ||
283 | page_cache_release(dma->pages[i]); | ||
284 | kfree(dma->pages); | ||
285 | dma->pages = NULL; | ||
286 | } | ||
287 | 46 | ||
288 | vfree(dma->vmalloc); | 47 | BUG_ON (q->msize<sizeof(*vb)); |
289 | dma->vmalloc = NULL; | ||
290 | dma->varea = NULL; | ||
291 | 48 | ||
292 | if (dma->bus_addr) { | 49 | if (!q->int_ops || !q->int_ops->alloc) { |
293 | dma->bus_addr = 0; | 50 | printk(KERN_ERR "No specific ops defined!\n"); |
51 | BUG(); | ||
294 | } | 52 | } |
295 | dma->direction = PCI_DMA_NONE; | ||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | /* --------------------------------------------------------------------- */ | ||
300 | 53 | ||
301 | void* videobuf_alloc(unsigned int size) | 54 | vb = q->int_ops->alloc(q->msize); |
302 | { | ||
303 | struct videobuf_buffer *vb; | ||
304 | 55 | ||
305 | vb = kzalloc(size,GFP_KERNEL); | ||
306 | if (NULL != vb) { | 56 | if (NULL != vb) { |
307 | videobuf_dma_init(&vb->dma); | ||
308 | init_waitqueue_head(&vb->done); | 57 | init_waitqueue_head(&vb->done); |
309 | vb->magic = MAGIC_BUFFER; | 58 | vb->magic = MAGIC_BUFFER; |
310 | } | 59 | } |
60 | |||
311 | return vb; | 61 | return vb; |
312 | } | 62 | } |
313 | 63 | ||
@@ -338,127 +88,65 @@ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr) | |||
338 | return retval; | 88 | return retval; |
339 | } | 89 | } |
340 | 90 | ||
341 | int | 91 | int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, |
342 | videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, | 92 | struct v4l2_framebuffer *fbuf) |
343 | struct v4l2_framebuffer *fbuf) | ||
344 | { | 93 | { |
345 | int err,pages; | ||
346 | dma_addr_t bus; | ||
347 | |||
348 | MAGIC_CHECK(vb->magic,MAGIC_BUFFER); | 94 | MAGIC_CHECK(vb->magic,MAGIC_BUFFER); |
349 | switch (vb->memory) { | 95 | MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); |
350 | case V4L2_MEMORY_MMAP: | ||
351 | case V4L2_MEMORY_USERPTR: | ||
352 | if (0 == vb->baddr) { | ||
353 | /* no userspace addr -- kernel bounce buffer */ | ||
354 | pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; | ||
355 | err = videobuf_dma_init_kernel(&vb->dma,PCI_DMA_FROMDEVICE, | ||
356 | pages); | ||
357 | if (0 != err) | ||
358 | return err; | ||
359 | } else { | ||
360 | /* dma directly to userspace */ | ||
361 | err = videobuf_dma_init_user(&vb->dma,PCI_DMA_FROMDEVICE, | ||
362 | vb->baddr,vb->bsize); | ||
363 | if (0 != err) | ||
364 | return err; | ||
365 | } | ||
366 | break; | ||
367 | case V4L2_MEMORY_OVERLAY: | ||
368 | if (NULL == fbuf) | ||
369 | return -EINVAL; | ||
370 | /* FIXME: need sanity checks for vb->boff */ | ||
371 | /* | ||
372 | * Using a double cast to avoid compiler warnings when | ||
373 | * building for PAE. Compiler doesn't like direct casting | ||
374 | * of a 32 bit ptr to 64 bit integer. | ||
375 | */ | ||
376 | bus = (dma_addr_t)(unsigned long)fbuf->base + vb->boff; | ||
377 | pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; | ||
378 | err = videobuf_dma_init_overlay(&vb->dma,PCI_DMA_FROMDEVICE, | ||
379 | bus, pages); | ||
380 | if (0 != err) | ||
381 | return err; | ||
382 | break; | ||
383 | default: | ||
384 | BUG(); | ||
385 | } | ||
386 | err = videobuf_dma_map(q,&vb->dma); | ||
387 | if (0 != err) | ||
388 | return err; | ||
389 | |||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | /* --------------------------------------------------------------------- */ | ||
394 | 96 | ||
395 | void videobuf_queue_pci(struct videobuf_queue* q) | 97 | /* FIXME: This is required to avoid OOPS on some cases, since mmap_mapper() |
396 | { | 98 | method should be called before _iolock. |
397 | /* If not specified, defaults to PCI map sg */ | 99 | On some cases, the mmap_mapper() is called only after scheduling. |
398 | if (!q->ops->vb_map_sg) | ||
399 | q->ops->vb_map_sg=(vb_map_sg_t *)pci_map_sg; | ||
400 | |||
401 | if (!q->ops->vb_dma_sync_sg) | ||
402 | q->ops->vb_dma_sync_sg=(vb_map_sg_t *)pci_dma_sync_sg_for_cpu; | ||
403 | if (!q->ops->vb_unmap_sg) | ||
404 | q->ops->vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg; | ||
405 | } | ||
406 | |||
407 | int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma) | ||
408 | { | ||
409 | struct videobuf_queue q; | ||
410 | struct videobuf_queue_ops qops; | ||
411 | 100 | ||
412 | q.dev=pci; | 101 | However, this way is just too dirty! Better to wait for some event. |
413 | qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg; | 102 | */ |
414 | qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg; | 103 | schedule_timeout(HZ); |
415 | q.ops = &qops; | ||
416 | 104 | ||
417 | return (videobuf_dma_map(&q,dma)); | 105 | return CALL(q,iolock,q,vb,fbuf); |
418 | } | 106 | } |
419 | 107 | ||
420 | int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma) | 108 | /* --------------------------------------------------------------------- */ |
421 | { | ||
422 | struct videobuf_queue q; | ||
423 | struct videobuf_queue_ops qops; | ||
424 | |||
425 | q.dev=pci; | ||
426 | qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg; | ||
427 | qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg; | ||
428 | q.ops = &qops; | ||
429 | 109 | ||
430 | return (videobuf_dma_unmap(&q,dma)); | ||
431 | } | ||
432 | 110 | ||
433 | void videobuf_queue_init(struct videobuf_queue* q, | 111 | void videobuf_queue_core_init(struct videobuf_queue* q, |
434 | struct videobuf_queue_ops *ops, | 112 | struct videobuf_queue_ops *ops, |
435 | void *dev, | 113 | void *dev, |
436 | spinlock_t *irqlock, | 114 | spinlock_t *irqlock, |
437 | enum v4l2_buf_type type, | 115 | enum v4l2_buf_type type, |
438 | enum v4l2_field field, | 116 | enum v4l2_field field, |
439 | unsigned int msize, | 117 | unsigned int msize, |
440 | void *priv) | 118 | void *priv, |
119 | struct videobuf_qtype_ops *int_ops) | ||
441 | { | 120 | { |
442 | memset(q,0,sizeof(*q)); | 121 | memset(q,0,sizeof(*q)); |
443 | q->irqlock = irqlock; | 122 | q->irqlock = irqlock; |
444 | q->dev = dev; | 123 | q->dev = dev; |
445 | q->type = type; | 124 | q->type = type; |
446 | q->field = field; | 125 | q->field = field; |
447 | q->msize = msize; | 126 | q->msize = msize; |
448 | q->ops = ops; | 127 | q->ops = ops; |
449 | q->priv_data = priv; | 128 | q->priv_data = priv; |
129 | q->int_ops = int_ops; | ||
450 | 130 | ||
451 | videobuf_queue_pci(q); | 131 | /* All buffer operations are mandatory */ |
132 | BUG_ON (!q->ops->buf_setup); | ||
133 | BUG_ON (!q->ops->buf_prepare); | ||
134 | BUG_ON (!q->ops->buf_queue); | ||
135 | BUG_ON (!q->ops->buf_release); | ||
136 | |||
137 | /* Having implementations for abstract methods are mandatory */ | ||
138 | BUG_ON (!q->int_ops); | ||
452 | 139 | ||
453 | mutex_init(&q->lock); | 140 | mutex_init(&q->lock); |
454 | INIT_LIST_HEAD(&q->stream); | 141 | INIT_LIST_HEAD(&q->stream); |
455 | } | 142 | } |
456 | 143 | ||
457 | int | 144 | int videobuf_queue_is_busy(struct videobuf_queue *q) |
458 | videobuf_queue_is_busy(struct videobuf_queue *q) | ||
459 | { | 145 | { |
460 | int i; | 146 | int i; |
461 | 147 | ||
148 | MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); | ||
149 | |||
462 | if (q->streaming) { | 150 | if (q->streaming) { |
463 | dprintk(1,"busy: streaming active\n"); | 151 | dprintk(1,"busy: streaming active\n"); |
464 | return 1; | 152 | return 1; |
@@ -490,8 +178,7 @@ videobuf_queue_is_busy(struct videobuf_queue *q) | |||
490 | return 0; | 178 | return 0; |
491 | } | 179 | } |
492 | 180 | ||
493 | void | 181 | void videobuf_queue_cancel(struct videobuf_queue *q) |
494 | videobuf_queue_cancel(struct videobuf_queue *q) | ||
495 | { | 182 | { |
496 | unsigned long flags=0; | 183 | unsigned long flags=0; |
497 | int i; | 184 | int i; |
@@ -521,8 +208,7 @@ videobuf_queue_cancel(struct videobuf_queue *q) | |||
521 | 208 | ||
522 | /* --------------------------------------------------------------------- */ | 209 | /* --------------------------------------------------------------------- */ |
523 | 210 | ||
524 | enum v4l2_field | 211 | enum v4l2_field videobuf_next_field(struct videobuf_queue *q) |
525 | videobuf_next_field(struct videobuf_queue *q) | ||
526 | { | 212 | { |
527 | enum v4l2_field field = q->field; | 213 | enum v4l2_field field = q->field; |
528 | 214 | ||
@@ -540,11 +226,11 @@ videobuf_next_field(struct videobuf_queue *q) | |||
540 | return field; | 226 | return field; |
541 | } | 227 | } |
542 | 228 | ||
543 | void | 229 | static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, |
544 | videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb, | 230 | struct videobuf_buffer *vb, enum v4l2_buf_type type) |
545 | enum v4l2_buf_type type) | ||
546 | { | 231 | { |
547 | MAGIC_CHECK(vb->magic,MAGIC_BUFFER); | 232 | MAGIC_CHECK(vb->magic,MAGIC_BUFFER); |
233 | MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); | ||
548 | 234 | ||
549 | b->index = vb->i; | 235 | b->index = vb->i; |
550 | b->type = type; | 236 | b->type = type; |
@@ -595,8 +281,7 @@ videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb, | |||
595 | b->sequence = vb->field_count >> 1; | 281 | b->sequence = vb->field_count >> 1; |
596 | } | 282 | } |
597 | 283 | ||
598 | int | 284 | int videobuf_reqbufs(struct videobuf_queue *q, |
599 | videobuf_reqbufs(struct videobuf_queue *q, | ||
600 | struct v4l2_requestbuffers *req) | 285 | struct v4l2_requestbuffers *req) |
601 | { | 286 | { |
602 | unsigned int size,count; | 287 | unsigned int size,count; |
@@ -617,16 +302,18 @@ videobuf_reqbufs(struct videobuf_queue *q, | |||
617 | return -EINVAL; | 302 | return -EINVAL; |
618 | } | 303 | } |
619 | 304 | ||
305 | mutex_lock(&q->lock); | ||
620 | if (q->streaming) { | 306 | if (q->streaming) { |
621 | dprintk(1,"reqbufs: streaming already exists\n"); | 307 | dprintk(1,"reqbufs: streaming already exists\n"); |
622 | return -EBUSY; | 308 | retval = -EBUSY; |
309 | goto done; | ||
623 | } | 310 | } |
624 | if (!list_empty(&q->stream)) { | 311 | if (!list_empty(&q->stream)) { |
625 | dprintk(1,"reqbufs: stream running\n"); | 312 | dprintk(1,"reqbufs: stream running\n"); |
626 | return -EBUSY; | 313 | retval = -EBUSY; |
314 | goto done; | ||
627 | } | 315 | } |
628 | 316 | ||
629 | mutex_lock(&q->lock); | ||
630 | count = req->count; | 317 | count = req->count; |
631 | if (count > VIDEO_MAX_FRAME) | 318 | if (count > VIDEO_MAX_FRAME) |
632 | count = VIDEO_MAX_FRAME; | 319 | count = VIDEO_MAX_FRAME; |
@@ -642,15 +329,14 @@ videobuf_reqbufs(struct videobuf_queue *q, | |||
642 | goto done; | 329 | goto done; |
643 | } | 330 | } |
644 | 331 | ||
645 | req->count = count; | 332 | req->count = retval; |
646 | 333 | ||
647 | done: | 334 | done: |
648 | mutex_unlock(&q->lock); | 335 | mutex_unlock(&q->lock); |
649 | return retval; | 336 | return retval; |
650 | } | 337 | } |
651 | 338 | ||
652 | int | 339 | int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) |
653 | videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) | ||
654 | { | 340 | { |
655 | if (unlikely(b->type != q->type)) { | 341 | if (unlikely(b->type != q->type)) { |
656 | dprintk(1,"querybuf: Wrong type.\n"); | 342 | dprintk(1,"querybuf: Wrong type.\n"); |
@@ -664,12 +350,11 @@ videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) | |||
664 | dprintk(1,"querybuf: buffer is null.\n"); | 350 | dprintk(1,"querybuf: buffer is null.\n"); |
665 | return -EINVAL; | 351 | return -EINVAL; |
666 | } | 352 | } |
667 | videobuf_status(b,q->bufs[b->index],q->type); | 353 | videobuf_status(q,b,q->bufs[b->index],q->type); |
668 | return 0; | 354 | return 0; |
669 | } | 355 | } |
670 | 356 | ||
671 | int | 357 | int videobuf_qbuf(struct videobuf_queue *q, |
672 | videobuf_qbuf(struct videobuf_queue *q, | ||
673 | struct v4l2_buffer *b) | 358 | struct v4l2_buffer *b) |
674 | { | 359 | { |
675 | struct videobuf_buffer *buf; | 360 | struct videobuf_buffer *buf; |
@@ -677,6 +362,11 @@ videobuf_qbuf(struct videobuf_queue *q, | |||
677 | unsigned long flags=0; | 362 | unsigned long flags=0; |
678 | int retval; | 363 | int retval; |
679 | 364 | ||
365 | MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); | ||
366 | |||
367 | if (b->memory == V4L2_MEMORY_MMAP) | ||
368 | down_read(¤t->mm->mmap_sem); | ||
369 | |||
680 | mutex_lock(&q->lock); | 370 | mutex_lock(&q->lock); |
681 | retval = -EBUSY; | 371 | retval = -EBUSY; |
682 | if (q->reading) { | 372 | if (q->reading) { |
@@ -762,16 +452,21 @@ videobuf_qbuf(struct videobuf_queue *q, | |||
762 | 452 | ||
763 | done: | 453 | done: |
764 | mutex_unlock(&q->lock); | 454 | mutex_unlock(&q->lock); |
455 | |||
456 | if (b->memory == V4L2_MEMORY_MMAP) | ||
457 | up_read(¤t->mm->mmap_sem); | ||
458 | |||
765 | return retval; | 459 | return retval; |
766 | } | 460 | } |
767 | 461 | ||
768 | int | 462 | int videobuf_dqbuf(struct videobuf_queue *q, |
769 | videobuf_dqbuf(struct videobuf_queue *q, | ||
770 | struct v4l2_buffer *b, int nonblocking) | 463 | struct v4l2_buffer *b, int nonblocking) |
771 | { | 464 | { |
772 | struct videobuf_buffer *buf; | 465 | struct videobuf_buffer *buf; |
773 | int retval; | 466 | int retval; |
774 | 467 | ||
468 | MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); | ||
469 | |||
775 | mutex_lock(&q->lock); | 470 | mutex_lock(&q->lock); |
776 | retval = -EBUSY; | 471 | retval = -EBUSY; |
777 | if (q->reading) { | 472 | if (q->reading) { |
@@ -797,12 +492,12 @@ videobuf_dqbuf(struct videobuf_queue *q, | |||
797 | case STATE_ERROR: | 492 | case STATE_ERROR: |
798 | dprintk(1,"dqbuf: state is error\n"); | 493 | dprintk(1,"dqbuf: state is error\n"); |
799 | retval = -EIO; | 494 | retval = -EIO; |
800 | videobuf_dma_sync(q,&buf->dma); | 495 | CALL(q,sync,q, buf); |
801 | buf->state = STATE_IDLE; | 496 | buf->state = STATE_IDLE; |
802 | break; | 497 | break; |
803 | case STATE_DONE: | 498 | case STATE_DONE: |
804 | dprintk(1,"dqbuf: state is done\n"); | 499 | dprintk(1,"dqbuf: state is done\n"); |
805 | videobuf_dma_sync(q,&buf->dma); | 500 | CALL(q,sync,q, buf); |
806 | buf->state = STATE_IDLE; | 501 | buf->state = STATE_IDLE; |
807 | break; | 502 | break; |
808 | default: | 503 | default: |
@@ -812,7 +507,7 @@ videobuf_dqbuf(struct videobuf_queue *q, | |||
812 | } | 507 | } |
813 | list_del(&buf->stream); | 508 | list_del(&buf->stream); |
814 | memset(b,0,sizeof(*b)); | 509 | memset(b,0,sizeof(*b)); |
815 | videobuf_status(b,buf,q->type); | 510 | videobuf_status(q,b,buf,q->type); |
816 | 511 | ||
817 | done: | 512 | done: |
818 | mutex_unlock(&q->lock); | 513 | mutex_unlock(&q->lock); |
@@ -822,7 +517,6 @@ videobuf_dqbuf(struct videobuf_queue *q, | |||
822 | int videobuf_streamon(struct videobuf_queue *q) | 517 | int videobuf_streamon(struct videobuf_queue *q) |
823 | { | 518 | { |
824 | struct videobuf_buffer *buf; | 519 | struct videobuf_buffer *buf; |
825 | struct list_head *list; | ||
826 | unsigned long flags=0; | 520 | unsigned long flags=0; |
827 | int retval; | 521 | int retval; |
828 | 522 | ||
@@ -836,11 +530,9 @@ int videobuf_streamon(struct videobuf_queue *q) | |||
836 | q->streaming = 1; | 530 | q->streaming = 1; |
837 | if (q->irqlock) | 531 | if (q->irqlock) |
838 | spin_lock_irqsave(q->irqlock,flags); | 532 | spin_lock_irqsave(q->irqlock,flags); |
839 | list_for_each(list,&q->stream) { | 533 | list_for_each_entry(buf, &q->stream, stream) |
840 | buf = list_entry(list, struct videobuf_buffer, stream); | ||
841 | if (buf->state == STATE_PREPARED) | 534 | if (buf->state == STATE_PREPARED) |
842 | q->ops->buf_queue(q,buf); | 535 | q->ops->buf_queue(q,buf); |
843 | } | ||
844 | if (q->irqlock) | 536 | if (q->irqlock) |
845 | spin_unlock_irqrestore(q->irqlock,flags); | 537 | spin_unlock_irqrestore(q->irqlock,flags); |
846 | 538 | ||
@@ -865,22 +557,25 @@ int videobuf_streamoff(struct videobuf_queue *q) | |||
865 | return retval; | 557 | return retval; |
866 | } | 558 | } |
867 | 559 | ||
868 | static ssize_t | 560 | static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, |
869 | videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, | 561 | char __user *data, |
870 | size_t count, loff_t *ppos) | 562 | size_t count, loff_t *ppos) |
871 | { | 563 | { |
872 | enum v4l2_field field; | 564 | enum v4l2_field field; |
873 | unsigned long flags=0; | 565 | unsigned long flags=0; |
874 | int retval; | 566 | int retval; |
875 | 567 | ||
568 | MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); | ||
569 | |||
876 | /* setup stuff */ | 570 | /* setup stuff */ |
877 | q->read_buf = videobuf_alloc(q->msize); | 571 | q->read_buf = videobuf_alloc(q); |
878 | if (NULL == q->read_buf) | 572 | if (NULL == q->read_buf) |
879 | return -ENOMEM; | 573 | return -ENOMEM; |
880 | 574 | ||
881 | q->read_buf->memory = V4L2_MEMORY_USERPTR; | 575 | q->read_buf->memory = V4L2_MEMORY_USERPTR; |
882 | q->read_buf->baddr = (unsigned long)data; | 576 | q->read_buf->baddr = (unsigned long)data; |
883 | q->read_buf->bsize = count; | 577 | q->read_buf->bsize = count; |
578 | |||
884 | field = videobuf_next_field(q); | 579 | field = videobuf_next_field(q); |
885 | retval = q->ops->buf_prepare(q,q->read_buf,field); | 580 | retval = q->ops->buf_prepare(q,q->read_buf,field); |
886 | if (0 != retval) | 581 | if (0 != retval) |
@@ -894,7 +589,7 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, | |||
894 | spin_unlock_irqrestore(q->irqlock,flags); | 589 | spin_unlock_irqrestore(q->irqlock,flags); |
895 | retval = videobuf_waiton(q->read_buf,0,0); | 590 | retval = videobuf_waiton(q->read_buf,0,0); |
896 | if (0 == retval) { | 591 | if (0 == retval) { |
897 | videobuf_dma_sync(q,&q->read_buf->dma); | 592 | CALL(q,sync,q,q->read_buf); |
898 | if (STATE_ERROR == q->read_buf->state) | 593 | if (STATE_ERROR == q->read_buf->state) |
899 | retval = -EIO; | 594 | retval = -EIO; |
900 | else | 595 | else |
@@ -915,13 +610,16 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, | |||
915 | { | 610 | { |
916 | enum v4l2_field field; | 611 | enum v4l2_field field; |
917 | unsigned long flags=0; | 612 | unsigned long flags=0; |
918 | unsigned size, nbufs, bytes; | 613 | unsigned size, nbufs; |
919 | int retval; | 614 | int retval; |
920 | 615 | ||
616 | MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); | ||
617 | |||
921 | mutex_lock(&q->lock); | 618 | mutex_lock(&q->lock); |
922 | 619 | ||
923 | nbufs = 1; size = 0; | 620 | nbufs = 1; size = 0; |
924 | q->ops->buf_setup(q,&nbufs,&size); | 621 | q->ops->buf_setup(q,&nbufs,&size); |
622 | |||
925 | if (NULL == q->read_buf && | 623 | if (NULL == q->read_buf && |
926 | count >= size && | 624 | count >= size && |
927 | !nonblocking) { | 625 | !nonblocking) { |
@@ -935,7 +633,8 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, | |||
935 | if (NULL == q->read_buf) { | 633 | if (NULL == q->read_buf) { |
936 | /* need to capture a new frame */ | 634 | /* need to capture a new frame */ |
937 | retval = -ENOMEM; | 635 | retval = -ENOMEM; |
938 | q->read_buf = videobuf_alloc(q->msize); | 636 | q->read_buf = videobuf_alloc(q); |
637 | |||
939 | dprintk(1,"video alloc=0x%p\n", q->read_buf); | 638 | dprintk(1,"video alloc=0x%p\n", q->read_buf); |
940 | if (NULL == q->read_buf) | 639 | if (NULL == q->read_buf) |
941 | goto done; | 640 | goto done; |
@@ -943,6 +642,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, | |||
943 | q->read_buf->bsize = count; /* preferred size */ | 642 | q->read_buf->bsize = count; /* preferred size */ |
944 | field = videobuf_next_field(q); | 643 | field = videobuf_next_field(q); |
945 | retval = q->ops->buf_prepare(q,q->read_buf,field); | 644 | retval = q->ops->buf_prepare(q,q->read_buf,field); |
645 | |||
946 | if (0 != retval) { | 646 | if (0 != retval) { |
947 | kfree (q->read_buf); | 647 | kfree (q->read_buf); |
948 | q->read_buf = NULL; | 648 | q->read_buf = NULL; |
@@ -950,6 +650,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, | |||
950 | } | 650 | } |
951 | if (q->irqlock) | 651 | if (q->irqlock) |
952 | spin_lock_irqsave(q->irqlock,flags); | 652 | spin_lock_irqsave(q->irqlock,flags); |
653 | |||
953 | q->ops->buf_queue(q,q->read_buf); | 654 | q->ops->buf_queue(q,q->read_buf); |
954 | if (q->irqlock) | 655 | if (q->irqlock) |
955 | spin_unlock_irqrestore(q->irqlock,flags); | 656 | spin_unlock_irqrestore(q->irqlock,flags); |
@@ -960,7 +661,8 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, | |||
960 | retval = videobuf_waiton(q->read_buf, nonblocking, 1); | 661 | retval = videobuf_waiton(q->read_buf, nonblocking, 1); |
961 | if (0 != retval) | 662 | if (0 != retval) |
962 | goto done; | 663 | goto done; |
963 | videobuf_dma_sync(q,&q->read_buf->dma); | 664 | |
665 | CALL(q,sync,q,q->read_buf); | ||
964 | 666 | ||
965 | if (STATE_ERROR == q->read_buf->state) { | 667 | if (STATE_ERROR == q->read_buf->state) { |
966 | /* catch I/O errors */ | 668 | /* catch I/O errors */ |
@@ -971,16 +673,12 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, | |||
971 | goto done; | 673 | goto done; |
972 | } | 674 | } |
973 | 675 | ||
974 | /* copy to userspace */ | 676 | /* Copy to userspace */ |
975 | bytes = count; | 677 | retval=CALL(q,copy_to_user,q,data,count,nonblocking); |
976 | if (bytes > q->read_buf->size - q->read_off) | 678 | if (retval<0) |
977 | bytes = q->read_buf->size - q->read_off; | ||
978 | retval = -EFAULT; | ||
979 | if (copy_to_user(data, q->read_buf->dma.vmalloc+q->read_off, bytes)) | ||
980 | goto done; | 679 | goto done; |
981 | 680 | ||
982 | retval = bytes; | 681 | q->read_off += retval; |
983 | q->read_off += bytes; | ||
984 | if (q->read_off == q->read_buf->size) { | 682 | if (q->read_off == q->read_buf->size) { |
985 | /* all data copied, cleanup */ | 683 | /* all data copied, cleanup */ |
986 | q->ops->buf_release(q,q->read_buf); | 684 | q->ops->buf_release(q,q->read_buf); |
@@ -997,7 +695,7 @@ int videobuf_read_start(struct videobuf_queue *q) | |||
997 | { | 695 | { |
998 | enum v4l2_field field; | 696 | enum v4l2_field field; |
999 | unsigned long flags=0; | 697 | unsigned long flags=0; |
1000 | int count = 0, size = 0; | 698 | unsigned int count = 0, size = 0; |
1001 | int err, i; | 699 | int err, i; |
1002 | 700 | ||
1003 | q->ops->buf_setup(q,&count,&size); | 701 | q->ops->buf_setup(q,&count,&size); |
@@ -1008,8 +706,11 @@ int videobuf_read_start(struct videobuf_queue *q) | |||
1008 | size = PAGE_ALIGN(size); | 706 | size = PAGE_ALIGN(size); |
1009 | 707 | ||
1010 | err = videobuf_mmap_setup(q, count, size, V4L2_MEMORY_USERPTR); | 708 | err = videobuf_mmap_setup(q, count, size, V4L2_MEMORY_USERPTR); |
1011 | if (err) | 709 | if (err < 0) |
1012 | return err; | 710 | return err; |
711 | |||
712 | count = err; | ||
713 | |||
1013 | for (i = 0; i < count; i++) { | 714 | for (i = 0; i < count; i++) { |
1014 | field = videobuf_next_field(q); | 715 | field = videobuf_next_field(q); |
1015 | err = q->ops->buf_prepare(q,q->bufs[i],field); | 716 | err = q->ops->buf_prepare(q,q->bufs[i],field); |
@@ -1048,10 +749,11 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, | |||
1048 | char __user *data, size_t count, loff_t *ppos, | 749 | char __user *data, size_t count, loff_t *ppos, |
1049 | int vbihack, int nonblocking) | 750 | int vbihack, int nonblocking) |
1050 | { | 751 | { |
1051 | unsigned int *fc, bytes; | 752 | int rc, retval; |
1052 | int err, retval; | ||
1053 | unsigned long flags=0; | 753 | unsigned long flags=0; |
1054 | 754 | ||
755 | MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); | ||
756 | |||
1055 | dprintk(2,"%s\n",__FUNCTION__); | 757 | dprintk(2,"%s\n",__FUNCTION__); |
1056 | mutex_lock(&q->lock); | 758 | mutex_lock(&q->lock); |
1057 | retval = -EBUSY; | 759 | retval = -EBUSY; |
@@ -1073,39 +775,23 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, | |||
1073 | list_del(&q->read_buf->stream); | 775 | list_del(&q->read_buf->stream); |
1074 | q->read_off = 0; | 776 | q->read_off = 0; |
1075 | } | 777 | } |
1076 | err = videobuf_waiton(q->read_buf, nonblocking, 1); | 778 | rc = videobuf_waiton(q->read_buf, nonblocking, 1); |
1077 | if (err < 0) { | 779 | if (rc < 0) { |
1078 | if (0 == retval) | 780 | if (0 == retval) |
1079 | retval = err; | 781 | retval = rc; |
1080 | break; | 782 | break; |
1081 | } | 783 | } |
1082 | 784 | ||
1083 | if (q->read_buf->state == STATE_DONE) { | 785 | if (q->read_buf->state == STATE_DONE) { |
1084 | if (vbihack) { | 786 | rc = CALL (q,copy_stream, q, data + retval, count, |
1085 | /* dirty, undocumented hack -- pass the frame counter | 787 | retval, vbihack, nonblocking); |
1086 | * within the last four bytes of each vbi data block. | 788 | if (rc < 0) { |
1087 | * We need that one to maintain backward compatibility | 789 | retval = rc; |
1088 | * to all vbi decoding software out there ... */ | ||
1089 | fc = (unsigned int*)q->read_buf->dma.vmalloc; | ||
1090 | fc += (q->read_buf->size>>2) -1; | ||
1091 | *fc = q->read_buf->field_count >> 1; | ||
1092 | dprintk(1,"vbihack: %d\n",*fc); | ||
1093 | } | ||
1094 | |||
1095 | /* copy stuff */ | ||
1096 | bytes = count; | ||
1097 | if (bytes > q->read_buf->size - q->read_off) | ||
1098 | bytes = q->read_buf->size - q->read_off; | ||
1099 | if (copy_to_user(data + retval, | ||
1100 | q->read_buf->dma.vmalloc + q->read_off, | ||
1101 | bytes)) { | ||
1102 | if (0 == retval) | ||
1103 | retval = -EFAULT; | ||
1104 | break; | 790 | break; |
1105 | } | 791 | } |
1106 | count -= bytes; | 792 | retval += rc; |
1107 | retval += bytes; | 793 | count -= rc; |
1108 | q->read_off += bytes; | 794 | q->read_off += rc; |
1109 | } else { | 795 | } else { |
1110 | /* some error */ | 796 | /* some error */ |
1111 | q->read_off = q->read_buf->size; | 797 | q->read_off = q->read_buf->size; |
@@ -1172,81 +858,6 @@ unsigned int videobuf_poll_stream(struct file *file, | |||
1172 | return rc; | 858 | return rc; |
1173 | } | 859 | } |
1174 | 860 | ||
1175 | /* --------------------------------------------------------------------- */ | ||
1176 | |||
1177 | static void | ||
1178 | videobuf_vm_open(struct vm_area_struct *vma) | ||
1179 | { | ||
1180 | struct videobuf_mapping *map = vma->vm_private_data; | ||
1181 | |||
1182 | dprintk(2,"vm_open %p [count=%d,vma=%08lx-%08lx]\n",map, | ||
1183 | map->count,vma->vm_start,vma->vm_end); | ||
1184 | map->count++; | ||
1185 | } | ||
1186 | |||
1187 | static void | ||
1188 | videobuf_vm_close(struct vm_area_struct *vma) | ||
1189 | { | ||
1190 | struct videobuf_mapping *map = vma->vm_private_data; | ||
1191 | struct videobuf_queue *q = map->q; | ||
1192 | int i; | ||
1193 | |||
1194 | dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map, | ||
1195 | map->count,vma->vm_start,vma->vm_end); | ||
1196 | |||
1197 | map->count--; | ||
1198 | if (0 == map->count) { | ||
1199 | dprintk(1,"munmap %p q=%p\n",map,q); | ||
1200 | mutex_lock(&q->lock); | ||
1201 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
1202 | if (NULL == q->bufs[i]) | ||
1203 | continue; | ||
1204 | if (q->bufs[i]) | ||
1205 | ; | ||
1206 | if (q->bufs[i]->map != map) | ||
1207 | continue; | ||
1208 | q->bufs[i]->map = NULL; | ||
1209 | q->bufs[i]->baddr = 0; | ||
1210 | q->ops->buf_release(q,q->bufs[i]); | ||
1211 | } | ||
1212 | mutex_unlock(&q->lock); | ||
1213 | kfree(map); | ||
1214 | } | ||
1215 | return; | ||
1216 | } | ||
1217 | |||
1218 | /* | ||
1219 | * Get a anonymous page for the mapping. Make sure we can DMA to that | ||
1220 | * memory location with 32bit PCI devices (i.e. don't use highmem for | ||
1221 | * now ...). Bounce buffers don't work very well for the data rates | ||
1222 | * video capture has. | ||
1223 | */ | ||
1224 | static struct page* | ||
1225 | videobuf_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr, | ||
1226 | int *type) | ||
1227 | { | ||
1228 | struct page *page; | ||
1229 | |||
1230 | dprintk(3,"nopage: fault @ %08lx [vma %08lx-%08lx]\n", | ||
1231 | vaddr,vma->vm_start,vma->vm_end); | ||
1232 | if (vaddr > vma->vm_end) | ||
1233 | return NOPAGE_SIGBUS; | ||
1234 | page = alloc_page(GFP_USER | __GFP_DMA32); | ||
1235 | if (!page) | ||
1236 | return NOPAGE_OOM; | ||
1237 | clear_user_page(page_address(page), vaddr, page); | ||
1238 | if (type) | ||
1239 | *type = VM_FAULT_MINOR; | ||
1240 | return page; | ||
1241 | } | ||
1242 | |||
1243 | static struct vm_operations_struct videobuf_vm_ops = | ||
1244 | { | ||
1245 | .open = videobuf_vm_open, | ||
1246 | .close = videobuf_vm_close, | ||
1247 | .nopage = videobuf_vm_nopage, | ||
1248 | }; | ||
1249 | |||
1250 | int videobuf_mmap_setup(struct videobuf_queue *q, | 861 | int videobuf_mmap_setup(struct videobuf_queue *q, |
1251 | unsigned int bcount, unsigned int bsize, | 862 | unsigned int bcount, unsigned int bsize, |
1252 | enum v4l2_memory memory) | 863 | enum v4l2_memory memory) |
@@ -1254,12 +865,19 @@ int videobuf_mmap_setup(struct videobuf_queue *q, | |||
1254 | unsigned int i; | 865 | unsigned int i; |
1255 | int err; | 866 | int err; |
1256 | 867 | ||
868 | MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); | ||
869 | |||
1257 | err = videobuf_mmap_free(q); | 870 | err = videobuf_mmap_free(q); |
1258 | if (0 != err) | 871 | if (0 != err) |
1259 | return err; | 872 | return err; |
1260 | 873 | ||
874 | /* Allocate and initialize buffers */ | ||
1261 | for (i = 0; i < bcount; i++) { | 875 | for (i = 0; i < bcount; i++) { |
1262 | q->bufs[i] = videobuf_alloc(q->msize); | 876 | q->bufs[i] = videobuf_alloc(q); |
877 | |||
878 | if (q->bufs[i] == NULL) | ||
879 | break; | ||
880 | |||
1263 | q->bufs[i]->i = i; | 881 | q->bufs[i]->i = i; |
1264 | q->bufs[i]->input = UNSET; | 882 | q->bufs[i]->input = UNSET; |
1265 | q->bufs[i]->memory = memory; | 883 | q->bufs[i]->memory = memory; |
@@ -1274,18 +892,30 @@ int videobuf_mmap_setup(struct videobuf_queue *q, | |||
1274 | break; | 892 | break; |
1275 | } | 893 | } |
1276 | } | 894 | } |
895 | |||
896 | if (!i) | ||
897 | return -ENOMEM; | ||
898 | |||
1277 | dprintk(1,"mmap setup: %d buffers, %d bytes each\n", | 899 | dprintk(1,"mmap setup: %d buffers, %d bytes each\n", |
1278 | bcount,bsize); | 900 | i, bsize); |
1279 | return 0; | 901 | |
902 | return i; | ||
1280 | } | 903 | } |
1281 | 904 | ||
1282 | int videobuf_mmap_free(struct videobuf_queue *q) | 905 | int videobuf_mmap_free(struct videobuf_queue *q) |
1283 | { | 906 | { |
1284 | int i; | 907 | int i; |
908 | int rc; | ||
909 | |||
910 | if (!q) | ||
911 | return 0; | ||
912 | |||
913 | MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); | ||
914 | |||
915 | rc = CALL(q,mmap_free,q); | ||
916 | if (rc<0) | ||
917 | return rc; | ||
1285 | 918 | ||
1286 | for (i = 0; i < VIDEO_MAX_FRAME; i++) | ||
1287 | if (q->bufs[i] && q->bufs[i]->map) | ||
1288 | return -EBUSY; | ||
1289 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | 919 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { |
1290 | if (NULL == q->bufs[i]) | 920 | if (NULL == q->bufs[i]) |
1291 | continue; | 921 | continue; |
@@ -1293,118 +923,69 @@ int videobuf_mmap_free(struct videobuf_queue *q) | |||
1293 | kfree(q->bufs[i]); | 923 | kfree(q->bufs[i]); |
1294 | q->bufs[i] = NULL; | 924 | q->bufs[i] = NULL; |
1295 | } | 925 | } |
1296 | return 0; | 926 | |
927 | return rc; | ||
1297 | } | 928 | } |
1298 | 929 | ||
1299 | int videobuf_mmap_mapper(struct videobuf_queue *q, | 930 | int videobuf_mmap_mapper(struct videobuf_queue *q, |
1300 | struct vm_area_struct *vma) | 931 | struct vm_area_struct *vma) |
1301 | { | 932 | { |
1302 | struct videobuf_mapping *map; | ||
1303 | unsigned int first,last,size,i; | ||
1304 | int retval; | 933 | int retval; |
1305 | 934 | ||
935 | MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); | ||
936 | |||
1306 | mutex_lock(&q->lock); | 937 | mutex_lock(&q->lock); |
1307 | retval = -EINVAL; | 938 | retval=CALL(q,mmap_mapper,q,vma); |
1308 | if (!(vma->vm_flags & VM_WRITE)) { | 939 | mutex_unlock(&q->lock); |
1309 | dprintk(1,"mmap app bug: PROT_WRITE please\n"); | ||
1310 | goto done; | ||
1311 | } | ||
1312 | if (!(vma->vm_flags & VM_SHARED)) { | ||
1313 | dprintk(1,"mmap app bug: MAP_SHARED please\n"); | ||
1314 | goto done; | ||
1315 | } | ||
1316 | 940 | ||
1317 | /* look for first buffer to map */ | 941 | return retval; |
1318 | for (first = 0; first < VIDEO_MAX_FRAME; first++) { | 942 | } |
1319 | if (NULL == q->bufs[first]) | ||
1320 | continue; | ||
1321 | if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) | ||
1322 | continue; | ||
1323 | if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT)) | ||
1324 | break; | ||
1325 | } | ||
1326 | if (VIDEO_MAX_FRAME == first) { | ||
1327 | dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n", | ||
1328 | (vma->vm_pgoff << PAGE_SHIFT)); | ||
1329 | goto done; | ||
1330 | } | ||
1331 | 943 | ||
1332 | /* look for last buffer to map */ | 944 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1333 | for (size = 0, last = first; last < VIDEO_MAX_FRAME; last++) { | 945 | int videobuf_cgmbuf(struct videobuf_queue *q, |
1334 | if (NULL == q->bufs[last]) | 946 | struct video_mbuf *mbuf, int count) |
1335 | continue; | 947 | { |
1336 | if (V4L2_MEMORY_MMAP != q->bufs[last]->memory) | 948 | struct v4l2_requestbuffers req; |
1337 | continue; | 949 | int rc,i; |
1338 | if (q->bufs[last]->map) { | ||
1339 | retval = -EBUSY; | ||
1340 | goto done; | ||
1341 | } | ||
1342 | size += q->bufs[last]->bsize; | ||
1343 | if (size == (vma->vm_end - vma->vm_start)) | ||
1344 | break; | ||
1345 | } | ||
1346 | if (VIDEO_MAX_FRAME == last) { | ||
1347 | dprintk(1,"mmap app bug: size invalid [size=0x%lx]\n", | ||
1348 | (vma->vm_end - vma->vm_start)); | ||
1349 | goto done; | ||
1350 | } | ||
1351 | 950 | ||
1352 | /* create mapping + update buffer list */ | 951 | MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); |
1353 | retval = -ENOMEM; | 952 | |
1354 | map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL); | 953 | memset(&req,0,sizeof(req)); |
1355 | if (NULL == map) | 954 | req.type = q->type; |
1356 | goto done; | 955 | req.count = count; |
1357 | for (size = 0, i = first; i <= last; size += q->bufs[i++]->bsize) { | 956 | req.memory = V4L2_MEMORY_MMAP; |
1358 | q->bufs[i]->map = map; | 957 | rc = videobuf_reqbufs(q,&req); |
1359 | q->bufs[i]->baddr = vma->vm_start + size; | 958 | if (rc < 0) |
959 | return rc; | ||
960 | |||
961 | mbuf->frames = req.count; | ||
962 | mbuf->size = 0; | ||
963 | for (i = 0; i < mbuf->frames; i++) { | ||
964 | mbuf->offsets[i] = q->bufs[i]->boff; | ||
965 | mbuf->size += q->bufs[i]->bsize; | ||
1360 | } | 966 | } |
1361 | map->count = 1; | ||
1362 | map->start = vma->vm_start; | ||
1363 | map->end = vma->vm_end; | ||
1364 | map->q = q; | ||
1365 | vma->vm_ops = &videobuf_vm_ops; | ||
1366 | vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; | ||
1367 | vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ | ||
1368 | vma->vm_private_data = map; | ||
1369 | dprintk(1,"mmap %p: q=%p %08lx-%08lx pgoff %08lx bufs %d-%d\n", | ||
1370 | map,q,vma->vm_start,vma->vm_end,vma->vm_pgoff,first,last); | ||
1371 | retval = 0; | ||
1372 | 967 | ||
1373 | done: | 968 | return 0; |
1374 | mutex_unlock(&q->lock); | ||
1375 | return retval; | ||
1376 | } | 969 | } |
970 | #endif | ||
1377 | 971 | ||
1378 | /* --------------------------------------------------------------------- */ | 972 | /* --------------------------------------------------------------------- */ |
1379 | 973 | ||
1380 | EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg); | ||
1381 | |||
1382 | EXPORT_SYMBOL_GPL(videobuf_dma_init); | ||
1383 | EXPORT_SYMBOL_GPL(videobuf_dma_init_user); | ||
1384 | EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); | ||
1385 | EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); | ||
1386 | EXPORT_SYMBOL_GPL(videobuf_dma_map); | ||
1387 | EXPORT_SYMBOL_GPL(videobuf_dma_sync); | ||
1388 | EXPORT_SYMBOL_GPL(videobuf_dma_unmap); | ||
1389 | EXPORT_SYMBOL_GPL(videobuf_dma_free); | ||
1390 | |||
1391 | EXPORT_SYMBOL_GPL(videobuf_pci_dma_map); | ||
1392 | EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap); | ||
1393 | |||
1394 | EXPORT_SYMBOL_GPL(videobuf_alloc); | ||
1395 | EXPORT_SYMBOL_GPL(videobuf_waiton); | 974 | EXPORT_SYMBOL_GPL(videobuf_waiton); |
1396 | EXPORT_SYMBOL_GPL(videobuf_iolock); | 975 | EXPORT_SYMBOL_GPL(videobuf_iolock); |
1397 | 976 | ||
1398 | EXPORT_SYMBOL_GPL(videobuf_queue_init); | 977 | EXPORT_SYMBOL_GPL(videobuf_alloc); |
978 | |||
979 | EXPORT_SYMBOL_GPL(videobuf_queue_core_init); | ||
1399 | EXPORT_SYMBOL_GPL(videobuf_queue_cancel); | 980 | EXPORT_SYMBOL_GPL(videobuf_queue_cancel); |
1400 | EXPORT_SYMBOL_GPL(videobuf_queue_is_busy); | 981 | EXPORT_SYMBOL_GPL(videobuf_queue_is_busy); |
1401 | 982 | ||
1402 | EXPORT_SYMBOL_GPL(videobuf_next_field); | 983 | EXPORT_SYMBOL_GPL(videobuf_next_field); |
1403 | EXPORT_SYMBOL_GPL(videobuf_status); | ||
1404 | EXPORT_SYMBOL_GPL(videobuf_reqbufs); | 984 | EXPORT_SYMBOL_GPL(videobuf_reqbufs); |
1405 | EXPORT_SYMBOL_GPL(videobuf_querybuf); | 985 | EXPORT_SYMBOL_GPL(videobuf_querybuf); |
1406 | EXPORT_SYMBOL_GPL(videobuf_qbuf); | 986 | EXPORT_SYMBOL_GPL(videobuf_qbuf); |
1407 | EXPORT_SYMBOL_GPL(videobuf_dqbuf); | 987 | EXPORT_SYMBOL_GPL(videobuf_dqbuf); |
988 | EXPORT_SYMBOL_GPL(videobuf_cgmbuf); | ||
1408 | EXPORT_SYMBOL_GPL(videobuf_streamon); | 989 | EXPORT_SYMBOL_GPL(videobuf_streamon); |
1409 | EXPORT_SYMBOL_GPL(videobuf_streamoff); | 990 | EXPORT_SYMBOL_GPL(videobuf_streamoff); |
1410 | 991 | ||
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c new file mode 100644 index 000000000000..8bb7fdd306d6 --- /dev/null +++ b/drivers/media/video/videobuf-dma-sg.c | |||
@@ -0,0 +1,726 @@ | |||
1 | /* | ||
2 | * helper functions for PCI DMA video4linux capture buffers | ||
3 | * | ||
4 | * The functions expect the hardware being able to scatter gatter | ||
5 | * (i.e. the buffers are not linear in physical memory, but fragmented | ||
6 | * into PAGE_SIZE chunks). They also assume the driver does not need | ||
7 | * to touch the video data. | ||
8 | * | ||
9 | * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org> | ||
10 | * | ||
11 | * Highly based on video-buf written originally by: | ||
12 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> | ||
13 | * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org> | ||
14 | * (c) 2006 Ted Walther and John Sokol | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/moduleparam.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | |||
27 | #include <linux/pci.h> | ||
28 | #include <linux/vmalloc.h> | ||
29 | #include <linux/pagemap.h> | ||
30 | #include <asm/page.h> | ||
31 | #include <asm/pgtable.h> | ||
32 | |||
33 | #include <media/videobuf-dma-sg.h> | ||
34 | |||
35 | #define MAGIC_DMABUF 0x19721112 | ||
36 | #define MAGIC_SG_MEM 0x17890714 | ||
37 | |||
38 | #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ | ||
39 | { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } | ||
40 | |||
41 | static int debug = 0; | ||
42 | module_param(debug, int, 0644); | ||
43 | |||
44 | MODULE_DESCRIPTION("helper module to manage video4linux pci dma sg buffers"); | ||
45 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | ||
46 | MODULE_LICENSE("GPL"); | ||
47 | |||
48 | #define dprintk(level, fmt, arg...) if (debug >= level) \ | ||
49 | printk(KERN_DEBUG "vbuf-sg: " fmt , ## arg) | ||
50 | |||
51 | /* --------------------------------------------------------------------- */ | ||
52 | |||
53 | struct scatterlist* | ||
54 | videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) | ||
55 | { | ||
56 | struct scatterlist *sglist; | ||
57 | struct page *pg; | ||
58 | int i; | ||
59 | |||
60 | sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL); | ||
61 | if (NULL == sglist) | ||
62 | return NULL; | ||
63 | for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) { | ||
64 | pg = vmalloc_to_page(virt); | ||
65 | if (NULL == pg) | ||
66 | goto err; | ||
67 | BUG_ON(PageHighMem(pg)); | ||
68 | sglist[i].page = pg; | ||
69 | sglist[i].length = PAGE_SIZE; | ||
70 | } | ||
71 | return sglist; | ||
72 | |||
73 | err: | ||
74 | kfree(sglist); | ||
75 | return NULL; | ||
76 | } | ||
77 | |||
78 | struct scatterlist* | ||
79 | videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) | ||
80 | { | ||
81 | struct scatterlist *sglist; | ||
82 | int i = 0; | ||
83 | |||
84 | if (NULL == pages[0]) | ||
85 | return NULL; | ||
86 | sglist = kcalloc(nr_pages, sizeof(*sglist), GFP_KERNEL); | ||
87 | if (NULL == sglist) | ||
88 | return NULL; | ||
89 | |||
90 | if (NULL == pages[0]) | ||
91 | goto nopage; | ||
92 | if (PageHighMem(pages[0])) | ||
93 | /* DMA to highmem pages might not work */ | ||
94 | goto highmem; | ||
95 | sglist[0].page = pages[0]; | ||
96 | sglist[0].offset = offset; | ||
97 | sglist[0].length = PAGE_SIZE - offset; | ||
98 | for (i = 1; i < nr_pages; i++) { | ||
99 | if (NULL == pages[i]) | ||
100 | goto nopage; | ||
101 | if (PageHighMem(pages[i])) | ||
102 | goto highmem; | ||
103 | sglist[i].page = pages[i]; | ||
104 | sglist[i].length = PAGE_SIZE; | ||
105 | } | ||
106 | return sglist; | ||
107 | |||
108 | nopage: | ||
109 | dprintk(2,"sgl: oops - no page\n"); | ||
110 | kfree(sglist); | ||
111 | return NULL; | ||
112 | |||
113 | highmem: | ||
114 | dprintk(2,"sgl: oops - highmem page\n"); | ||
115 | kfree(sglist); | ||
116 | return NULL; | ||
117 | } | ||
118 | |||
119 | /* --------------------------------------------------------------------- */ | ||
120 | |||
121 | struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf) | ||
122 | { | ||
123 | struct videbuf_pci_sg_memory *mem=buf->priv; | ||
124 | BUG_ON (!mem); | ||
125 | |||
126 | MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); | ||
127 | |||
128 | return &mem->dma; | ||
129 | } | ||
130 | |||
131 | void videobuf_dma_init(struct videobuf_dmabuf *dma) | ||
132 | { | ||
133 | memset(dma,0,sizeof(*dma)); | ||
134 | dma->magic = MAGIC_DMABUF; | ||
135 | } | ||
136 | |||
137 | static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, | ||
138 | int direction, unsigned long data, unsigned long size) | ||
139 | { | ||
140 | unsigned long first,last; | ||
141 | int err, rw = 0; | ||
142 | |||
143 | dma->direction = direction; | ||
144 | switch (dma->direction) { | ||
145 | case PCI_DMA_FROMDEVICE: rw = READ; break; | ||
146 | case PCI_DMA_TODEVICE: rw = WRITE; break; | ||
147 | default: BUG(); | ||
148 | } | ||
149 | |||
150 | first = (data & PAGE_MASK) >> PAGE_SHIFT; | ||
151 | last = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT; | ||
152 | dma->offset = data & ~PAGE_MASK; | ||
153 | dma->nr_pages = last-first+1; | ||
154 | dma->pages = kmalloc(dma->nr_pages * sizeof(struct page*), | ||
155 | GFP_KERNEL); | ||
156 | if (NULL == dma->pages) | ||
157 | return -ENOMEM; | ||
158 | dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n", | ||
159 | data,size,dma->nr_pages); | ||
160 | |||
161 | dma->varea = (void *) data; | ||
162 | |||
163 | |||
164 | err = get_user_pages(current,current->mm, | ||
165 | data & PAGE_MASK, dma->nr_pages, | ||
166 | rw == READ, 1, /* force */ | ||
167 | dma->pages, NULL); | ||
168 | |||
169 | if (err != dma->nr_pages) { | ||
170 | dma->nr_pages = (err >= 0) ? err : 0; | ||
171 | dprintk(1,"get_user_pages: err=%d [%d]\n",err,dma->nr_pages); | ||
172 | return err < 0 ? err : -EINVAL; | ||
173 | } | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, | ||
178 | unsigned long data, unsigned long size) | ||
179 | { | ||
180 | int ret; | ||
181 | down_read(¤t->mm->mmap_sem); | ||
182 | ret = videobuf_dma_init_user_locked(dma, direction, data, size); | ||
183 | up_read(¤t->mm->mmap_sem); | ||
184 | |||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, | ||
189 | int nr_pages) | ||
190 | { | ||
191 | dprintk(1,"init kernel [%d pages]\n",nr_pages); | ||
192 | dma->direction = direction; | ||
193 | dma->vmalloc = vmalloc_32(nr_pages << PAGE_SHIFT); | ||
194 | if (NULL == dma->vmalloc) { | ||
195 | dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages); | ||
196 | return -ENOMEM; | ||
197 | } | ||
198 | dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n", | ||
199 | (unsigned long)dma->vmalloc, | ||
200 | nr_pages << PAGE_SHIFT); | ||
201 | memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT); | ||
202 | dma->nr_pages = nr_pages; | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, | ||
207 | dma_addr_t addr, int nr_pages) | ||
208 | { | ||
209 | dprintk(1,"init overlay [%d pages @ bus 0x%lx]\n", | ||
210 | nr_pages,(unsigned long)addr); | ||
211 | dma->direction = direction; | ||
212 | if (0 == addr) | ||
213 | return -EINVAL; | ||
214 | |||
215 | dma->bus_addr = addr; | ||
216 | dma->nr_pages = nr_pages; | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) | ||
221 | { | ||
222 | void *dev=q->dev; | ||
223 | |||
224 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); | ||
225 | BUG_ON(0 == dma->nr_pages); | ||
226 | |||
227 | if (dma->pages) { | ||
228 | dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages, | ||
229 | dma->offset); | ||
230 | } | ||
231 | if (dma->vmalloc) { | ||
232 | dma->sglist = videobuf_vmalloc_to_sg | ||
233 | (dma->vmalloc,dma->nr_pages); | ||
234 | } | ||
235 | if (dma->bus_addr) { | ||
236 | dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL); | ||
237 | if (NULL != dma->sglist) { | ||
238 | dma->sglen = 1; | ||
239 | sg_dma_address(&dma->sglist[0]) = dma->bus_addr & PAGE_MASK; | ||
240 | dma->sglist[0].offset = dma->bus_addr & ~PAGE_MASK; | ||
241 | sg_dma_len(&dma->sglist[0]) = dma->nr_pages * PAGE_SIZE; | ||
242 | } | ||
243 | } | ||
244 | if (NULL == dma->sglist) { | ||
245 | dprintk(1,"scatterlist is NULL\n"); | ||
246 | return -ENOMEM; | ||
247 | } | ||
248 | if (!dma->bus_addr) { | ||
249 | dma->sglen = pci_map_sg(dev,dma->sglist, | ||
250 | dma->nr_pages, dma->direction); | ||
251 | if (0 == dma->sglen) { | ||
252 | printk(KERN_WARNING | ||
253 | "%s: videobuf_map_sg failed\n",__FUNCTION__); | ||
254 | kfree(dma->sglist); | ||
255 | dma->sglist = NULL; | ||
256 | dma->sglen = 0; | ||
257 | return -EIO; | ||
258 | } | ||
259 | } | ||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | int videobuf_dma_sync(struct videobuf_queue *q,struct videobuf_dmabuf *dma) | ||
264 | { | ||
265 | void *dev=q->dev; | ||
266 | |||
267 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); | ||
268 | BUG_ON(!dma->sglen); | ||
269 | |||
270 | pci_dma_sync_sg_for_cpu (dev,dma->sglist,dma->nr_pages,dma->direction); | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) | ||
275 | { | ||
276 | void *dev=q->dev; | ||
277 | |||
278 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); | ||
279 | if (!dma->sglen) | ||
280 | return 0; | ||
281 | |||
282 | pci_unmap_sg (dev,dma->sglist,dma->nr_pages,dma->direction); | ||
283 | |||
284 | kfree(dma->sglist); | ||
285 | dma->sglist = NULL; | ||
286 | dma->sglen = 0; | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | int videobuf_dma_free(struct videobuf_dmabuf *dma) | ||
291 | { | ||
292 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); | ||
293 | BUG_ON(dma->sglen); | ||
294 | |||
295 | if (dma->pages) { | ||
296 | int i; | ||
297 | for (i=0; i < dma->nr_pages; i++) | ||
298 | page_cache_release(dma->pages[i]); | ||
299 | kfree(dma->pages); | ||
300 | dma->pages = NULL; | ||
301 | } | ||
302 | |||
303 | vfree(dma->vmalloc); | ||
304 | dma->vmalloc = NULL; | ||
305 | dma->varea = NULL; | ||
306 | |||
307 | if (dma->bus_addr) { | ||
308 | dma->bus_addr = 0; | ||
309 | } | ||
310 | dma->direction = PCI_DMA_NONE; | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | /* --------------------------------------------------------------------- */ | ||
315 | |||
316 | int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma) | ||
317 | { | ||
318 | struct videobuf_queue q; | ||
319 | |||
320 | q.dev=pci; | ||
321 | |||
322 | return (videobuf_dma_map(&q,dma)); | ||
323 | } | ||
324 | |||
325 | int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma) | ||
326 | { | ||
327 | struct videobuf_queue q; | ||
328 | |||
329 | q.dev=pci; | ||
330 | |||
331 | return (videobuf_dma_unmap(&q,dma)); | ||
332 | } | ||
333 | |||
334 | /* --------------------------------------------------------------------- */ | ||
335 | |||
336 | static void | ||
337 | videobuf_vm_open(struct vm_area_struct *vma) | ||
338 | { | ||
339 | struct videobuf_mapping *map = vma->vm_private_data; | ||
340 | |||
341 | dprintk(2,"vm_open %p [count=%d,vma=%08lx-%08lx]\n",map, | ||
342 | map->count,vma->vm_start,vma->vm_end); | ||
343 | map->count++; | ||
344 | } | ||
345 | |||
346 | static void | ||
347 | videobuf_vm_close(struct vm_area_struct *vma) | ||
348 | { | ||
349 | struct videobuf_mapping *map = vma->vm_private_data; | ||
350 | struct videobuf_queue *q = map->q; | ||
351 | struct videbuf_pci_sg_memory *mem; | ||
352 | int i; | ||
353 | |||
354 | dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map, | ||
355 | map->count,vma->vm_start,vma->vm_end); | ||
356 | |||
357 | map->count--; | ||
358 | if (0 == map->count) { | ||
359 | dprintk(1,"munmap %p q=%p\n",map,q); | ||
360 | mutex_lock(&q->lock); | ||
361 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
362 | if (NULL == q->bufs[i]) | ||
363 | continue; | ||
364 | mem=q->bufs[i]->priv; | ||
365 | |||
366 | if (!mem) | ||
367 | continue; | ||
368 | |||
369 | MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); | ||
370 | |||
371 | if (q->bufs[i]->map != map) | ||
372 | continue; | ||
373 | q->bufs[i]->map = NULL; | ||
374 | q->bufs[i]->baddr = 0; | ||
375 | q->ops->buf_release(q,q->bufs[i]); | ||
376 | } | ||
377 | mutex_unlock(&q->lock); | ||
378 | kfree(map); | ||
379 | } | ||
380 | return; | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | * Get a anonymous page for the mapping. Make sure we can DMA to that | ||
385 | * memory location with 32bit PCI devices (i.e. don't use highmem for | ||
386 | * now ...). Bounce buffers don't work very well for the data rates | ||
387 | * video capture has. | ||
388 | */ | ||
389 | static struct page* | ||
390 | videobuf_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr, | ||
391 | int *type) | ||
392 | { | ||
393 | struct page *page; | ||
394 | |||
395 | dprintk(3,"nopage: fault @ %08lx [vma %08lx-%08lx]\n", | ||
396 | vaddr,vma->vm_start,vma->vm_end); | ||
397 | if (vaddr > vma->vm_end) | ||
398 | return NOPAGE_SIGBUS; | ||
399 | page = alloc_page(GFP_USER | __GFP_DMA32); | ||
400 | if (!page) | ||
401 | return NOPAGE_OOM; | ||
402 | clear_user_page(page_address(page), vaddr, page); | ||
403 | if (type) | ||
404 | *type = VM_FAULT_MINOR; | ||
405 | return page; | ||
406 | } | ||
407 | |||
408 | static struct vm_operations_struct videobuf_vm_ops = | ||
409 | { | ||
410 | .open = videobuf_vm_open, | ||
411 | .close = videobuf_vm_close, | ||
412 | .nopage = videobuf_vm_nopage, | ||
413 | }; | ||
414 | |||
415 | /* --------------------------------------------------------------------- | ||
416 | * PCI handlers for the generic methods | ||
417 | */ | ||
418 | |||
419 | /* Allocated area consists on 3 parts: | ||
420 | struct video_buffer | ||
421 | struct <driver>_buffer (cx88_buffer, saa7134_buf, ...) | ||
422 | struct videobuf_pci_sg_memory | ||
423 | */ | ||
424 | |||
425 | static void *__videobuf_alloc(size_t size) | ||
426 | { | ||
427 | struct videbuf_pci_sg_memory *mem; | ||
428 | struct videobuf_buffer *vb; | ||
429 | |||
430 | vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); | ||
431 | |||
432 | mem = vb->priv = ((char *)vb)+size; | ||
433 | mem->magic=MAGIC_SG_MEM; | ||
434 | |||
435 | videobuf_dma_init(&mem->dma); | ||
436 | |||
437 | dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n", | ||
438 | __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb), | ||
439 | mem,(long)sizeof(*mem)); | ||
440 | |||
441 | return vb; | ||
442 | } | ||
443 | |||
444 | static int __videobuf_iolock (struct videobuf_queue* q, | ||
445 | struct videobuf_buffer *vb, | ||
446 | struct v4l2_framebuffer *fbuf) | ||
447 | { | ||
448 | int err,pages; | ||
449 | dma_addr_t bus; | ||
450 | struct videbuf_pci_sg_memory *mem=vb->priv; | ||
451 | BUG_ON(!mem); | ||
452 | |||
453 | MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); | ||
454 | |||
455 | switch (vb->memory) { | ||
456 | case V4L2_MEMORY_MMAP: | ||
457 | case V4L2_MEMORY_USERPTR: | ||
458 | if (0 == vb->baddr) { | ||
459 | /* no userspace addr -- kernel bounce buffer */ | ||
460 | pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; | ||
461 | err = videobuf_dma_init_kernel( &mem->dma, | ||
462 | PCI_DMA_FROMDEVICE, | ||
463 | pages ); | ||
464 | if (0 != err) | ||
465 | return err; | ||
466 | } else if (vb->memory == V4L2_MEMORY_USERPTR) { | ||
467 | /* dma directly to userspace */ | ||
468 | err = videobuf_dma_init_user( &mem->dma, | ||
469 | PCI_DMA_FROMDEVICE, | ||
470 | vb->baddr,vb->bsize ); | ||
471 | if (0 != err) | ||
472 | return err; | ||
473 | } else { | ||
474 | /* NOTE: HACK: videobuf_iolock on V4L2_MEMORY_MMAP | ||
475 | buffers can only be called from videobuf_qbuf | ||
476 | we take current->mm->mmap_sem there, to prevent | ||
477 | locking inversion, so don't take it here */ | ||
478 | |||
479 | err = videobuf_dma_init_user_locked(&mem->dma, | ||
480 | PCI_DMA_FROMDEVICE, | ||
481 | vb->baddr, vb->bsize); | ||
482 | if (0 != err) | ||
483 | return err; | ||
484 | } | ||
485 | break; | ||
486 | case V4L2_MEMORY_OVERLAY: | ||
487 | if (NULL == fbuf) | ||
488 | return -EINVAL; | ||
489 | /* FIXME: need sanity checks for vb->boff */ | ||
490 | /* | ||
491 | * Using a double cast to avoid compiler warnings when | ||
492 | * building for PAE. Compiler doesn't like direct casting | ||
493 | * of a 32 bit ptr to 64 bit integer. | ||
494 | */ | ||
495 | bus = (dma_addr_t)(unsigned long)fbuf->base + vb->boff; | ||
496 | pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; | ||
497 | err = videobuf_dma_init_overlay(&mem->dma,PCI_DMA_FROMDEVICE, | ||
498 | bus, pages); | ||
499 | if (0 != err) | ||
500 | return err; | ||
501 | break; | ||
502 | default: | ||
503 | BUG(); | ||
504 | } | ||
505 | err = videobuf_dma_map(q,&mem->dma); | ||
506 | if (0 != err) | ||
507 | return err; | ||
508 | |||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | static int __videobuf_sync(struct videobuf_queue *q, | ||
513 | struct videobuf_buffer *buf) | ||
514 | { | ||
515 | struct videbuf_pci_sg_memory *mem=buf->priv; | ||
516 | BUG_ON (!mem); | ||
517 | MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); | ||
518 | |||
519 | return videobuf_dma_sync(q,&mem->dma); | ||
520 | } | ||
521 | |||
522 | static int __videobuf_mmap_free(struct videobuf_queue *q) | ||
523 | { | ||
524 | int i; | ||
525 | |||
526 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
527 | if (q->bufs[i]) { | ||
528 | if (q->bufs[i]->map) | ||
529 | return -EBUSY; | ||
530 | } | ||
531 | } | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | static int __videobuf_mmap_mapper(struct videobuf_queue *q, | ||
537 | struct vm_area_struct *vma) | ||
538 | { | ||
539 | struct videbuf_pci_sg_memory *mem; | ||
540 | struct videobuf_mapping *map; | ||
541 | unsigned int first,last,size,i; | ||
542 | int retval; | ||
543 | |||
544 | retval = -EINVAL; | ||
545 | if (!(vma->vm_flags & VM_WRITE)) { | ||
546 | dprintk(1,"mmap app bug: PROT_WRITE please\n"); | ||
547 | goto done; | ||
548 | } | ||
549 | if (!(vma->vm_flags & VM_SHARED)) { | ||
550 | dprintk(1,"mmap app bug: MAP_SHARED please\n"); | ||
551 | goto done; | ||
552 | } | ||
553 | |||
554 | /* look for first buffer to map */ | ||
555 | for (first = 0; first < VIDEO_MAX_FRAME; first++) { | ||
556 | if (NULL == q->bufs[first]) | ||
557 | continue; | ||
558 | mem=q->bufs[first]->priv; | ||
559 | BUG_ON (!mem); | ||
560 | MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); | ||
561 | |||
562 | if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) | ||
563 | continue; | ||
564 | if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT)) | ||
565 | break; | ||
566 | } | ||
567 | if (VIDEO_MAX_FRAME == first) { | ||
568 | dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n", | ||
569 | (vma->vm_pgoff << PAGE_SHIFT)); | ||
570 | goto done; | ||
571 | } | ||
572 | |||
573 | /* look for last buffer to map */ | ||
574 | for (size = 0, last = first; last < VIDEO_MAX_FRAME; last++) { | ||
575 | if (NULL == q->bufs[last]) | ||
576 | continue; | ||
577 | if (V4L2_MEMORY_MMAP != q->bufs[last]->memory) | ||
578 | continue; | ||
579 | if (q->bufs[last]->map) { | ||
580 | retval = -EBUSY; | ||
581 | goto done; | ||
582 | } | ||
583 | size += q->bufs[last]->bsize; | ||
584 | if (size == (vma->vm_end - vma->vm_start)) | ||
585 | break; | ||
586 | } | ||
587 | if (VIDEO_MAX_FRAME == last) { | ||
588 | dprintk(1,"mmap app bug: size invalid [size=0x%lx]\n", | ||
589 | (vma->vm_end - vma->vm_start)); | ||
590 | goto done; | ||
591 | } | ||
592 | |||
593 | /* create mapping + update buffer list */ | ||
594 | retval = -ENOMEM; | ||
595 | map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL); | ||
596 | if (NULL == map) | ||
597 | goto done; | ||
598 | for (size = 0, i = first; i <= last; size += q->bufs[i++]->bsize) { | ||
599 | q->bufs[i]->map = map; | ||
600 | q->bufs[i]->baddr = vma->vm_start + size; | ||
601 | } | ||
602 | map->count = 1; | ||
603 | map->start = vma->vm_start; | ||
604 | map->end = vma->vm_end; | ||
605 | map->q = q; | ||
606 | vma->vm_ops = &videobuf_vm_ops; | ||
607 | vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; | ||
608 | vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ | ||
609 | vma->vm_private_data = map; | ||
610 | dprintk(1,"mmap %p: q=%p %08lx-%08lx pgoff %08lx bufs %d-%d\n", | ||
611 | map,q,vma->vm_start,vma->vm_end,vma->vm_pgoff,first,last); | ||
612 | retval = 0; | ||
613 | |||
614 | done: | ||
615 | return retval; | ||
616 | } | ||
617 | |||
618 | static int __videobuf_copy_to_user ( struct videobuf_queue *q, | ||
619 | char __user *data, size_t count, | ||
620 | int nonblocking ) | ||
621 | { | ||
622 | struct videbuf_pci_sg_memory *mem=q->read_buf->priv; | ||
623 | BUG_ON (!mem); | ||
624 | MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); | ||
625 | |||
626 | /* copy to userspace */ | ||
627 | if (count > q->read_buf->size - q->read_off) | ||
628 | count = q->read_buf->size - q->read_off; | ||
629 | |||
630 | if (copy_to_user(data, mem->dma.vmalloc+q->read_off, count)) | ||
631 | return -EFAULT; | ||
632 | |||
633 | return count; | ||
634 | } | ||
635 | |||
636 | static int __videobuf_copy_stream ( struct videobuf_queue *q, | ||
637 | char __user *data, size_t count, size_t pos, | ||
638 | int vbihack, int nonblocking ) | ||
639 | { | ||
640 | unsigned int *fc; | ||
641 | struct videbuf_pci_sg_memory *mem=q->read_buf->priv; | ||
642 | BUG_ON (!mem); | ||
643 | MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); | ||
644 | |||
645 | if (vbihack) { | ||
646 | /* dirty, undocumented hack -- pass the frame counter | ||
647 | * within the last four bytes of each vbi data block. | ||
648 | * We need that one to maintain backward compatibility | ||
649 | * to all vbi decoding software out there ... */ | ||
650 | fc = (unsigned int*)mem->dma.vmalloc; | ||
651 | fc += (q->read_buf->size>>2) -1; | ||
652 | *fc = q->read_buf->field_count >> 1; | ||
653 | dprintk(1,"vbihack: %d\n",*fc); | ||
654 | } | ||
655 | |||
656 | /* copy stuff using the common method */ | ||
657 | count = __videobuf_copy_to_user (q,data,count,nonblocking); | ||
658 | |||
659 | if ( (count==-EFAULT) && (0 == pos) ) | ||
660 | return -EFAULT; | ||
661 | |||
662 | return count; | ||
663 | } | ||
664 | |||
665 | static struct videobuf_qtype_ops pci_ops = { | ||
666 | .magic = MAGIC_QTYPE_OPS, | ||
667 | |||
668 | .alloc = __videobuf_alloc, | ||
669 | .iolock = __videobuf_iolock, | ||
670 | .sync = __videobuf_sync, | ||
671 | .mmap_free = __videobuf_mmap_free, | ||
672 | .mmap_mapper = __videobuf_mmap_mapper, | ||
673 | .copy_to_user = __videobuf_copy_to_user, | ||
674 | .copy_stream = __videobuf_copy_stream, | ||
675 | }; | ||
676 | |||
677 | void *videobuf_pci_alloc (size_t size) | ||
678 | { | ||
679 | struct videobuf_queue q; | ||
680 | |||
681 | /* Required to make generic handler to call __videobuf_alloc */ | ||
682 | q.int_ops=&pci_ops; | ||
683 | |||
684 | q.msize=size; | ||
685 | |||
686 | return videobuf_alloc (&q); | ||
687 | } | ||
688 | |||
689 | void videobuf_queue_pci_init(struct videobuf_queue* q, | ||
690 | struct videobuf_queue_ops *ops, | ||
691 | void *dev, | ||
692 | spinlock_t *irqlock, | ||
693 | enum v4l2_buf_type type, | ||
694 | enum v4l2_field field, | ||
695 | unsigned int msize, | ||
696 | void *priv) | ||
697 | { | ||
698 | videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, | ||
699 | priv, &pci_ops); | ||
700 | } | ||
701 | |||
702 | /* --------------------------------------------------------------------- */ | ||
703 | |||
704 | EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg); | ||
705 | |||
706 | EXPORT_SYMBOL_GPL(videobuf_to_dma); | ||
707 | EXPORT_SYMBOL_GPL(videobuf_dma_init); | ||
708 | EXPORT_SYMBOL_GPL(videobuf_dma_init_user); | ||
709 | EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); | ||
710 | EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); | ||
711 | EXPORT_SYMBOL_GPL(videobuf_dma_map); | ||
712 | EXPORT_SYMBOL_GPL(videobuf_dma_sync); | ||
713 | EXPORT_SYMBOL_GPL(videobuf_dma_unmap); | ||
714 | EXPORT_SYMBOL_GPL(videobuf_dma_free); | ||
715 | |||
716 | EXPORT_SYMBOL_GPL(videobuf_pci_dma_map); | ||
717 | EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap); | ||
718 | EXPORT_SYMBOL_GPL(videobuf_pci_alloc); | ||
719 | |||
720 | EXPORT_SYMBOL_GPL(videobuf_queue_pci_init); | ||
721 | |||
722 | /* | ||
723 | * Local variables: | ||
724 | * c-basic-offset: 8 | ||
725 | * End: | ||
726 | */ | ||
diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/videobuf-dvb.c index e617925ba31e..880317e04a02 100644 --- a/drivers/media/video/video-buf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c | |||
@@ -22,8 +22,8 @@ | |||
22 | #include <linux/file.h> | 22 | #include <linux/file.h> |
23 | #include <linux/freezer.h> | 23 | #include <linux/freezer.h> |
24 | 24 | ||
25 | #include <media/video-buf.h> | 25 | #include <media/videobuf-dma-sg.h> |
26 | #include <media/video-buf-dvb.h> | 26 | #include <media/videobuf-dvb.h> |
27 | 27 | ||
28 | /* ------------------------------------------------------------------ */ | 28 | /* ------------------------------------------------------------------ */ |
29 | 29 | ||
@@ -45,6 +45,7 @@ static int videobuf_dvb_thread(void *data) | |||
45 | struct videobuf_buffer *buf; | 45 | struct videobuf_buffer *buf; |
46 | unsigned long flags; | 46 | unsigned long flags; |
47 | int err; | 47 | int err; |
48 | struct videobuf_dmabuf *dma; | ||
48 | 49 | ||
49 | dprintk("dvb thread started\n"); | 50 | dprintk("dvb thread started\n"); |
50 | set_freezable(); | 51 | set_freezable(); |
@@ -56,7 +57,6 @@ static int videobuf_dvb_thread(void *data) | |||
56 | struct videobuf_buffer, stream); | 57 | struct videobuf_buffer, stream); |
57 | list_del(&buf->stream); | 58 | list_del(&buf->stream); |
58 | err = videobuf_waiton(buf,0,1); | 59 | err = videobuf_waiton(buf,0,1); |
59 | BUG_ON(0 != err); | ||
60 | 60 | ||
61 | /* no more feeds left or stop_feed() asked us to quit */ | 61 | /* no more feeds left or stop_feed() asked us to quit */ |
62 | if (0 == dvb->nfeeds) | 62 | if (0 == dvb->nfeeds) |
@@ -66,8 +66,9 @@ static int videobuf_dvb_thread(void *data) | |||
66 | try_to_freeze(); | 66 | try_to_freeze(); |
67 | 67 | ||
68 | /* feed buffer data to demux */ | 68 | /* feed buffer data to demux */ |
69 | dma=videobuf_to_dma(buf); | ||
69 | if (buf->state == STATE_DONE) | 70 | if (buf->state == STATE_DONE) |
70 | dvb_dmx_swfilter(&dvb->demux, buf->dma.vmalloc, | 71 | dvb_dmx_swfilter(&dvb->demux, dma->vmalloc, |
71 | buf->size); | 72 | buf->size); |
72 | 73 | ||
73 | /* requeue buffer */ | 74 | /* requeue buffer */ |
diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c new file mode 100644 index 000000000000..2e3689a12a28 --- /dev/null +++ b/drivers/media/video/videobuf-vmalloc.c | |||
@@ -0,0 +1,370 @@ | |||
1 | /* | ||
2 | * helper functions for vmalloc video4linux capture buffers | ||
3 | * | ||
4 | * The functions expect the hardware being able to scatter gatter | ||
5 | * (i.e. the buffers are not linear in physical memory, but fragmented | ||
6 | * into PAGE_SIZE chunks). They also assume the driver does not need | ||
7 | * to touch the video data. | ||
8 | * | ||
9 | * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 | ||
14 | */ | ||
15 | |||
16 | #include <linux/init.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/moduleparam.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | |||
22 | #include <linux/pci.h> | ||
23 | #include <linux/vmalloc.h> | ||
24 | #include <linux/pagemap.h> | ||
25 | #include <asm/page.h> | ||
26 | #include <asm/pgtable.h> | ||
27 | |||
28 | #include <media/videobuf-vmalloc.h> | ||
29 | |||
30 | #define MAGIC_DMABUF 0x17760309 | ||
31 | #define MAGIC_VMAL_MEM 0x18221223 | ||
32 | |||
33 | #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ | ||
34 | { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } | ||
35 | |||
36 | static int debug = 0; | ||
37 | module_param(debug, int, 0644); | ||
38 | |||
39 | MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers"); | ||
40 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | |||
43 | #define dprintk(level, fmt, arg...) if (debug >= level) \ | ||
44 | printk(KERN_DEBUG "vbuf-sg: " fmt , ## arg) | ||
45 | |||
46 | |||
47 | /***************************************************************************/ | ||
48 | |||
49 | static void | ||
50 | videobuf_vm_open(struct vm_area_struct *vma) | ||
51 | { | ||
52 | struct videobuf_mapping *map = vma->vm_private_data; | ||
53 | |||
54 | dprintk(2,"vm_open %p [count=%d,vma=%08lx-%08lx]\n",map, | ||
55 | map->count,vma->vm_start,vma->vm_end); | ||
56 | |||
57 | map->count++; | ||
58 | } | ||
59 | |||
60 | static void | ||
61 | videobuf_vm_close(struct vm_area_struct *vma) | ||
62 | { | ||
63 | struct videobuf_mapping *map = vma->vm_private_data; | ||
64 | struct videobuf_queue *q = map->q; | ||
65 | int i; | ||
66 | |||
67 | dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map, | ||
68 | map->count,vma->vm_start,vma->vm_end); | ||
69 | |||
70 | map->count--; | ||
71 | if (0 == map->count) { | ||
72 | dprintk(1,"munmap %p q=%p\n",map,q); | ||
73 | mutex_lock(&q->lock); | ||
74 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
75 | if (NULL == q->bufs[i]) | ||
76 | continue; | ||
77 | |||
78 | if (q->bufs[i]->map != map) | ||
79 | continue; | ||
80 | |||
81 | q->ops->buf_release(q,q->bufs[i]); | ||
82 | |||
83 | q->bufs[i]->map = NULL; | ||
84 | q->bufs[i]->baddr = 0; | ||
85 | } | ||
86 | mutex_unlock(&q->lock); | ||
87 | kfree(map); | ||
88 | } | ||
89 | return; | ||
90 | } | ||
91 | |||
92 | static struct vm_operations_struct videobuf_vm_ops = | ||
93 | { | ||
94 | .open = videobuf_vm_open, | ||
95 | .close = videobuf_vm_close, | ||
96 | }; | ||
97 | |||
98 | /* --------------------------------------------------------------------- | ||
99 | * vmalloc handlers for the generic methods | ||
100 | */ | ||
101 | |||
102 | /* Allocated area consists on 3 parts: | ||
103 | struct video_buffer | ||
104 | struct <driver>_buffer (cx88_buffer, saa7134_buf, ...) | ||
105 | struct videobuf_pci_sg_memory | ||
106 | */ | ||
107 | |||
108 | static void *__videobuf_alloc(size_t size) | ||
109 | { | ||
110 | struct videbuf_vmalloc_memory *mem; | ||
111 | struct videobuf_buffer *vb; | ||
112 | |||
113 | vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); | ||
114 | |||
115 | mem = vb->priv = ((char *)vb)+size; | ||
116 | mem->magic=MAGIC_VMAL_MEM; | ||
117 | |||
118 | dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n", | ||
119 | __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb), | ||
120 | mem,(long)sizeof(*mem)); | ||
121 | |||
122 | return vb; | ||
123 | } | ||
124 | |||
125 | static int __videobuf_iolock (struct videobuf_queue* q, | ||
126 | struct videobuf_buffer *vb, | ||
127 | struct v4l2_framebuffer *fbuf) | ||
128 | { | ||
129 | int pages; | ||
130 | |||
131 | struct videbuf_vmalloc_memory *mem=vb->priv; | ||
132 | |||
133 | |||
134 | BUG_ON(!mem); | ||
135 | |||
136 | MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); | ||
137 | |||
138 | pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; | ||
139 | |||
140 | /* Currently, doesn't support V4L2_MEMORY_OVERLAY */ | ||
141 | if ((vb->memory != V4L2_MEMORY_MMAP) && | ||
142 | (vb->memory != V4L2_MEMORY_USERPTR) ) { | ||
143 | printk(KERN_ERR "Method currently unsupported.\n"); | ||
144 | return -EINVAL; | ||
145 | } | ||
146 | |||
147 | /* FIXME: should be tested with kernel mmap mem */ | ||
148 | mem->vmalloc=vmalloc_user (PAGE_ALIGN(vb->size)); | ||
149 | if (NULL == mem->vmalloc) { | ||
150 | printk(KERN_ERR "vmalloc (%d pages) failed\n",pages); | ||
151 | return -ENOMEM; | ||
152 | } | ||
153 | |||
154 | dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n", | ||
155 | (unsigned long)mem->vmalloc, | ||
156 | pages << PAGE_SHIFT); | ||
157 | |||
158 | /* It seems that some kernel versions need to do remap *after* | ||
159 | the mmap() call | ||
160 | */ | ||
161 | if (mem->vma) { | ||
162 | int retval=remap_vmalloc_range(mem->vma, mem->vmalloc,0); | ||
163 | kfree(mem->vma); | ||
164 | mem->vma=NULL; | ||
165 | if (retval<0) { | ||
166 | dprintk(1,"mmap app bug: remap_vmalloc_range area %p error %d\n", | ||
167 | mem->vmalloc,retval); | ||
168 | return retval; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int __videobuf_sync(struct videobuf_queue *q, | ||
176 | struct videobuf_buffer *buf) | ||
177 | { | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static int __videobuf_mmap_free(struct videobuf_queue *q) | ||
182 | { | ||
183 | unsigned int i; | ||
184 | |||
185 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
186 | if (q->bufs[i]) { | ||
187 | if (q->bufs[i]->map) | ||
188 | return -EBUSY; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static int __videobuf_mmap_mapper(struct videobuf_queue *q, | ||
196 | struct vm_area_struct *vma) | ||
197 | { | ||
198 | struct videbuf_vmalloc_memory *mem; | ||
199 | struct videobuf_mapping *map; | ||
200 | unsigned int first; | ||
201 | int retval; | ||
202 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
203 | |||
204 | if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED)) | ||
205 | return -EINVAL; | ||
206 | |||
207 | /* look for first buffer to map */ | ||
208 | for (first = 0; first < VIDEO_MAX_FRAME; first++) { | ||
209 | if (NULL == q->bufs[first]) | ||
210 | continue; | ||
211 | |||
212 | if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) | ||
213 | continue; | ||
214 | if (q->bufs[first]->boff == offset) | ||
215 | break; | ||
216 | } | ||
217 | if (VIDEO_MAX_FRAME == first) { | ||
218 | dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n", | ||
219 | (vma->vm_pgoff << PAGE_SHIFT)); | ||
220 | return -EINVAL; | ||
221 | } | ||
222 | |||
223 | /* create mapping + update buffer list */ | ||
224 | map = q->bufs[first]->map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL); | ||
225 | if (NULL == map) | ||
226 | return -ENOMEM; | ||
227 | |||
228 | map->start = vma->vm_start; | ||
229 | map->end = vma->vm_end; | ||
230 | map->q = q; | ||
231 | |||
232 | q->bufs[first]->baddr = vma->vm_start; | ||
233 | |||
234 | vma->vm_ops = &videobuf_vm_ops; | ||
235 | vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; | ||
236 | vma->vm_private_data = map; | ||
237 | |||
238 | mem=q->bufs[first]->priv; | ||
239 | BUG_ON (!mem); | ||
240 | MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); | ||
241 | |||
242 | /* Try to remap memory */ | ||
243 | retval=remap_vmalloc_range(vma, mem->vmalloc,0); | ||
244 | if (retval<0) { | ||
245 | dprintk(1,"mmap: postponing remap_vmalloc_range\n"); | ||
246 | |||
247 | mem->vma=kmalloc(sizeof(*vma),GFP_KERNEL); | ||
248 | if (!mem->vma) { | ||
249 | kfree(map); | ||
250 | q->bufs[first]->map=NULL; | ||
251 | return -ENOMEM; | ||
252 | } | ||
253 | memcpy(mem->vma,vma,sizeof(*vma)); | ||
254 | } | ||
255 | |||
256 | dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", | ||
257 | map,q,vma->vm_start,vma->vm_end, | ||
258 | (long int) q->bufs[first]->bsize, | ||
259 | vma->vm_pgoff,first); | ||
260 | |||
261 | videobuf_vm_open(vma); | ||
262 | |||
263 | return (0); | ||
264 | } | ||
265 | |||
266 | static int __videobuf_copy_to_user ( struct videobuf_queue *q, | ||
267 | char __user *data, size_t count, | ||
268 | int nonblocking ) | ||
269 | { | ||
270 | struct videbuf_vmalloc_memory *mem=q->read_buf->priv; | ||
271 | BUG_ON (!mem); | ||
272 | MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); | ||
273 | |||
274 | BUG_ON (!mem->vmalloc); | ||
275 | |||
276 | /* copy to userspace */ | ||
277 | if (count > q->read_buf->size - q->read_off) | ||
278 | count = q->read_buf->size - q->read_off; | ||
279 | |||
280 | if (copy_to_user(data, mem->vmalloc+q->read_off, count)) | ||
281 | return -EFAULT; | ||
282 | |||
283 | return count; | ||
284 | } | ||
285 | |||
286 | static int __videobuf_copy_stream ( struct videobuf_queue *q, | ||
287 | char __user *data, size_t count, size_t pos, | ||
288 | int vbihack, int nonblocking ) | ||
289 | { | ||
290 | unsigned int *fc; | ||
291 | struct videbuf_vmalloc_memory *mem=q->read_buf->priv; | ||
292 | BUG_ON (!mem); | ||
293 | MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); | ||
294 | |||
295 | if (vbihack) { | ||
296 | /* dirty, undocumented hack -- pass the frame counter | ||
297 | * within the last four bytes of each vbi data block. | ||
298 | * We need that one to maintain backward compatibility | ||
299 | * to all vbi decoding software out there ... */ | ||
300 | fc = (unsigned int*)mem->vmalloc; | ||
301 | fc += (q->read_buf->size>>2) -1; | ||
302 | *fc = q->read_buf->field_count >> 1; | ||
303 | dprintk(1,"vbihack: %d\n",*fc); | ||
304 | } | ||
305 | |||
306 | /* copy stuff using the common method */ | ||
307 | count = __videobuf_copy_to_user (q,data,count,nonblocking); | ||
308 | |||
309 | if ( (count==-EFAULT) && (0 == pos) ) | ||
310 | return -EFAULT; | ||
311 | |||
312 | return count; | ||
313 | } | ||
314 | |||
315 | static struct videobuf_qtype_ops qops = { | ||
316 | .magic = MAGIC_QTYPE_OPS, | ||
317 | |||
318 | .alloc = __videobuf_alloc, | ||
319 | .iolock = __videobuf_iolock, | ||
320 | .sync = __videobuf_sync, | ||
321 | .mmap_free = __videobuf_mmap_free, | ||
322 | .mmap_mapper = __videobuf_mmap_mapper, | ||
323 | .copy_to_user = __videobuf_copy_to_user, | ||
324 | .copy_stream = __videobuf_copy_stream, | ||
325 | }; | ||
326 | |||
327 | void videobuf_queue_vmalloc_init(struct videobuf_queue* q, | ||
328 | struct videobuf_queue_ops *ops, | ||
329 | void *dev, | ||
330 | spinlock_t *irqlock, | ||
331 | enum v4l2_buf_type type, | ||
332 | enum v4l2_field field, | ||
333 | unsigned int msize, | ||
334 | void *priv) | ||
335 | { | ||
336 | videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, | ||
337 | priv, &qops); | ||
338 | } | ||
339 | |||
340 | EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init); | ||
341 | |||
342 | void *videobuf_to_vmalloc (struct videobuf_buffer *buf) | ||
343 | { | ||
344 | struct videbuf_vmalloc_memory *mem=buf->priv; | ||
345 | BUG_ON (!mem); | ||
346 | MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); | ||
347 | |||
348 | return mem->vmalloc; | ||
349 | } | ||
350 | EXPORT_SYMBOL_GPL(videobuf_to_vmalloc); | ||
351 | |||
352 | void videobuf_vmalloc_free (struct videobuf_buffer *buf) | ||
353 | { | ||
354 | struct videbuf_vmalloc_memory *mem=buf->priv; | ||
355 | BUG_ON (!mem); | ||
356 | |||
357 | MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); | ||
358 | |||
359 | vfree(mem->vmalloc); | ||
360 | mem->vmalloc=NULL; | ||
361 | |||
362 | return; | ||
363 | } | ||
364 | EXPORT_SYMBOL_GPL(videobuf_vmalloc_free); | ||
365 | |||
366 | /* | ||
367 | * Local variables: | ||
368 | * c-basic-offset: 8 | ||
369 | * End: | ||
370 | */ | ||
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index b876aca69c73..8d8e517b344f 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c | |||
@@ -54,15 +54,14 @@ | |||
54 | * sysfs stuff | 54 | * sysfs stuff |
55 | */ | 55 | */ |
56 | 56 | ||
57 | static ssize_t show_name(struct class_device *cd, char *buf) | 57 | static ssize_t show_name(struct device *cd, |
58 | struct device_attribute *attr, char *buf) | ||
58 | { | 59 | { |
59 | struct video_device *vfd = container_of(cd, struct video_device, | 60 | struct video_device *vfd = container_of(cd, struct video_device, |
60 | class_dev); | 61 | class_dev); |
61 | return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name); | 62 | return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name); |
62 | } | 63 | } |
63 | 64 | ||
64 | static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
65 | |||
66 | struct video_device *video_device_alloc(void) | 65 | struct video_device *video_device_alloc(void) |
67 | { | 66 | { |
68 | struct video_device *vfd; | 67 | struct video_device *vfd; |
@@ -76,7 +75,7 @@ void video_device_release(struct video_device *vfd) | |||
76 | kfree(vfd); | 75 | kfree(vfd); |
77 | } | 76 | } |
78 | 77 | ||
79 | static void video_release(struct class_device *cd) | 78 | static void video_release(struct device *cd) |
80 | { | 79 | { |
81 | struct video_device *vfd = container_of(cd, struct video_device, | 80 | struct video_device *vfd = container_of(cd, struct video_device, |
82 | class_dev); | 81 | class_dev); |
@@ -89,9 +88,15 @@ static void video_release(struct class_device *cd) | |||
89 | vfd->release(vfd); | 88 | vfd->release(vfd); |
90 | } | 89 | } |
91 | 90 | ||
91 | static struct device_attribute video_device_attrs[] = { | ||
92 | __ATTR(name, S_IRUGO, show_name, NULL), | ||
93 | __ATTR_NULL | ||
94 | }; | ||
95 | |||
92 | static struct class video_class = { | 96 | static struct class video_class = { |
93 | .name = VIDEO_NAME, | 97 | .name = VIDEO_NAME, |
94 | .release = video_release, | 98 | .dev_attrs = video_device_attrs, |
99 | .dev_release = video_release, | ||
95 | }; | 100 | }; |
96 | 101 | ||
97 | /* | 102 | /* |
@@ -448,7 +453,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
448 | if (cmd == VIDIOCGMBUF) { | 453 | if (cmd == VIDIOCGMBUF) { |
449 | struct video_mbuf *p=arg; | 454 | struct video_mbuf *p=arg; |
450 | 455 | ||
451 | memset(p,0,sizeof(p)); | 456 | memset(p, 0, sizeof(*p)); |
452 | 457 | ||
453 | if (!vfd->vidiocgmbuf) | 458 | if (!vfd->vidiocgmbuf) |
454 | return ret; | 459 | return ret; |
@@ -1753,22 +1758,16 @@ int video_register_device(struct video_device *vfd, int type, int nr) | |||
1753 | /* sysfs class */ | 1758 | /* sysfs class */ |
1754 | memset(&vfd->class_dev, 0x00, sizeof(vfd->class_dev)); | 1759 | memset(&vfd->class_dev, 0x00, sizeof(vfd->class_dev)); |
1755 | if (vfd->dev) | 1760 | if (vfd->dev) |
1756 | vfd->class_dev.dev = vfd->dev; | 1761 | vfd->class_dev.parent = vfd->dev; |
1757 | vfd->class_dev.class = &video_class; | 1762 | vfd->class_dev.class = &video_class; |
1758 | vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); | 1763 | vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); |
1759 | sprintf(vfd->class_dev.class_id, "%s%d", name_base, i - base); | 1764 | sprintf(vfd->class_dev.bus_id, "%s%d", name_base, i - base); |
1760 | ret = class_device_register(&vfd->class_dev); | 1765 | ret = device_register(&vfd->class_dev); |
1761 | if (ret < 0) { | 1766 | if (ret < 0) { |
1762 | printk(KERN_ERR "%s: class_device_register failed\n", | 1767 | printk(KERN_ERR "%s: device_register failed\n", |
1763 | __FUNCTION__); | 1768 | __FUNCTION__); |
1764 | goto fail_minor; | 1769 | goto fail_minor; |
1765 | } | 1770 | } |
1766 | ret = class_device_create_file(&vfd->class_dev, &class_device_attr_name); | ||
1767 | if (ret < 0) { | ||
1768 | printk(KERN_ERR "%s: class_device_create_file 'name' failed\n", | ||
1769 | __FUNCTION__); | ||
1770 | goto fail_classdev; | ||
1771 | } | ||
1772 | 1771 | ||
1773 | #if 1 | 1772 | #if 1 |
1774 | /* needed until all drivers are fixed */ | 1773 | /* needed until all drivers are fixed */ |
@@ -1779,8 +1778,6 @@ int video_register_device(struct video_device *vfd, int type, int nr) | |||
1779 | #endif | 1778 | #endif |
1780 | return 0; | 1779 | return 0; |
1781 | 1780 | ||
1782 | fail_classdev: | ||
1783 | class_device_unregister(&vfd->class_dev); | ||
1784 | fail_minor: | 1781 | fail_minor: |
1785 | mutex_lock(&videodev_lock); | 1782 | mutex_lock(&videodev_lock); |
1786 | video_device[vfd->minor] = NULL; | 1783 | video_device[vfd->minor] = NULL; |
@@ -1804,7 +1801,7 @@ void video_unregister_device(struct video_device *vfd) | |||
1804 | panic("videodev: bad unregister"); | 1801 | panic("videodev: bad unregister"); |
1805 | 1802 | ||
1806 | video_device[vfd->minor]=NULL; | 1803 | video_device[vfd->minor]=NULL; |
1807 | class_device_unregister(&vfd->class_dev); | 1804 | device_unregister(&vfd->class_dev); |
1808 | mutex_unlock(&videodev_lock); | 1805 | mutex_unlock(&videodev_lock); |
1809 | } | 1806 | } |
1810 | 1807 | ||
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index a0c1647a2ba4..9a03dc82c6ca 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/time.h> | 31 | #include <linux/time.h> |
33 | #include <linux/version.h> | 32 | #include <linux/version.h> |
34 | 33 | ||
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index f6d3a9460ccc..b532aa280a1b 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/videodev.h> | 33 | #include <linux/videodev.h> |
34 | #endif | 34 | #endif |
35 | #include <linux/interrupt.h> | 35 | #include <linux/interrupt.h> |
36 | #include <media/video-buf.h> | 36 | #include <media/videobuf-vmalloc.h> |
37 | #include <media/v4l2-common.h> | 37 | #include <media/v4l2-common.h> |
38 | #include <linux/kthread.h> | 38 | #include <linux/kthread.h> |
39 | #include <linux/highmem.h> | 39 | #include <linux/highmem.h> |
@@ -145,7 +145,6 @@ struct vivi_buffer { | |||
145 | struct videobuf_buffer vb; | 145 | struct videobuf_buffer vb; |
146 | 146 | ||
147 | struct vivi_fmt *fmt; | 147 | struct vivi_fmt *fmt; |
148 | |||
149 | }; | 148 | }; |
150 | 149 | ||
151 | struct vivi_dmaqueue { | 150 | struct vivi_dmaqueue { |
@@ -171,7 +170,6 @@ struct vivi_dev { | |||
171 | int users; | 170 | int users; |
172 | 171 | ||
173 | /* various device info */ | 172 | /* various device info */ |
174 | unsigned int resources; | ||
175 | struct video_device vfd; | 173 | struct video_device vfd; |
176 | 174 | ||
177 | struct vivi_dmaqueue vidq; | 175 | struct vivi_dmaqueue vidq; |
@@ -230,9 +228,8 @@ static u8 bars[8][3] = { | |||
230 | #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 | 228 | #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 |
231 | #define TSTAMP_MIN_X 64 | 229 | #define TSTAMP_MIN_X 64 |
232 | 230 | ||
233 | |||
234 | static void gen_line(char *basep,int inipos,int wmax, | 231 | static void gen_line(char *basep,int inipos,int wmax, |
235 | int hmax, int line, char *timestr) | 232 | int hmax, int line, int count, char *timestr) |
236 | { | 233 | { |
237 | int w,i,j,pos=inipos,y; | 234 | int w,i,j,pos=inipos,y; |
238 | char *p,*s; | 235 | char *p,*s; |
@@ -243,9 +240,10 @@ static void gen_line(char *basep,int inipos,int wmax, | |||
243 | 240 | ||
244 | /* Generate a standard color bar pattern */ | 241 | /* Generate a standard color bar pattern */ |
245 | for (w=0;w<wmax;w++) { | 242 | for (w=0;w<wmax;w++) { |
246 | r=bars[w*7/wmax][0]; | 243 | int colorpos=((w+count)*8/(wmax+1)) % 8; |
247 | g=bars[w*7/wmax][1]; | 244 | r=bars[colorpos][0]; |
248 | b=bars[w*7/wmax][2]; | 245 | g=bars[colorpos][1]; |
246 | b=bars[colorpos][2]; | ||
249 | 247 | ||
250 | for (color=0;color<4;color++) { | 248 | for (color=0;color<4;color++) { |
251 | p=basep+pos; | 249 | p=basep+pos; |
@@ -326,27 +324,27 @@ static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) | |||
326 | int hmax = buf->vb.height; | 324 | int hmax = buf->vb.height; |
327 | int wmax = buf->vb.width; | 325 | int wmax = buf->vb.width; |
328 | struct timeval ts; | 326 | struct timeval ts; |
329 | char *tmpbuf; | 327 | char *tmpbuf = kmalloc(wmax*2,GFP_KERNEL); |
330 | 328 | void *vbuf=videobuf_to_vmalloc (&buf->vb); | |
331 | if (buf->vb.dma.varea) { | 329 | /* FIXME: move to dev struct */ |
332 | tmpbuf=kmalloc (wmax*2, GFP_KERNEL); | 330 | static int mv_count=0; |
333 | } else { | ||
334 | tmpbuf=buf->vb.dma.vmalloc; | ||
335 | } | ||
336 | 331 | ||
332 | if (!tmpbuf) | ||
333 | return; | ||
337 | 334 | ||
338 | for (h=0;h<hmax;h++) { | 335 | for (h=0;h<hmax;h++) { |
339 | if (buf->vb.dma.varea) { | 336 | gen_line(tmpbuf,0,wmax,hmax,h,mv_count, |
340 | gen_line(tmpbuf,0,wmax,hmax,h,dev->timestr); | 337 | dev->timestr); |
341 | /* FIXME: replacing to __copy_to_user */ | 338 | /* FIXME: replacing to __copy_to_user */ |
342 | if (copy_to_user(buf->vb.dma.varea+pos,tmpbuf,wmax*2)!=0) | 339 | if (copy_to_user(vbuf+pos,tmpbuf,wmax*2)!=0) |
343 | dprintk(2,"vivifill copy_to_user failed.\n"); | 340 | dprintk(2,"vivifill copy_to_user failed.\n"); |
344 | } else { | ||
345 | gen_line(tmpbuf,pos,wmax,hmax,h,dev->timestr); | ||
346 | } | ||
347 | pos += wmax*2; | 341 | pos += wmax*2; |
348 | } | 342 | } |
349 | 343 | ||
344 | mv_count++; | ||
345 | |||
346 | kfree(tmpbuf); | ||
347 | |||
350 | /* Updates stream time */ | 348 | /* Updates stream time */ |
351 | 349 | ||
352 | dev->us+=jiffies_to_usecs(jiffies-dev->jiffies); | 350 | dev->us+=jiffies_to_usecs(jiffies-dev->jiffies); |
@@ -369,7 +367,7 @@ static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) | |||
369 | dev->h,dev->m,dev->s,(dev->us+500)/1000); | 367 | dev->h,dev->m,dev->s,(dev->us+500)/1000); |
370 | 368 | ||
371 | dprintk(2,"vivifill at %s: Buffer 0x%08lx size= %d\n",dev->timestr, | 369 | dprintk(2,"vivifill at %s: Buffer 0x%08lx size= %d\n",dev->timestr, |
372 | (unsigned long)buf->vb.dma.varea,pos); | 370 | (unsigned long)tmpbuf,pos); |
373 | 371 | ||
374 | /* Advice that buffer was filled */ | 372 | /* Advice that buffer was filled */ |
375 | buf->vb.state = STATE_DONE; | 373 | buf->vb.state = STATE_DONE; |
@@ -509,7 +507,6 @@ static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) | |||
509 | static int restart_video_queue(struct vivi_dmaqueue *dma_q) | 507 | static int restart_video_queue(struct vivi_dmaqueue *dma_q) |
510 | { | 508 | { |
511 | struct vivi_buffer *buf, *prev; | 509 | struct vivi_buffer *buf, *prev; |
512 | struct list_head *item; | ||
513 | 510 | ||
514 | dprintk(1,"%s dma_q=0x%08lx\n",__FUNCTION__,(unsigned long)dma_q); | 511 | dprintk(1,"%s dma_q=0x%08lx\n",__FUNCTION__,(unsigned long)dma_q); |
515 | 512 | ||
@@ -523,9 +520,7 @@ static int restart_video_queue(struct vivi_dmaqueue *dma_q) | |||
523 | // vivi_start_thread(dma_q); | 520 | // vivi_start_thread(dma_q); |
524 | 521 | ||
525 | /* cancel all outstanding capture / vbi requests */ | 522 | /* cancel all outstanding capture / vbi requests */ |
526 | list_for_each(item,&dma_q->active) { | 523 | list_for_each_entry_safe(buf, prev, &dma_q->active, vb.queue) { |
527 | buf = list_entry(item, struct vivi_buffer, vb.queue); | ||
528 | |||
529 | list_del(&buf->vb.queue); | 524 | list_del(&buf->vb.queue); |
530 | buf->vb.state = STATE_ERROR; | 525 | buf->vb.state = STATE_ERROR; |
531 | wake_up(&buf->vb.done); | 526 | wake_up(&buf->vb.done); |
@@ -597,8 +592,12 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) | |||
597 | 592 | ||
598 | if (0 == *count) | 593 | if (0 == *count) |
599 | *count = 32; | 594 | *count = 32; |
595 | |||
600 | while (*size * *count > vid_limit * 1024 * 1024) | 596 | while (*size * *count > vid_limit * 1024 * 1024) |
601 | (*count)--; | 597 | (*count)--; |
598 | |||
599 | dprintk(1,"%s, count=%d, size=%d\n",__FUNCTION__,*count, *size); | ||
600 | |||
602 | return 0; | 601 | return 0; |
603 | } | 602 | } |
604 | 603 | ||
@@ -609,10 +608,8 @@ static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) | |||
609 | if (in_interrupt()) | 608 | if (in_interrupt()) |
610 | BUG(); | 609 | BUG(); |
611 | 610 | ||
612 | |||
613 | videobuf_waiton(&buf->vb,0,0); | 611 | videobuf_waiton(&buf->vb,0,0); |
614 | videobuf_dma_unmap(vq, &buf->vb.dma); | 612 | videobuf_vmalloc_free(&buf->vb); |
615 | videobuf_dma_free(&buf->vb.dma); | ||
616 | buf->vb.state = STATE_NEEDS_INIT; | 613 | buf->vb.state = STATE_NEEDS_INIT; |
617 | } | 614 | } |
618 | 615 | ||
@@ -626,7 +623,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | |||
626 | struct vivi_buffer *buf = container_of(vb,struct vivi_buffer,vb); | 623 | struct vivi_buffer *buf = container_of(vb,struct vivi_buffer,vb); |
627 | int rc, init_buffer = 0; | 624 | int rc, init_buffer = 0; |
628 | 625 | ||
629 | // dprintk(1,"%s, field=%d\n",__FUNCTION__,field); | 626 | dprintk(1,"%s, field=%d\n",__FUNCTION__,field); |
630 | 627 | ||
631 | BUG_ON(NULL == fh->fmt); | 628 | BUG_ON(NULL == fh->fmt); |
632 | if (fh->width < 48 || fh->width > norm_maxw() || | 629 | if (fh->width < 48 || fh->width > norm_maxw() || |
@@ -718,54 +715,14 @@ static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb | |||
718 | free_buffer(vq,buf); | 715 | free_buffer(vq,buf); |
719 | } | 716 | } |
720 | 717 | ||
721 | |||
722 | static struct videobuf_queue_ops vivi_video_qops = { | 718 | static struct videobuf_queue_ops vivi_video_qops = { |
723 | .buf_setup = buffer_setup, | 719 | .buf_setup = buffer_setup, |
724 | .buf_prepare = buffer_prepare, | 720 | .buf_prepare = buffer_prepare, |
725 | .buf_queue = buffer_queue, | 721 | .buf_queue = buffer_queue, |
726 | .buf_release = buffer_release, | 722 | .buf_release = buffer_release, |
727 | |||
728 | /* Non-pci handling routines */ | ||
729 | // .vb_map_sg = vivi_map_sg, | ||
730 | // .vb_dma_sync_sg = vivi_dma_sync_sg, | ||
731 | // .vb_unmap_sg = vivi_unmap_sg, | ||
732 | }; | 723 | }; |
733 | 724 | ||
734 | /* ------------------------------------------------------------------ | 725 | /* ------------------------------------------------------------------ |
735 | IOCTL handling | ||
736 | ------------------------------------------------------------------*/ | ||
737 | |||
738 | |||
739 | static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) | ||
740 | { | ||
741 | /* is it free? */ | ||
742 | mutex_lock(&dev->lock); | ||
743 | if (dev->resources) { | ||
744 | /* no, someone else uses it */ | ||
745 | mutex_unlock(&dev->lock); | ||
746 | return 0; | ||
747 | } | ||
748 | /* it's free, grab it */ | ||
749 | dev->resources =1; | ||
750 | dprintk(1,"res: get\n"); | ||
751 | mutex_unlock(&dev->lock); | ||
752 | return 1; | ||
753 | } | ||
754 | |||
755 | static int res_locked(struct vivi_dev *dev) | ||
756 | { | ||
757 | return (dev->resources); | ||
758 | } | ||
759 | |||
760 | static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) | ||
761 | { | ||
762 | mutex_lock(&dev->lock); | ||
763 | dev->resources = 0; | ||
764 | dprintk(1,"res: put\n"); | ||
765 | mutex_lock(&dev->lock); | ||
766 | } | ||
767 | |||
768 | /* ------------------------------------------------------------------ | ||
769 | IOCTL vidioc handling | 726 | IOCTL vidioc handling |
770 | ------------------------------------------------------------------*/ | 727 | ------------------------------------------------------------------*/ |
771 | static int vidioc_querycap (struct file *file, void *priv, | 728 | static int vidioc_querycap (struct file *file, void *priv, |
@@ -825,8 +782,7 @@ static int vidioc_try_fmt_cap (struct file *file, void *priv, | |||
825 | field = f->fmt.pix.field; | 782 | field = f->fmt.pix.field; |
826 | 783 | ||
827 | if (field == V4L2_FIELD_ANY) { | 784 | if (field == V4L2_FIELD_ANY) { |
828 | // field=V4L2_FIELD_INTERLACED; | 785 | field=V4L2_FIELD_INTERLACED; |
829 | field=V4L2_FIELD_SEQ_TB; | ||
830 | } else if (V4L2_FIELD_INTERLACED != field) { | 786 | } else if (V4L2_FIELD_INTERLACED != field) { |
831 | dprintk(1,"Field type invalid.\n"); | 787 | dprintk(1,"Field type invalid.\n"); |
832 | return -EINVAL; | 788 | return -EINVAL; |
@@ -904,57 +860,33 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) | |||
904 | static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) | 860 | static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) |
905 | { | 861 | { |
906 | struct vivi_fh *fh=priv; | 862 | struct vivi_fh *fh=priv; |
907 | struct videobuf_queue *q=&fh->vb_vidq; | ||
908 | struct v4l2_requestbuffers req; | ||
909 | unsigned int i; | ||
910 | int ret; | ||
911 | |||
912 | req.type = q->type; | ||
913 | req.count = 8; | ||
914 | req.memory = V4L2_MEMORY_MMAP; | ||
915 | ret = videobuf_reqbufs(q,&req); | ||
916 | if (ret < 0) | ||
917 | return (ret); | ||
918 | 863 | ||
919 | mbuf->frames = req.count; | 864 | return videobuf_cgmbuf (&fh->vb_vidq, mbuf, 8); |
920 | mbuf->size = 0; | ||
921 | for (i = 0; i < mbuf->frames; i++) { | ||
922 | mbuf->offsets[i] = q->bufs[i]->boff; | ||
923 | mbuf->size += q->bufs[i]->bsize; | ||
924 | } | ||
925 | return (0); | ||
926 | } | 865 | } |
927 | #endif | 866 | #endif |
928 | 867 | ||
929 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | 868 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) |
930 | { | 869 | { |
931 | struct vivi_fh *fh=priv; | 870 | struct vivi_fh *fh=priv; |
932 | struct vivi_dev *dev = fh->dev; | ||
933 | 871 | ||
934 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 872 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
935 | return -EINVAL; | 873 | return -EINVAL; |
936 | if (i != fh->type) | 874 | if (i != fh->type) |
937 | return -EINVAL; | 875 | return -EINVAL; |
938 | 876 | ||
939 | if (!res_get(dev,fh)) | 877 | return videobuf_streamon(&fh->vb_vidq); |
940 | return -EBUSY; | ||
941 | return (videobuf_streamon(&fh->vb_vidq)); | ||
942 | } | 878 | } |
943 | 879 | ||
944 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | 880 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) |
945 | { | 881 | { |
946 | struct vivi_fh *fh=priv; | 882 | struct vivi_fh *fh=priv; |
947 | struct vivi_dev *dev = fh->dev; | ||
948 | 883 | ||
949 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 884 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
950 | return -EINVAL; | 885 | return -EINVAL; |
951 | if (i != fh->type) | 886 | if (i != fh->type) |
952 | return -EINVAL; | 887 | return -EINVAL; |
953 | 888 | ||
954 | videobuf_streamoff(&fh->vb_vidq); | 889 | return videobuf_streamoff(&fh->vb_vidq); |
955 | res_free(dev,fh); | ||
956 | |||
957 | return (0); | ||
958 | } | 890 | } |
959 | 891 | ||
960 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *i) | 892 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *i) |
@@ -1047,31 +979,25 @@ static int vidioc_s_ctrl (struct file *file, void *priv, | |||
1047 | static int vivi_open(struct inode *inode, struct file *file) | 979 | static int vivi_open(struct inode *inode, struct file *file) |
1048 | { | 980 | { |
1049 | int minor = iminor(inode); | 981 | int minor = iminor(inode); |
1050 | struct vivi_dev *h,*dev = NULL; | 982 | struct vivi_dev *dev; |
1051 | struct vivi_fh *fh; | 983 | struct vivi_fh *fh; |
1052 | struct list_head *list; | ||
1053 | enum v4l2_buf_type type = 0; | ||
1054 | int i; | 984 | int i; |
1055 | 985 | ||
1056 | printk(KERN_DEBUG "vivi: open called (minor=%d)\n",minor); | 986 | printk(KERN_DEBUG "vivi: open called (minor=%d)\n",minor); |
1057 | 987 | ||
1058 | list_for_each(list,&vivi_devlist) { | 988 | list_for_each_entry(dev, &vivi_devlist, vivi_devlist) |
1059 | h = list_entry(list, struct vivi_dev, vivi_devlist); | 989 | if (dev->vfd.minor == minor) |
1060 | if (h->vfd.minor == minor) { | 990 | goto found; |
1061 | dev = h; | 991 | return -ENODEV; |
1062 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 992 | found: |
1063 | } | ||
1064 | } | ||
1065 | if (NULL == dev) | ||
1066 | return -ENODEV; | ||
1067 | 993 | ||
1068 | 994 | ||
1069 | 995 | ||
1070 | /* If more than one user, mutex should be added */ | 996 | /* If more than one user, mutex should be added */ |
1071 | dev->users++; | 997 | dev->users++; |
1072 | 998 | ||
1073 | dprintk(1,"open minor=%d type=%s users=%d\n", | 999 | dprintk(1, "open minor=%d type=%s users=%d\n", minor, |
1074 | minor,v4l2_type_names[type],dev->users); | 1000 | v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); |
1075 | 1001 | ||
1076 | /* allocate + initialize per filehandle data */ | 1002 | /* allocate + initialize per filehandle data */ |
1077 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | 1003 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); |
@@ -1106,7 +1032,7 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1106 | sprintf(dev->timestr,"%02d:%02d:%02d:%03d", | 1032 | sprintf(dev->timestr,"%02d:%02d:%02d:%03d", |
1107 | dev->h,dev->m,dev->s,(dev->us+500)/1000); | 1033 | dev->h,dev->m,dev->s,(dev->us+500)/1000); |
1108 | 1034 | ||
1109 | videobuf_queue_init(&fh->vb_vidq, &vivi_video_qops, | 1035 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops, |
1110 | NULL, NULL, | 1036 | NULL, NULL, |
1111 | fh->type, | 1037 | fh->type, |
1112 | V4L2_FIELD_INTERLACED, | 1038 | V4L2_FIELD_INTERLACED, |
@@ -1121,9 +1047,7 @@ vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | |||
1121 | struct vivi_fh *fh = file->private_data; | 1047 | struct vivi_fh *fh = file->private_data; |
1122 | 1048 | ||
1123 | if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1049 | if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1124 | if (res_locked(fh->dev)) | 1050 | return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0, |
1125 | return -EBUSY; | ||
1126 | return videobuf_read_one(&fh->vb_vidq, data, count, ppos, | ||
1127 | file->f_flags & O_NONBLOCK); | 1051 | file->f_flags & O_NONBLOCK); |
1128 | } | 1052 | } |
1129 | return 0; | 1053 | return 0; |
@@ -1133,31 +1057,14 @@ static unsigned int | |||
1133 | vivi_poll(struct file *file, struct poll_table_struct *wait) | 1057 | vivi_poll(struct file *file, struct poll_table_struct *wait) |
1134 | { | 1058 | { |
1135 | struct vivi_fh *fh = file->private_data; | 1059 | struct vivi_fh *fh = file->private_data; |
1136 | struct vivi_buffer *buf; | 1060 | struct videobuf_queue *q = &fh->vb_vidq; |
1137 | 1061 | ||
1138 | dprintk(1,"%s\n",__FUNCTION__); | 1062 | dprintk(1,"%s\n",__FUNCTION__); |
1139 | 1063 | ||
1140 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) | 1064 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) |
1141 | return POLLERR; | 1065 | return POLLERR; |
1142 | 1066 | ||
1143 | if (res_get(fh->dev,fh)) { | 1067 | return videobuf_poll_stream(file, q, wait); |
1144 | dprintk(1,"poll: mmap interface\n"); | ||
1145 | /* streaming capture */ | ||
1146 | if (list_empty(&fh->vb_vidq.stream)) | ||
1147 | return POLLERR; | ||
1148 | buf = list_entry(fh->vb_vidq.stream.next,struct vivi_buffer,vb.stream); | ||
1149 | } else { | ||
1150 | dprintk(1,"poll: read() interface\n"); | ||
1151 | /* read() capture */ | ||
1152 | buf = (struct vivi_buffer*)fh->vb_vidq.read_buf; | ||
1153 | if (NULL == buf) | ||
1154 | return POLLERR; | ||
1155 | } | ||
1156 | poll_wait(file, &buf->vb.done, wait); | ||
1157 | if (buf->vb.state == STATE_DONE || | ||
1158 | buf->vb.state == STATE_ERROR) | ||
1159 | return POLLIN|POLLRDNORM; | ||
1160 | return 0; | ||
1161 | } | 1068 | } |
1162 | 1069 | ||
1163 | static int vivi_release(struct inode *inode, struct file *file) | 1070 | static int vivi_release(struct inode *inode, struct file *file) |
@@ -1205,7 +1112,7 @@ static const struct file_operations vivi_fops = { | |||
1205 | .read = vivi_read, | 1112 | .read = vivi_read, |
1206 | .poll = vivi_poll, | 1113 | .poll = vivi_poll, |
1207 | .ioctl = video_ioctl2, /* V4L2 ioctl handler */ | 1114 | .ioctl = video_ioctl2, /* V4L2 ioctl handler */ |
1208 | .mmap = vivi_mmap, | 1115 | .mmap = vivi_mmap, |
1209 | .llseek = no_llseek, | 1116 | .llseek = no_llseek, |
1210 | }; | 1117 | }; |
1211 | 1118 | ||
diff --git a/drivers/media/video/vp27smpx.c b/drivers/media/video/vp27smpx.c new file mode 100644 index 000000000000..63002e0ac764 --- /dev/null +++ b/drivers/media/video/vp27smpx.c | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | * vp27smpx - driver version 0.0.1 | ||
3 | * | ||
4 | * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | * | ||
6 | * Based on a tvaudio patch from Takahiro Adachi <tadachi@tadachi-net.com> | ||
7 | * and Kazuhiko Kawakami <kazz-0@mail.goo.ne.jp> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/ioctl.h> | ||
27 | #include <asm/uaccess.h> | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/i2c-id.h> | ||
30 | #include <linux/videodev.h> | ||
31 | #include <media/v4l2-common.h> | ||
32 | #include <media/v4l2-chip-ident.h> | ||
33 | |||
34 | MODULE_DESCRIPTION("vp27smpx driver"); | ||
35 | MODULE_AUTHOR("Hans Verkuil"); | ||
36 | MODULE_LICENSE("GPL"); | ||
37 | |||
38 | static unsigned short normal_i2c[] = { 0xb6 >> 1, I2C_CLIENT_END }; | ||
39 | |||
40 | |||
41 | I2C_CLIENT_INSMOD; | ||
42 | |||
43 | /* ----------------------------------------------------------------------- */ | ||
44 | |||
45 | struct vp27smpx_state { | ||
46 | int radio; | ||
47 | u32 audmode; | ||
48 | }; | ||
49 | |||
50 | static void vp27smpx_set_audmode(struct i2c_client *client, u32 audmode) | ||
51 | { | ||
52 | struct vp27smpx_state *state = i2c_get_clientdata(client); | ||
53 | u8 data[3] = { 0x00, 0x00, 0x04 }; | ||
54 | |||
55 | switch (audmode) { | ||
56 | case V4L2_TUNER_MODE_MONO: | ||
57 | case V4L2_TUNER_MODE_LANG1: | ||
58 | break; | ||
59 | case V4L2_TUNER_MODE_STEREO: | ||
60 | case V4L2_TUNER_MODE_LANG1_LANG2: | ||
61 | data[1] = 0x01; | ||
62 | break; | ||
63 | case V4L2_TUNER_MODE_LANG2: | ||
64 | data[1] = 0x02; | ||
65 | break; | ||
66 | } | ||
67 | |||
68 | if (i2c_master_send(client, data, sizeof(data)) != sizeof(data)) { | ||
69 | v4l_err(client, "%s: I/O error setting audmode\n", client->name); | ||
70 | } | ||
71 | else { | ||
72 | state->audmode = audmode; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | static int vp27smpx_command(struct i2c_client *client, unsigned int cmd, | ||
77 | void *arg) | ||
78 | { | ||
79 | struct vp27smpx_state *state = i2c_get_clientdata(client); | ||
80 | struct v4l2_tuner *vt = arg; | ||
81 | |||
82 | switch (cmd) { | ||
83 | case AUDC_SET_RADIO: | ||
84 | state->radio = 1; | ||
85 | break; | ||
86 | |||
87 | case VIDIOC_S_STD: | ||
88 | state->radio = 0; | ||
89 | break; | ||
90 | |||
91 | case VIDIOC_S_TUNER: | ||
92 | if (!state->radio) | ||
93 | vp27smpx_set_audmode(client, vt->audmode); | ||
94 | break; | ||
95 | |||
96 | case VIDIOC_G_TUNER: | ||
97 | if (state->radio) | ||
98 | break; | ||
99 | vt->audmode = state->audmode; | ||
100 | vt->capability = V4L2_TUNER_CAP_STEREO | | ||
101 | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; | ||
102 | vt->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
103 | break; | ||
104 | |||
105 | case VIDIOC_G_CHIP_IDENT: | ||
106 | return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_VP27SMPX, 0); | ||
107 | |||
108 | case VIDIOC_LOG_STATUS: | ||
109 | v4l_info(client, "Audio Mode: %u%s\n", state->audmode, | ||
110 | state->radio ? " (Radio)" : ""); | ||
111 | break; | ||
112 | |||
113 | default: | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | /* ----------------------------------------------------------------------- */ | ||
120 | |||
121 | /* i2c implementation */ | ||
122 | |||
123 | /* | ||
124 | * Generic i2c probe | ||
125 | * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' | ||
126 | */ | ||
127 | |||
128 | static struct i2c_driver i2c_driver; | ||
129 | |||
130 | static int vp27smpx_attach(struct i2c_adapter *adapter, int address, int kind) | ||
131 | { | ||
132 | struct i2c_client *client; | ||
133 | struct vp27smpx_state *state; | ||
134 | |||
135 | /* Check if the adapter supports the needed features */ | ||
136 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
137 | return 0; | ||
138 | |||
139 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
140 | if (client == 0) | ||
141 | return -ENOMEM; | ||
142 | |||
143 | client->addr = address; | ||
144 | client->adapter = adapter; | ||
145 | client->driver = &i2c_driver; | ||
146 | snprintf(client->name, sizeof(client->name) - 1, "vp27smpx"); | ||
147 | |||
148 | v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); | ||
149 | |||
150 | state = kzalloc(sizeof(struct vp27smpx_state), GFP_KERNEL); | ||
151 | if (state == NULL) { | ||
152 | kfree(client); | ||
153 | return -ENOMEM; | ||
154 | } | ||
155 | state->audmode = V4L2_TUNER_MODE_STEREO; | ||
156 | i2c_set_clientdata(client, state); | ||
157 | |||
158 | /* initialize vp27smpx */ | ||
159 | vp27smpx_set_audmode(client, state->audmode); | ||
160 | i2c_attach_client(client); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int vp27smpx_probe(struct i2c_adapter *adapter) | ||
166 | { | ||
167 | if (adapter->class & I2C_CLASS_TV_ANALOG) | ||
168 | return i2c_probe(adapter, &addr_data, vp27smpx_attach); | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int vp27smpx_detach(struct i2c_client *client) | ||
173 | { | ||
174 | struct vp27smpx_state *state = i2c_get_clientdata(client); | ||
175 | int err; | ||
176 | |||
177 | err = i2c_detach_client(client); | ||
178 | if (err) { | ||
179 | return err; | ||
180 | } | ||
181 | kfree(state); | ||
182 | kfree(client); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | /* ----------------------------------------------------------------------- */ | ||
188 | |||
189 | /* i2c implementation */ | ||
190 | static struct i2c_driver i2c_driver = { | ||
191 | .driver = { | ||
192 | .name = "vp27smpx", | ||
193 | }, | ||
194 | .id = I2C_DRIVERID_VP27SMPX, | ||
195 | .attach_adapter = vp27smpx_probe, | ||
196 | .detach_client = vp27smpx_detach, | ||
197 | .command = vp27smpx_command, | ||
198 | }; | ||
199 | |||
200 | |||
201 | static int __init vp27smpx_init_module(void) | ||
202 | { | ||
203 | return i2c_add_driver(&i2c_driver); | ||
204 | } | ||
205 | |||
206 | static void __exit vp27smpx_cleanup_module(void) | ||
207 | { | ||
208 | i2c_del_driver(&i2c_driver); | ||
209 | } | ||
210 | |||
211 | module_init(vp27smpx_init_module); | ||
212 | module_exit(vp27smpx_cleanup_module); | ||
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index 8f31613b9903..5a1b5f5a7d46 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <asm/page.h> | 42 | #include <asm/page.h> |
43 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
44 | #include <linux/page-flags.h> | 44 | #include <linux/page-flags.h> |
45 | #include <linux/moduleparam.h> | ||
46 | 45 | ||
47 | #include "w9968cf.h" | 46 | #include "w9968cf.h" |
48 | #include "w9968cf_decoder.h" | 47 | #include "w9968cf_decoder.h" |
@@ -2680,7 +2679,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp) | |||
2680 | 2679 | ||
2681 | /* This the only safe way to prevent race conditions with disconnect */ | 2680 | /* This the only safe way to prevent race conditions with disconnect */ |
2682 | if (!down_read_trylock(&w9968cf_disconnect)) | 2681 | if (!down_read_trylock(&w9968cf_disconnect)) |
2683 | return -ERESTARTSYS; | 2682 | return -EAGAIN; |
2684 | 2683 | ||
2685 | cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); | 2684 | cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); |
2686 | 2685 | ||
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 703b741e46df..08a93c31c0a0 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/param.h> | 28 | #include <linux/param.h> |
29 | #include <linux/moduleparam.h> | ||
30 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
31 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
32 | #include <linux/device.h> | 31 | #include <linux/device.h> |
@@ -656,7 +655,7 @@ static int zc0301_open(struct inode* inode, struct file* filp) | |||
656 | int err = 0; | 655 | int err = 0; |
657 | 656 | ||
658 | if (!down_read_trylock(&zc0301_dev_lock)) | 657 | if (!down_read_trylock(&zc0301_dev_lock)) |
659 | return -ERESTARTSYS; | 658 | return -EAGAIN; |
660 | 659 | ||
661 | cam = video_get_drvdata(video_devdata(filp)); | 660 | cam = video_get_drvdata(video_devdata(filp)); |
662 | 661 | ||
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index 73162a3a61dd..48da36a15fca 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c | |||
@@ -64,15 +64,15 @@ | |||
64 | extern const struct zoran_format zoran_formats[]; | 64 | extern const struct zoran_format zoran_formats[]; |
65 | 65 | ||
66 | static int card[BUZ_MAX] = { -1, -1, -1, -1 }; | 66 | static int card[BUZ_MAX] = { -1, -1, -1, -1 }; |
67 | module_param_array(card, int, NULL, 0); | 67 | module_param_array(card, int, NULL, 0444); |
68 | MODULE_PARM_DESC(card, "The type of card"); | 68 | MODULE_PARM_DESC(card, "The type of card"); |
69 | 69 | ||
70 | static int encoder[BUZ_MAX] = { -1, -1, -1, -1 }; | 70 | static int encoder[BUZ_MAX] = { -1, -1, -1, -1 }; |
71 | module_param_array(encoder, int, NULL, 0); | 71 | module_param_array(encoder, int, NULL, 0444); |
72 | MODULE_PARM_DESC(encoder, "i2c TV encoder"); | 72 | MODULE_PARM_DESC(encoder, "i2c TV encoder"); |
73 | 73 | ||
74 | static int decoder[BUZ_MAX] = { -1, -1, -1, -1 }; | 74 | static int decoder[BUZ_MAX] = { -1, -1, -1, -1 }; |
75 | module_param_array(decoder, int, NULL, 0); | 75 | module_param_array(decoder, int, NULL, 0444); |
76 | MODULE_PARM_DESC(decoder, "i2c TV decoder"); | 76 | MODULE_PARM_DESC(decoder, "i2c TV decoder"); |
77 | 77 | ||
78 | /* | 78 | /* |
@@ -84,29 +84,31 @@ MODULE_PARM_DESC(decoder, "i2c TV decoder"); | |||
84 | */ | 84 | */ |
85 | 85 | ||
86 | static unsigned long vidmem = 0; /* Video memory base address */ | 86 | static unsigned long vidmem = 0; /* Video memory base address */ |
87 | module_param(vidmem, ulong, 0); | 87 | module_param(vidmem, ulong, 0444); |
88 | MODULE_PARM_DESC(vidmem, "Default video memory base address"); | ||
88 | 89 | ||
89 | /* | 90 | /* |
90 | Default input and video norm at startup of the driver. | 91 | Default input and video norm at startup of the driver. |
91 | */ | 92 | */ |
92 | 93 | ||
93 | static int default_input = 0; /* 0=Composite, 1=S-Video */ | 94 | static unsigned int default_input = 0; /* 0=Composite, 1=S-Video */ |
94 | module_param(default_input, int, 0); | 95 | module_param(default_input, uint, 0444); |
95 | MODULE_PARM_DESC(default_input, | 96 | MODULE_PARM_DESC(default_input, |
96 | "Default input (0=Composite, 1=S-Video, 2=Internal)"); | 97 | "Default input (0=Composite, 1=S-Video, 2=Internal)"); |
97 | 98 | ||
98 | static int default_mux = 1; /* 6 Eyes input selection */ | 99 | static int default_mux = 1; /* 6 Eyes input selection */ |
99 | module_param(default_mux, int, 0); | 100 | module_param(default_mux, int, 0644); |
100 | MODULE_PARM_DESC(default_mux, | 101 | MODULE_PARM_DESC(default_mux, |
101 | "Default 6 Eyes mux setting (Input selection)"); | 102 | "Default 6 Eyes mux setting (Input selection)"); |
102 | 103 | ||
103 | static int default_norm = 0; /* 0=PAL, 1=NTSC 2=SECAM */ | 104 | static int default_norm = 0; /* 0=PAL, 1=NTSC 2=SECAM */ |
104 | module_param(default_norm, int, 0); | 105 | module_param(default_norm, int, 0444); |
105 | MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)"); | 106 | MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)"); |
106 | 107 | ||
107 | static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ | 108 | /* /dev/videoN, -1 for autodetect */ |
108 | module_param(video_nr, int, 0); | 109 | static int video_nr[BUZ_MAX] = {-1, -1, -1, -1}; |
109 | MODULE_PARM_DESC(video_nr, "video device number"); | 110 | module_param_array(video_nr, int, NULL, 0444); |
111 | MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)"); | ||
110 | 112 | ||
111 | /* | 113 | /* |
112 | Number and size of grab buffers for Video 4 Linux | 114 | Number and size of grab buffers for Video 4 Linux |
@@ -127,28 +129,27 @@ MODULE_PARM_DESC(video_nr, "video device number"); | |||
127 | 129 | ||
128 | int v4l_nbufs = 2; | 130 | int v4l_nbufs = 2; |
129 | int v4l_bufsize = 128; /* Everybody should be able to work with this setting */ | 131 | int v4l_bufsize = 128; /* Everybody should be able to work with this setting */ |
130 | module_param(v4l_nbufs, int, 0); | 132 | module_param(v4l_nbufs, int, 0644); |
131 | MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use"); | 133 | MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use"); |
132 | module_param(v4l_bufsize, int, 0); | 134 | module_param(v4l_bufsize, int, 0644); |
133 | MODULE_PARM_DESC(v4l_bufsize, "Maximum size per V4L buffer (in kB)"); | 135 | MODULE_PARM_DESC(v4l_bufsize, "Maximum size per V4L buffer (in kB)"); |
134 | 136 | ||
135 | int jpg_nbufs = 32; | 137 | int jpg_nbufs = 32; |
136 | int jpg_bufsize = 512; /* max size for 100% quality full-PAL frame */ | 138 | int jpg_bufsize = 512; /* max size for 100% quality full-PAL frame */ |
137 | module_param(jpg_nbufs, int, 0); | 139 | module_param(jpg_nbufs, int, 0644); |
138 | MODULE_PARM_DESC(jpg_nbufs, "Maximum number of JPG buffers to use"); | 140 | MODULE_PARM_DESC(jpg_nbufs, "Maximum number of JPG buffers to use"); |
139 | module_param(jpg_bufsize, int, 0); | 141 | module_param(jpg_bufsize, int, 0644); |
140 | MODULE_PARM_DESC(jpg_bufsize, "Maximum size per JPG buffer (in kB)"); | 142 | MODULE_PARM_DESC(jpg_bufsize, "Maximum size per JPG buffer (in kB)"); |
141 | 143 | ||
142 | int pass_through = 0; /* 1=Pass through TV signal when device is not used */ | 144 | int pass_through = 0; /* 1=Pass through TV signal when device is not used */ |
143 | /* 0=Show color bar when device is not used (LML33: only if lml33dpath=1) */ | 145 | /* 0=Show color bar when device is not used (LML33: only if lml33dpath=1) */ |
144 | module_param(pass_through, int, 0); | 146 | module_param(pass_through, int, 0644); |
145 | MODULE_PARM_DESC(pass_through, | 147 | MODULE_PARM_DESC(pass_through, |
146 | "Pass TV signal through to TV-out when idling"); | 148 | "Pass TV signal through to TV-out when idling"); |
147 | 149 | ||
148 | static int debug = 1; | 150 | int zr36067_debug = 1; |
149 | int *zr_debug = &debug; | 151 | module_param_named(debug, zr36067_debug, int, 0644); |
150 | module_param(debug, int, 0); | 152 | MODULE_PARM_DESC(debug, "Debug level (0-5)"); |
151 | MODULE_PARM_DESC(debug, "Debug level (0-4)"); | ||
152 | 153 | ||
153 | MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver"); | 154 | MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver"); |
154 | MODULE_AUTHOR("Serguei Miridonov"); | 155 | MODULE_AUTHOR("Serguei Miridonov"); |
@@ -161,12 +162,6 @@ static struct pci_device_id zr36067_pci_tbl[] = { | |||
161 | }; | 162 | }; |
162 | MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl); | 163 | MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl); |
163 | 164 | ||
164 | #define dprintk(num, format, args...) \ | ||
165 | do { \ | ||
166 | if (*zr_debug >= num) \ | ||
167 | printk(format, ##args); \ | ||
168 | } while (0) | ||
169 | |||
170 | int zoran_num; /* number of Buzs in use */ | 165 | int zoran_num; /* number of Buzs in use */ |
171 | struct zoran zoran[BUZ_MAX]; | 166 | struct zoran zoran[BUZ_MAX]; |
172 | 167 | ||
@@ -1075,7 +1070,7 @@ test_interrupts (struct zoran *zr) | |||
1075 | if (timeout) { | 1070 | if (timeout) { |
1076 | dprintk(1, ": time spent: %d\n", 1 * HZ - timeout); | 1071 | dprintk(1, ": time spent: %d\n", 1 * HZ - timeout); |
1077 | } | 1072 | } |
1078 | if (*zr_debug > 1) | 1073 | if (zr36067_debug > 1) |
1079 | print_interrupts(zr); | 1074 | print_interrupts(zr); |
1080 | btwrite(icr, ZR36057_ICR); | 1075 | btwrite(icr, ZR36057_ICR); |
1081 | } | 1076 | } |
@@ -1121,7 +1116,14 @@ zr36057_init (struct zoran *zr) | |||
1121 | zr->timing = zr->card.tvn[zr->norm]; | 1116 | zr->timing = zr->card.tvn[zr->norm]; |
1122 | } | 1117 | } |
1123 | 1118 | ||
1124 | zr->input = default_input = (default_input ? 1 : 0); | 1119 | if (default_input > zr->card.inputs-1) { |
1120 | dprintk(1, | ||
1121 | KERN_WARNING | ||
1122 | "%s: default_input value %d out of range (0-%d)\n", | ||
1123 | ZR_DEVNAME(zr), default_input, zr->card.inputs-1); | ||
1124 | default_input = 0; | ||
1125 | } | ||
1126 | zr->input = default_input; | ||
1125 | 1127 | ||
1126 | /* Should the following be reset at every open ? */ | 1128 | /* Should the following be reset at every open ? */ |
1127 | zr->hue = 32768; | 1129 | zr->hue = 32768; |
@@ -1153,12 +1155,12 @@ zr36057_init (struct zoran *zr) | |||
1153 | */ | 1155 | */ |
1154 | memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template)); | 1156 | memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template)); |
1155 | strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); | 1157 | strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); |
1156 | err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr); | 1158 | err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]); |
1157 | if (err < 0) | 1159 | if (err < 0) |
1158 | goto exit_unregister; | 1160 | goto exit_unregister; |
1159 | 1161 | ||
1160 | zoran_init_hardware(zr); | 1162 | zoran_init_hardware(zr); |
1161 | if (*zr_debug > 2) | 1163 | if (zr36067_debug > 2) |
1162 | detect_guest_activity(zr); | 1164 | detect_guest_activity(zr); |
1163 | test_interrupts(zr); | 1165 | test_interrupts(zr); |
1164 | if (!pass_through) { | 1166 | if (!pass_through) { |
@@ -1620,7 +1622,7 @@ init_dc10_cards (void) | |||
1620 | } | 1622 | } |
1621 | 1623 | ||
1622 | /* random nonsense */ | 1624 | /* random nonsense */ |
1623 | dprintk(5, KERN_DEBUG "Jotti is een held!\n"); | 1625 | dprintk(6, KERN_DEBUG "Jotti is een held!\n"); |
1624 | 1626 | ||
1625 | /* some mainboards might not do PCI-PCI data transfer well */ | 1627 | /* some mainboards might not do PCI-PCI data transfer well */ |
1626 | if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL|PCIPCI_ALIMAGIK)) { | 1628 | if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL|PCIPCI_ALIMAGIK)) { |
diff --git a/drivers/media/video/zoran_card.h b/drivers/media/video/zoran_card.h index ad997c30bee5..8444ca0a5f3f 100644 --- a/drivers/media/video/zoran_card.h +++ b/drivers/media/video/zoran_card.h | |||
@@ -30,6 +30,14 @@ | |||
30 | #ifndef __ZORAN_CARD_H__ | 30 | #ifndef __ZORAN_CARD_H__ |
31 | #define __ZORAN_CARD_H__ | 31 | #define __ZORAN_CARD_H__ |
32 | 32 | ||
33 | extern int zr36067_debug; | ||
34 | |||
35 | #define dprintk(num, format, args...) \ | ||
36 | do { \ | ||
37 | if (zr36067_debug >= num) \ | ||
38 | printk(format, ##args); \ | ||
39 | } while (0) | ||
40 | |||
33 | /* Anybody who uses more than four? */ | 41 | /* Anybody who uses more than four? */ |
34 | #define BUZ_MAX 4 | 42 | #define BUZ_MAX 4 |
35 | extern int zoran_num; | 43 | extern int zoran_num; |
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index ba2f4ed29483..68c7c505587e 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include "videocodec.h" | 52 | #include "videocodec.h" |
53 | #include "zoran.h" | 53 | #include "zoran.h" |
54 | #include "zoran_device.h" | 54 | #include "zoran_device.h" |
55 | #include "zoran_card.h" | ||
55 | 56 | ||
56 | #define IRQ_MASK ( ZR36057_ISR_GIRQ0 | \ | 57 | #define IRQ_MASK ( ZR36057_ISR_GIRQ0 | \ |
57 | ZR36057_ISR_GIRQ1 | \ | 58 | ZR36057_ISR_GIRQ1 | \ |
@@ -59,14 +60,6 @@ | |||
59 | 60 | ||
60 | extern const struct zoran_format zoran_formats[]; | 61 | extern const struct zoran_format zoran_formats[]; |
61 | 62 | ||
62 | extern int *zr_debug; | ||
63 | |||
64 | #define dprintk(num, format, args...) \ | ||
65 | do { \ | ||
66 | if (*zr_debug >= num) \ | ||
67 | printk(format, ##args); \ | ||
68 | } while (0) | ||
69 | |||
70 | static int lml33dpath = 0; /* 1 will use digital path in capture | 63 | static int lml33dpath = 0; /* 1 will use digital path in capture |
71 | * mode instead of analog. It can be | 64 | * mode instead of analog. It can be |
72 | * used for picture adjustments using | 65 | * used for picture adjustments using |
@@ -76,7 +69,7 @@ static int lml33dpath = 0; /* 1 will use digital path in capture | |||
76 | * load on Bt819 input, there will be | 69 | * load on Bt819 input, there will be |
77 | * some image imperfections */ | 70 | * some image imperfections */ |
78 | 71 | ||
79 | module_param(lml33dpath, bool, 0); | 72 | module_param(lml33dpath, bool, 0644); |
80 | MODULE_PARM_DESC(lml33dpath, | 73 | MODULE_PARM_DESC(lml33dpath, |
81 | "Use digital path capture mode (on LML33 cards)"); | 74 | "Use digital path capture mode (on LML33 cards)"); |
82 | 75 | ||
@@ -174,7 +167,7 @@ post_office_read (struct zoran *zr, | |||
174 | static void | 167 | static void |
175 | dump_guests (struct zoran *zr) | 168 | dump_guests (struct zoran *zr) |
176 | { | 169 | { |
177 | if (*zr_debug > 2) { | 170 | if (zr36067_debug > 2) { |
178 | int i, guest[8]; | 171 | int i, guest[8]; |
179 | 172 | ||
180 | for (i = 1; i < 8; i++) { // Don't read jpeg codec here | 173 | for (i = 1; i < 8; i++) { // Don't read jpeg codec here |
@@ -1271,7 +1264,7 @@ error_handler (struct zoran *zr, | |||
1271 | zr->num_errors++; | 1264 | zr->num_errors++; |
1272 | 1265 | ||
1273 | /* Report error */ | 1266 | /* Report error */ |
1274 | if (*zr_debug > 1 && zr->num_errors <= 8) { | 1267 | if (zr36067_debug > 1 && zr->num_errors <= 8) { |
1275 | long frame; | 1268 | long frame; |
1276 | frame = | 1269 | frame = |
1277 | zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; | 1270 | zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; |
@@ -1531,7 +1524,7 @@ zoran_irq (int irq, | |||
1531 | 1524 | ||
1532 | if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || | 1525 | if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || |
1533 | zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { | 1526 | zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { |
1534 | if (*zr_debug > 1 && | 1527 | if (zr36067_debug > 1 && |
1535 | (!zr->frame_num || zr->JPEG_error)) { | 1528 | (!zr->frame_num || zr->JPEG_error)) { |
1536 | printk(KERN_INFO | 1529 | printk(KERN_INFO |
1537 | "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n", | 1530 | "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n", |
@@ -1568,7 +1561,7 @@ zoran_irq (int irq, | |||
1568 | zr->JPEG_missed; | 1561 | zr->JPEG_missed; |
1569 | } | 1562 | } |
1570 | 1563 | ||
1571 | if (*zr_debug > 2 && zr->frame_num < 6) { | 1564 | if (zr36067_debug > 2 && zr->frame_num < 6) { |
1572 | int i; | 1565 | int i; |
1573 | printk("%s: seq=%ld stat_com:", | 1566 | printk("%s: seq=%ld stat_com:", |
1574 | ZR_DEVNAME(zr), zr->jpg_seq_num); | 1567 | ZR_DEVNAME(zr), zr->jpg_seq_num); |
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 72a037b75d63..1c14fa2bd411 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c | |||
@@ -200,14 +200,6 @@ const struct zoran_format zoran_formats[] = { | |||
200 | // RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined | 200 | // RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined |
201 | 201 | ||
202 | 202 | ||
203 | extern int *zr_debug; | ||
204 | |||
205 | #define dprintk(num, format, args...) \ | ||
206 | do { \ | ||
207 | if (*zr_debug >= num) \ | ||
208 | printk(format, ##args); \ | ||
209 | } while (0) | ||
210 | |||
211 | extern int v4l_nbufs; | 203 | extern int v4l_nbufs; |
212 | extern int v4l_bufsize; | 204 | extern int v4l_bufsize; |
213 | extern int jpg_nbufs; | 205 | extern int jpg_nbufs; |
@@ -215,8 +207,8 @@ extern int jpg_bufsize; | |||
215 | extern int pass_through; | 207 | extern int pass_through; |
216 | 208 | ||
217 | static int lock_norm = 0; /* 1=Don't change TV standard (norm) */ | 209 | static int lock_norm = 0; /* 1=Don't change TV standard (norm) */ |
218 | module_param(lock_norm, int, 0); | 210 | module_param(lock_norm, int, 0644); |
219 | MODULE_PARM_DESC(lock_norm, "Users can't change norm"); | 211 | MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)"); |
220 | 212 | ||
221 | #ifdef CONFIG_VIDEO_V4L2 | 213 | #ifdef CONFIG_VIDEO_V4L2 |
222 | /* small helper function for calculating buffersizes for v4l2 | 214 | /* small helper function for calculating buffersizes for v4l2 |
@@ -347,10 +339,7 @@ v4l_fbuffer_alloc (struct file *file) | |||
347 | if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) { | 339 | if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) { |
348 | /* Use kmalloc */ | 340 | /* Use kmalloc */ |
349 | 341 | ||
350 | mem = | 342 | mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL); |
351 | (unsigned char *) kmalloc(fh->v4l_buffers. | ||
352 | buffer_size, | ||
353 | GFP_KERNEL); | ||
354 | if (mem == 0) { | 343 | if (mem == 0) { |
355 | dprintk(1, | 344 | dprintk(1, |
356 | KERN_ERR | 345 | KERN_ERR |
@@ -1106,12 +1095,10 @@ jpg_sync (struct file *file, | |||
1106 | frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME]; | 1095 | frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME]; |
1107 | 1096 | ||
1108 | /* buffer should now be in BUZ_STATE_DONE */ | 1097 | /* buffer should now be in BUZ_STATE_DONE */ |
1109 | if (*zr_debug > 0) | 1098 | if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE) |
1110 | if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE) | 1099 | dprintk(2, |
1111 | dprintk(2, | 1100 | KERN_ERR "%s: jpg_sync() - internal state error\n", |
1112 | KERN_ERR | 1101 | ZR_DEVNAME(zr)); |
1113 | "%s: jpg_sync() - internal state error\n", | ||
1114 | ZR_DEVNAME(zr)); | ||
1115 | 1102 | ||
1116 | *bs = zr->jpg_buffers.buffer[frame].bs; | 1103 | *bs = zr->jpg_buffers.buffer[frame].bs; |
1117 | bs->frame = frame; | 1104 | bs->frame = frame; |
@@ -1389,7 +1376,7 @@ zoran_close (struct inode *inode, | |||
1389 | /* disable interrupts */ | 1376 | /* disable interrupts */ |
1390 | btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR); | 1377 | btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR); |
1391 | 1378 | ||
1392 | if (*zr_debug > 1) | 1379 | if (zr36067_debug > 1) |
1393 | print_interrupts(zr); | 1380 | print_interrupts(zr); |
1394 | 1381 | ||
1395 | /* Overlay off */ | 1382 | /* Overlay off */ |
@@ -3206,7 +3193,7 @@ zoran_do_ioctl (struct inode *inode, | |||
3206 | "%s: VIDIOC_QUERYBUF - index=%d, type=%d\n", | 3193 | "%s: VIDIOC_QUERYBUF - index=%d, type=%d\n", |
3207 | ZR_DEVNAME(zr), buf->index, buf->type); | 3194 | ZR_DEVNAME(zr), buf->index, buf->type); |
3208 | 3195 | ||
3209 | memset(buf, 0, sizeof(buf)); | 3196 | memset(buf, 0, sizeof(*buf)); |
3210 | buf->type = type; | 3197 | buf->type = type; |
3211 | buf->index = index; | 3198 | buf->index = index; |
3212 | 3199 | ||
diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c index 446ae8d5c3df..328ed6e7ac6a 100644 --- a/drivers/media/video/zoran_procfs.c +++ b/drivers/media/video/zoran_procfs.c | |||
@@ -48,14 +48,7 @@ | |||
48 | #include "videocodec.h" | 48 | #include "videocodec.h" |
49 | #include "zoran.h" | 49 | #include "zoran.h" |
50 | #include "zoran_procfs.h" | 50 | #include "zoran_procfs.h" |
51 | 51 | #include "zoran_card.h" | |
52 | extern int *zr_debug; | ||
53 | |||
54 | #define dprintk(num, format, args...) \ | ||
55 | do { \ | ||
56 | if (*zr_debug >= num) \ | ||
57 | printk(format, ##args); \ | ||
58 | } while (0) | ||
59 | 52 | ||
60 | #ifdef CONFIG_PROC_FS | 53 | #ifdef CONFIG_PROC_FS |
61 | struct procfs_params_zr36067 { | 54 | struct procfs_params_zr36067 { |
diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c index 62f77584fb85..dd084555da8f 100644 --- a/drivers/media/video/zr36016.c +++ b/drivers/media/video/zr36016.c | |||
@@ -38,11 +38,11 @@ | |||
38 | #include<linux/videodev.h> */ | 38 | #include<linux/videodev.h> */ |
39 | 39 | ||
40 | /* I/O commands, error codes */ | 40 | /* I/O commands, error codes */ |
41 | #include<asm/io.h> | 41 | #include <asm/io.h> |
42 | //#include<errno.h> | 42 | //#include<errno.h> |
43 | 43 | ||
44 | /* v4l API */ | 44 | /* v4l API */ |
45 | #include<linux/videodev.h> | 45 | #include <linux/videodev.h> |
46 | 46 | ||
47 | /* headerfile of this module */ | 47 | /* headerfile of this module */ |
48 | #include"zr36016.h" | 48 | #include"zr36016.h" |
diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c index a6bbd125631c..9f622e00c479 100644 --- a/drivers/media/video/zr36050.c +++ b/drivers/media/video/zr36050.c | |||
@@ -38,14 +38,14 @@ | |||
38 | #include<linux/videodev.h> */ | 38 | #include<linux/videodev.h> */ |
39 | 39 | ||
40 | /* I/O commands, error codes */ | 40 | /* I/O commands, error codes */ |
41 | #include<asm/io.h> | 41 | #include <asm/io.h> |
42 | //#include<errno.h> | 42 | //#include<errno.h> |
43 | 43 | ||
44 | /* headerfile of this module */ | 44 | /* headerfile of this module */ |
45 | #include"zr36050.h" | 45 | #include "zr36050.h" |
46 | 46 | ||
47 | /* codec io API */ | 47 | /* codec io API */ |
48 | #include"videocodec.h" | 48 | #include "videocodec.h" |
49 | 49 | ||
50 | /* it doesn't make sense to have more than 20 or so, | 50 | /* it doesn't make sense to have more than 20 or so, |
51 | just to prevent some unwanted loops */ | 51 | just to prevent some unwanted loops */ |
diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c index 97c8f9b9dc12..1ef14fef08e6 100644 --- a/drivers/media/video/zr36060.c +++ b/drivers/media/video/zr36060.c | |||
@@ -38,14 +38,14 @@ | |||
38 | #include<linux/videodev.h> */ | 38 | #include<linux/videodev.h> */ |
39 | 39 | ||
40 | /* I/O commands, error codes */ | 40 | /* I/O commands, error codes */ |
41 | #include<asm/io.h> | 41 | #include <asm/io.h> |
42 | //#include<errno.h> | 42 | //#include<errno.h> |
43 | 43 | ||
44 | /* headerfile of this module */ | 44 | /* headerfile of this module */ |
45 | #include"zr36060.h" | 45 | #include "zr36060.h" |
46 | 46 | ||
47 | /* codec io API */ | 47 | /* codec io API */ |
48 | #include"videocodec.h" | 48 | #include "videocodec.h" |
49 | 49 | ||
50 | /* it doesn't make sense to have more than 20 or so, | 50 | /* it doesn't make sense to have more than 20 or so, |
51 | just to prevent some unwanted loops */ | 51 | just to prevent some unwanted loops */ |
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index b69014865714..a271b67a8e2d 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h | |||
@@ -119,6 +119,7 @@ | |||
119 | #define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */ | 119 | #define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */ |
120 | #define I2C_DRIVERID_WM8753 91 /* Wolfson WM8753 audio codec */ | 120 | #define I2C_DRIVERID_WM8753 91 /* Wolfson WM8753 audio codec */ |
121 | #define I2C_DRIVERID_LM4857 92 /* LM4857 Audio Amplifier */ | 121 | #define I2C_DRIVERID_LM4857 92 /* LM4857 Audio Amplifier */ |
122 | #define I2C_DRIVERID_VP27SMPX 93 /* Panasonic VP27s tuner internal MPX */ | ||
122 | 123 | ||
123 | #define I2C_DRIVERID_I2CDEV 900 | 124 | #define I2C_DRIVERID_I2CDEV 900 |
124 | #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ | 125 | #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ |
@@ -196,6 +197,7 @@ | |||
196 | #define I2C_HW_B_EM28XX 0x01001f /* em28xx video capture cards */ | 197 | #define I2C_HW_B_EM28XX 0x01001f /* em28xx video capture cards */ |
197 | #define I2C_HW_B_CX2341X 0x010020 /* Conexant CX2341X MPEG encoder cards */ | 198 | #define I2C_HW_B_CX2341X 0x010020 /* Conexant CX2341X MPEG encoder cards */ |
198 | #define I2C_HW_B_INTELFB 0x010021 /* intel framebuffer driver */ | 199 | #define I2C_HW_B_INTELFB 0x010021 /* intel framebuffer driver */ |
200 | #define I2C_HW_B_CX23885 0x010022 /* conexant 23885 based tv cards (bus1) */ | ||
199 | 201 | ||
200 | /* --- PCF 8584 based algorithms */ | 202 | /* --- PCF 8584 based algorithms */ |
201 | #define I2C_HW_P_LP 0x020000 /* Parallel port interface */ | 203 | #define I2C_HW_P_LP 0x020000 /* Parallel port interface */ |
diff --git a/include/media/ivtv.h b/include/linux/ivtv.h index 412b48ea8eda..794b8daa9378 100644 --- a/include/media/ivtv.h +++ b/include/linux/ivtv.h | |||
@@ -18,8 +18,15 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef _LINUX_IVTV_H | 21 | #ifndef __LINUX_IVTV_H__ |
22 | #define _LINUX_IVTV_H | 22 | #define __LINUX_IVTV_H__ |
23 | |||
24 | #ifdef __KERNEL__ | ||
25 | #include <linux/compiler.h> /* need __user */ | ||
26 | #else | ||
27 | #define __user | ||
28 | #endif | ||
29 | #include <linux/types.h> | ||
23 | 30 | ||
24 | /* ivtv knows several distinct output modes: MPEG streaming, | 31 | /* ivtv knows several distinct output modes: MPEG streaming, |
25 | YUV streaming, YUV updates through user DMA and the passthrough | 32 | YUV streaming, YUV updates through user DMA and the passthrough |
diff --git a/drivers/media/video/ivtv/ivtv-video.h b/include/linux/ivtvfb.h index c8ade5d3c413..e980ba62ddcc 100644 --- a/drivers/media/video/ivtv/ivtv-video.h +++ b/include/linux/ivtvfb.h | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | saa7127 interface functions | 2 | On Screen Display cx23415 Framebuffer driver |
3 | Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl> | 3 | |
4 | Copyright (C) 2006, 2007 Ian Armstrong <ian@iarmst.demon.co.uk> | ||
4 | 5 | ||
5 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by | 7 | it under the terms of the GNU General Public License as published by |
@@ -17,8 +18,25 @@ | |||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 19 | */ |
19 | 20 | ||
20 | void ivtv_set_wss(struct ivtv *itv, int enabled, int mode); | 21 | #ifndef __LINUX_IVTVFB_H__ |
21 | void ivtv_set_cc(struct ivtv *itv, int mode, u8 cc1, u8 cc2, u8 cc3, u8 cc4); | 22 | #define __LINUX_IVTVFB_H__ |
22 | void ivtv_set_vps(struct ivtv *itv, int enabled, u8 vps1, u8 vps2, u8 vps3, | 23 | |
23 | u8 vps4, u8 vps5); | 24 | #ifdef __KERNEL__ |
24 | void ivtv_video_set_io(struct ivtv *itv); | 25 | #include <linux/compiler.h> /* need __user */ |
26 | #else | ||
27 | #define __user | ||
28 | #endif | ||
29 | #include <linux/types.h> | ||
30 | |||
31 | /* Framebuffer external API */ | ||
32 | |||
33 | struct ivtvfb_dma_frame { | ||
34 | void __user *source; | ||
35 | unsigned long dest_offset; | ||
36 | int count; | ||
37 | }; | ||
38 | |||
39 | #define IVTVFB_IOC_DMA_FRAME _IOW('V', BASE_VIDIOC_PRIVATE+0, struct ivtvfb_dma_frame) | ||
40 | #define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t) | ||
41 | |||
42 | #endif | ||
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index ae9b24c12f6a..1f503e94eff1 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h | |||
@@ -271,6 +271,7 @@ struct v4l2_pix_format | |||
271 | 271 | ||
272 | /* Pixel format FOURCC depth Description */ | 272 | /* Pixel format FOURCC depth Description */ |
273 | #define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R','G','B','1') /* 8 RGB-3-3-2 */ | 273 | #define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R','G','B','1') /* 8 RGB-3-3-2 */ |
274 | #define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R','4','4','4') /* 16 xxxxrrrr ggggbbbb */ | ||
274 | #define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R','G','B','O') /* 16 RGB-5-5-5 */ | 275 | #define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R','G','B','O') /* 16 RGB-5-5-5 */ |
275 | #define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R','G','B','P') /* 16 RGB-5-6-5 */ | 276 | #define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R','G','B','P') /* 16 RGB-5-6-5 */ |
276 | #define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R','G','B','Q') /* 16 RGB-5-5-5 BE */ | 277 | #define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R','G','B','Q') /* 16 RGB-5-5-5 BE */ |
@@ -280,6 +281,7 @@ struct v4l2_pix_format | |||
280 | #define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B','G','R','4') /* 32 BGR-8-8-8-8 */ | 281 | #define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B','G','R','4') /* 32 BGR-8-8-8-8 */ |
281 | #define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R','G','B','4') /* 32 RGB-8-8-8-8 */ | 282 | #define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R','G','B','4') /* 32 RGB-8-8-8-8 */ |
282 | #define V4L2_PIX_FMT_GREY v4l2_fourcc('G','R','E','Y') /* 8 Greyscale */ | 283 | #define V4L2_PIX_FMT_GREY v4l2_fourcc('G','R','E','Y') /* 8 Greyscale */ |
284 | #define V4L2_PIX_FMT_PAL8 v4l2_fourcc('P','A','L','8') /* 8 8-bit palette */ | ||
283 | #define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y','V','U','9') /* 9 YVU 4:1:0 */ | 285 | #define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y','V','U','9') /* 9 YVU 4:1:0 */ |
284 | #define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */ | 286 | #define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */ |
285 | #define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y','U','Y','V') /* 16 YUV 4:2:2 */ | 287 | #define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y','U','Y','V') /* 16 YUV 4:2:2 */ |
@@ -287,6 +289,10 @@ struct v4l2_pix_format | |||
287 | #define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4','2','2','P') /* 16 YVU422 planar */ | 289 | #define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4','2','2','P') /* 16 YVU422 planar */ |
288 | #define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4','1','1','P') /* 16 YVU411 planar */ | 290 | #define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4','1','1','P') /* 16 YVU411 planar */ |
289 | #define V4L2_PIX_FMT_Y41P v4l2_fourcc('Y','4','1','P') /* 12 YUV 4:1:1 */ | 291 | #define V4L2_PIX_FMT_Y41P v4l2_fourcc('Y','4','1','P') /* 12 YUV 4:1:1 */ |
292 | #define V4L2_PIX_FMT_YUV444 v4l2_fourcc('Y','4','4','4') /* 16 xxxxyyyy uuuuvvvv */ | ||
293 | #define V4L2_PIX_FMT_YUV555 v4l2_fourcc('Y','U','V','O') /* 16 YUV-5-5-5 */ | ||
294 | #define V4L2_PIX_FMT_YUV565 v4l2_fourcc('Y','U','V','P') /* 16 YUV-5-6-5 */ | ||
295 | #define V4L2_PIX_FMT_YUV32 v4l2_fourcc('Y','U','V','4') /* 32 YUV-8-8-8-8 */ | ||
290 | 296 | ||
291 | /* two planes -- one Y, one Cr + Cb interleaved */ | 297 | /* two planes -- one Y, one Cr + Cb interleaved */ |
292 | #define V4L2_PIX_FMT_NV12 v4l2_fourcc('N','V','1','2') /* 12 Y/CbCr 4:2:0 */ | 298 | #define V4L2_PIX_FMT_NV12 v4l2_fourcc('N','V','1','2') /* 12 Y/CbCr 4:2:0 */ |
@@ -298,7 +304,6 @@ struct v4l2_pix_format | |||
298 | #define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y','Y','U','V') /* 16 YUV 4:2:2 */ | 304 | #define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y','Y','U','V') /* 16 YUV 4:2:2 */ |
299 | #define V4L2_PIX_FMT_HI240 v4l2_fourcc('H','I','2','4') /* 8 8-bit color */ | 305 | #define V4L2_PIX_FMT_HI240 v4l2_fourcc('H','I','2','4') /* 8 8-bit color */ |
300 | #define V4L2_PIX_FMT_HM12 v4l2_fourcc('H','M','1','2') /* 8 YUV 4:2:0 16x16 macroblocks */ | 306 | #define V4L2_PIX_FMT_HM12 v4l2_fourcc('H','M','1','2') /* 8 YUV 4:2:0 16x16 macroblocks */ |
301 | #define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R','4','4','4') /* 16 xxxxrrrr ggggbbbb */ | ||
302 | 307 | ||
303 | /* see http://www.siliconimaging.com/RGB%20Bayer.htm */ | 308 | /* see http://www.siliconimaging.com/RGB%20Bayer.htm */ |
304 | #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ | 309 | #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ |
diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h index 38c12fed7535..af8071d7620d 100644 --- a/include/media/cx2341x.h +++ b/include/media/cx2341x.h | |||
@@ -91,7 +91,7 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func, | |||
91 | int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, | 91 | int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, |
92 | struct v4l2_queryctrl *qctrl); | 92 | struct v4l2_queryctrl *qctrl); |
93 | const char **cx2341x_ctrl_get_menu(u32 id); | 93 | const char **cx2341x_ctrl_get_menu(u32 id); |
94 | int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, | 94 | int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy, |
95 | struct v4l2_ext_controls *ctrls, unsigned int cmd); | 95 | struct v4l2_ext_controls *ctrls, unsigned int cmd); |
96 | void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p); | 96 | void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p); |
97 | void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix); | 97 | void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix); |
diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 9807a7c15830..7a785fa77212 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h | |||
@@ -140,6 +140,7 @@ extern IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE]; | |||
140 | extern IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE]; | 140 | extern IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE]; |
141 | extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE]; | 141 | extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE]; |
142 | extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE]; | 142 | extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE]; |
143 | extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE]; | ||
143 | 144 | ||
144 | #endif | 145 | #endif |
145 | 146 | ||
diff --git a/include/media/saa7146.h b/include/media/saa7146.h index 67703249b245..cd3ff2c29d5e 100644 --- a/include/media/saa7146.h +++ b/include/media/saa7146.h | |||
@@ -146,7 +146,6 @@ struct saa7146_dev | |||
146 | 146 | ||
147 | /* from saa7146_i2c.c */ | 147 | /* from saa7146_i2c.c */ |
148 | int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate); | 148 | int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate); |
149 | int saa7146_i2c_transfer(struct saa7146_dev *saa, const struct i2c_msg *msgs, int num, int retries); | ||
150 | 149 | ||
151 | /* from saa7146_core.c */ | 150 | /* from saa7146_core.c */ |
152 | extern struct list_head saa7146_devices; | 151 | extern struct list_head saa7146_devices; |
diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h index cce20ed5cf6c..e49f7e156061 100644 --- a/include/media/saa7146_vv.h +++ b/include/media/saa7146_vv.h | |||
@@ -4,7 +4,7 @@ | |||
4 | #include <linux/videodev.h> | 4 | #include <linux/videodev.h> |
5 | #include <media/v4l2-common.h> | 5 | #include <media/v4l2-common.h> |
6 | #include <media/saa7146.h> | 6 | #include <media/saa7146.h> |
7 | #include <media/video-buf.h> | 7 | #include <media/videobuf-dma-sg.h> |
8 | 8 | ||
9 | #define MAX_SAA7146_CAPTURE_BUFFERS 32 /* arbitrary */ | 9 | #define MAX_SAA7146_CAPTURE_BUFFERS 32 /* arbitrary */ |
10 | #define BUFFER_TIMEOUT (HZ/2) /* 0.5 seconds */ | 10 | #define BUFFER_TIMEOUT (HZ/2) /* 0.5 seconds */ |
diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index e5ad3fcfe984..b201371416a0 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h | |||
@@ -79,6 +79,10 @@ struct tuner_params { | |||
79 | /* Select 18% (or according to datasheet 0%) L standard PLL gating, | 79 | /* Select 18% (or according to datasheet 0%) L standard PLL gating, |
80 | vs the driver default of 36%. */ | 80 | vs the driver default of 36%. */ |
81 | unsigned int default_pll_gating_18:1; | 81 | unsigned int default_pll_gating_18:1; |
82 | /* IF to use in radio mode. Tuners with a separate radio IF filter | ||
83 | seem to use 10.7, while those without use 33.3 for PAL/SECAM tuners | ||
84 | and 41.3 for NTSC tuners. 0 = 10.7, 1 = 33.3, 2 = 41.3 */ | ||
85 | unsigned int radio_if:2; | ||
82 | /* Default tda9887 TOP value in dB for the low band. Default is 0. | 86 | /* Default tda9887 TOP value in dB for the low band. Default is 0. |
83 | Range: -16:+15 */ | 87 | Range: -16:+15 */ |
84 | signed int default_top_low:5; | 88 | signed int default_top_low:5; |
diff --git a/include/media/tuner.h b/include/media/tuner.h index 160381c72e4b..c03dceb92605 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h | |||
@@ -146,6 +146,7 @@ extern int tuner_debug; | |||
146 | #define TDA9887_AUTOMUTE (1<<18) | 146 | #define TDA9887_AUTOMUTE (1<<18) |
147 | #define TDA9887_GATING_18 (1<<19) | 147 | #define TDA9887_GATING_18 (1<<19) |
148 | #define TDA9887_GAIN_NORMAL (1<<20) | 148 | #define TDA9887_GAIN_NORMAL (1<<20) |
149 | #define TDA9887_RIF_41_3 (1<<21) /* radio IF1 41.3 vs 33.3 */ | ||
149 | 150 | ||
150 | #ifdef __KERNEL__ | 151 | #ifdef __KERNEL__ |
151 | 152 | ||
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 09d16c4f00f7..8ae42c41dd08 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h | |||
@@ -65,6 +65,9 @@ enum { | |||
65 | V4L2_IDENT_CX23415 = 415, | 65 | V4L2_IDENT_CX23415 = 415, |
66 | V4L2_IDENT_CX23416 = 416, | 66 | V4L2_IDENT_CX23416 = 416, |
67 | 67 | ||
68 | /* module vp27smpx: just ident 2700 */ | ||
69 | V4L2_IDENT_VP27SMPX = 2700, | ||
70 | |||
68 | /* module wm8739: just ident 8739 */ | 71 | /* module wm8739: just ident 8739 */ |
69 | V4L2_IDENT_WM8739 = 8739, | 72 | V4L2_IDENT_WM8739 = 8739, |
70 | 73 | ||
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 17f8f3a2f0a3..e75d5e6c4cea 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h | |||
@@ -23,8 +23,6 @@ | |||
23 | #include <linux/videodev2.h> | 23 | #include <linux/videodev2.h> |
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | #include <linux/fs.h> | ||
27 | |||
28 | #define VIDEO_MAJOR 81 | 26 | #define VIDEO_MAJOR 81 |
29 | /* Minor device allocation */ | 27 | /* Minor device allocation */ |
30 | #define MINOR_VFL_TYPE_GRABBER_MIN 0 | 28 | #define MINOR_VFL_TYPE_GRABBER_MIN 0 |
@@ -88,8 +86,11 @@ struct video_device | |||
88 | /* device ops */ | 86 | /* device ops */ |
89 | const struct file_operations *fops; | 87 | const struct file_operations *fops; |
90 | 88 | ||
89 | /* sysfs */ | ||
90 | struct device class_dev; /* v4l device */ | ||
91 | struct device *dev; /* device parent */ | ||
92 | |||
91 | /* device info */ | 93 | /* device info */ |
92 | struct device *dev; | ||
93 | char name[32]; | 94 | char name[32]; |
94 | int type; /* v4l1 */ | 95 | int type; /* v4l1 */ |
95 | int type2; /* v4l2 */ | 96 | int type2; /* v4l2 */ |
@@ -334,7 +335,6 @@ void *priv; | |||
334 | /* for videodev.c intenal usage -- please don't touch */ | 335 | /* for videodev.c intenal usage -- please don't touch */ |
335 | int users; /* video_exclusive_{open|close} ... */ | 336 | int users; /* video_exclusive_{open|close} ... */ |
336 | struct mutex lock; /* ... helper function uses these */ | 337 | struct mutex lock; /* ... helper function uses these */ |
337 | struct class_device class_dev; /* sysfs */ | ||
338 | }; | 338 | }; |
339 | 339 | ||
340 | /* Class-dev to video-device */ | 340 | /* Class-dev to video-device */ |
@@ -362,18 +362,18 @@ extern int video_usercopy(struct inode *inode, struct file *file, | |||
362 | 362 | ||
363 | static inline int __must_check | 363 | static inline int __must_check |
364 | video_device_create_file(struct video_device *vfd, | 364 | video_device_create_file(struct video_device *vfd, |
365 | struct class_device_attribute *attr) | 365 | struct device_attribute *attr) |
366 | { | 366 | { |
367 | int ret = class_device_create_file(&vfd->class_dev, attr); | 367 | int ret = device_create_file(&vfd->class_dev, attr); |
368 | if (ret < 0) | 368 | if (ret < 0) |
369 | printk(KERN_WARNING "%s error: %d\n", __FUNCTION__, ret); | 369 | printk(KERN_WARNING "%s error: %d\n", __FUNCTION__, ret); |
370 | return ret; | 370 | return ret; |
371 | } | 371 | } |
372 | static inline void | 372 | static inline void |
373 | video_device_remove_file(struct video_device *vfd, | 373 | video_device_remove_file(struct video_device *vfd, |
374 | struct class_device_attribute *attr) | 374 | struct device_attribute *attr) |
375 | { | 375 | { |
376 | class_device_remove_file(&vfd->class_dev, attr); | 376 | device_remove_file(&vfd->class_dev, attr); |
377 | } | 377 | } |
378 | 378 | ||
379 | #endif /* CONFIG_VIDEO_V4L1_COMPAT */ | 379 | #endif /* CONFIG_VIDEO_V4L1_COMPAT */ |
diff --git a/include/media/v4l2-int-device.h b/include/media/v4l2-int-device.h new file mode 100644 index 000000000000..066ebfc4f983 --- /dev/null +++ b/include/media/v4l2-int-device.h | |||
@@ -0,0 +1,278 @@ | |||
1 | /* | ||
2 | * include/media/v4l2-int-device.h | ||
3 | * | ||
4 | * V4L2 internal ioctl interface. | ||
5 | * | ||
6 | * Copyright (C) 2007 Nokia Corporation. | ||
7 | * | ||
8 | * Contact: Sakari Ailus <sakari.ailus@nokia.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
22 | * 02110-1301 USA | ||
23 | */ | ||
24 | |||
25 | #ifndef V4L2_INT_DEVICE_H | ||
26 | #define V4L2_INT_DEVICE_H | ||
27 | |||
28 | #include <linux/module.h> | ||
29 | #include <media/v4l2-common.h> | ||
30 | |||
31 | #define V4L2NAMESIZE 32 | ||
32 | |||
33 | /* | ||
34 | * | ||
35 | * The internal V4L2 device interface core. | ||
36 | * | ||
37 | */ | ||
38 | |||
39 | enum v4l2_int_type { | ||
40 | v4l2_int_type_master = 1, | ||
41 | v4l2_int_type_slave | ||
42 | }; | ||
43 | |||
44 | struct v4l2_int_device; | ||
45 | |||
46 | struct v4l2_int_master { | ||
47 | int (*attach)(struct v4l2_int_device *master, | ||
48 | struct v4l2_int_device *slave); | ||
49 | void (*detach)(struct v4l2_int_device *master); | ||
50 | }; | ||
51 | |||
52 | typedef int (v4l2_int_ioctl_func)(struct v4l2_int_device *); | ||
53 | typedef int (v4l2_int_ioctl_func_0)(struct v4l2_int_device *); | ||
54 | typedef int (v4l2_int_ioctl_func_1)(struct v4l2_int_device *, void *); | ||
55 | |||
56 | struct v4l2_int_ioctl_desc { | ||
57 | int num; | ||
58 | v4l2_int_ioctl_func *func; | ||
59 | }; | ||
60 | |||
61 | struct v4l2_int_slave { | ||
62 | /* Don't touch master. */ | ||
63 | struct v4l2_int_device *master; | ||
64 | |||
65 | char attach_to[V4L2NAMESIZE]; | ||
66 | |||
67 | int num_ioctls; | ||
68 | struct v4l2_int_ioctl_desc *ioctls; | ||
69 | }; | ||
70 | |||
71 | struct v4l2_int_device { | ||
72 | /* Don't touch head. */ | ||
73 | struct list_head head; | ||
74 | |||
75 | struct module *module; | ||
76 | |||
77 | char name[V4L2NAMESIZE]; | ||
78 | |||
79 | enum v4l2_int_type type; | ||
80 | union { | ||
81 | struct v4l2_int_master *master; | ||
82 | struct v4l2_int_slave *slave; | ||
83 | } u; | ||
84 | |||
85 | void *priv; | ||
86 | }; | ||
87 | |||
88 | int v4l2_int_device_register(struct v4l2_int_device *d); | ||
89 | void v4l2_int_device_unregister(struct v4l2_int_device *d); | ||
90 | |||
91 | int v4l2_int_ioctl_0(struct v4l2_int_device *d, int cmd); | ||
92 | int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg); | ||
93 | |||
94 | /* | ||
95 | * | ||
96 | * Types and definitions for IOCTL commands. | ||
97 | * | ||
98 | */ | ||
99 | |||
100 | /* Slave interface type. */ | ||
101 | enum v4l2_if_type { | ||
102 | /* | ||
103 | * Parallel 8-, 10- or 12-bit interface, used by for example | ||
104 | * on certain image sensors. | ||
105 | */ | ||
106 | V4L2_IF_TYPE_BT656, | ||
107 | }; | ||
108 | |||
109 | enum v4l2_if_type_bt656_mode { | ||
110 | /* | ||
111 | * Modes without Bt synchronisation codes. Separate | ||
112 | * synchronisation signal lines are used. | ||
113 | */ | ||
114 | V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT, | ||
115 | V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT, | ||
116 | V4L2_IF_TYPE_BT656_MODE_NOBT_12BIT, | ||
117 | /* | ||
118 | * Use Bt synchronisation codes. The vertical and horizontal | ||
119 | * synchronisation is done based on synchronisation codes. | ||
120 | */ | ||
121 | V4L2_IF_TYPE_BT656_MODE_BT_8BIT, | ||
122 | V4L2_IF_TYPE_BT656_MODE_BT_10BIT, | ||
123 | }; | ||
124 | |||
125 | struct v4l2_if_type_bt656 { | ||
126 | /* | ||
127 | * 0: Frame begins when vsync is high. | ||
128 | * 1: Frame begins when vsync changes from low to high. | ||
129 | */ | ||
130 | unsigned frame_start_on_rising_vs:1; | ||
131 | /* Use Bt synchronisation codes for sync correction. */ | ||
132 | unsigned bt_sync_correct:1; | ||
133 | /* Swap every two adjacent image data elements. */ | ||
134 | unsigned swap:1; | ||
135 | /* Inverted latch clock polarity from slave. */ | ||
136 | unsigned latch_clk_inv:1; | ||
137 | /* Hs polarity. 0 is active high, 1 active low. */ | ||
138 | unsigned nobt_hs_inv:1; | ||
139 | /* Vs polarity. 0 is active high, 1 active low. */ | ||
140 | unsigned nobt_vs_inv:1; | ||
141 | enum v4l2_if_type_bt656_mode mode; | ||
142 | /* Minimum accepted bus clock for slave (in Hz). */ | ||
143 | u32 clock_min; | ||
144 | /* Maximum accepted bus clock for slave. */ | ||
145 | u32 clock_max; | ||
146 | /* | ||
147 | * Current wish of the slave. May only change in response to | ||
148 | * ioctls that affect image capture. | ||
149 | */ | ||
150 | u32 clock_curr; | ||
151 | }; | ||
152 | |||
153 | struct v4l2_ifparm { | ||
154 | enum v4l2_if_type if_type; | ||
155 | union { | ||
156 | struct v4l2_if_type_bt656 bt656; | ||
157 | } u; | ||
158 | }; | ||
159 | |||
160 | /* IOCTL command numbers. */ | ||
161 | enum v4l2_int_ioctl_num { | ||
162 | /* | ||
163 | * | ||
164 | * "Proper" V4L ioctls, as in struct video_device. | ||
165 | * | ||
166 | */ | ||
167 | vidioc_int_enum_fmt_cap_num = 1, | ||
168 | vidioc_int_g_fmt_cap_num, | ||
169 | vidioc_int_s_fmt_cap_num, | ||
170 | vidioc_int_try_fmt_cap_num, | ||
171 | vidioc_int_queryctrl_num, | ||
172 | vidioc_int_g_ctrl_num, | ||
173 | vidioc_int_s_ctrl_num, | ||
174 | vidioc_int_g_parm_num, | ||
175 | vidioc_int_s_parm_num, | ||
176 | |||
177 | /* | ||
178 | * | ||
179 | * Strictly internal ioctls. | ||
180 | * | ||
181 | */ | ||
182 | /* Initialise the device when slave attaches to the master. */ | ||
183 | vidioc_int_dev_init_num = 1000, | ||
184 | /* Delinitialise the device at slave detach. */ | ||
185 | vidioc_int_dev_exit_num, | ||
186 | /* Set device power state: 0 is off, non-zero is on. */ | ||
187 | vidioc_int_s_power_num, | ||
188 | /* Get slave interface parameters. */ | ||
189 | vidioc_int_g_ifparm_num, | ||
190 | /* Does the slave need to be reset after VIDIOC_DQBUF? */ | ||
191 | vidioc_int_g_needs_reset_num, | ||
192 | |||
193 | /* | ||
194 | * | ||
195 | * VIDIOC_INT_* ioctls. | ||
196 | * | ||
197 | */ | ||
198 | /* VIDIOC_INT_RESET */ | ||
199 | vidioc_int_reset_num, | ||
200 | /* VIDIOC_INT_INIT */ | ||
201 | vidioc_int_init_num, | ||
202 | /* VIDIOC_INT_G_CHIP_IDENT */ | ||
203 | vidioc_int_g_chip_ident_num, | ||
204 | |||
205 | /* | ||
206 | * | ||
207 | * Start of private ioctls. | ||
208 | * | ||
209 | */ | ||
210 | vidioc_int_priv_start_num = 2000, | ||
211 | }; | ||
212 | |||
213 | /* | ||
214 | * | ||
215 | * IOCTL wrapper functions for better type checking. | ||
216 | * | ||
217 | */ | ||
218 | |||
219 | #define V4L2_INT_WRAPPER_0(name) \ | ||
220 | static inline int vidioc_int_##name(struct v4l2_int_device *d) \ | ||
221 | { \ | ||
222 | return v4l2_int_ioctl_0(d, vidioc_int_##name##_num); \ | ||
223 | } \ | ||
224 | \ | ||
225 | static inline struct v4l2_int_ioctl_desc \ | ||
226 | vidioc_int_##name##_cb(int (*func) \ | ||
227 | (struct v4l2_int_device *)) \ | ||
228 | { \ | ||
229 | struct v4l2_int_ioctl_desc desc; \ | ||
230 | \ | ||
231 | desc.num = vidioc_int_##name##_num; \ | ||
232 | desc.func = (v4l2_int_ioctl_func *)func; \ | ||
233 | \ | ||
234 | return desc; \ | ||
235 | } | ||
236 | |||
237 | #define V4L2_INT_WRAPPER_1(name, arg_type, asterisk) \ | ||
238 | static inline int vidioc_int_##name(struct v4l2_int_device *d, \ | ||
239 | arg_type asterisk arg) \ | ||
240 | { \ | ||
241 | return v4l2_int_ioctl_1(d, vidioc_int_##name##_num, \ | ||
242 | (void *)(unsigned long)arg); \ | ||
243 | } \ | ||
244 | \ | ||
245 | static inline struct v4l2_int_ioctl_desc \ | ||
246 | vidioc_int_##name##_cb(int (*func) \ | ||
247 | (struct v4l2_int_device *, \ | ||
248 | arg_type asterisk)) \ | ||
249 | { \ | ||
250 | struct v4l2_int_ioctl_desc desc; \ | ||
251 | \ | ||
252 | desc.num = vidioc_int_##name##_num; \ | ||
253 | desc.func = (v4l2_int_ioctl_func *)func; \ | ||
254 | \ | ||
255 | return desc; \ | ||
256 | } | ||
257 | |||
258 | V4L2_INT_WRAPPER_1(enum_fmt_cap, struct v4l2_fmtdesc, *); | ||
259 | V4L2_INT_WRAPPER_1(g_fmt_cap, struct v4l2_format, *); | ||
260 | V4L2_INT_WRAPPER_1(s_fmt_cap, struct v4l2_format, *); | ||
261 | V4L2_INT_WRAPPER_1(try_fmt_cap, struct v4l2_format, *); | ||
262 | V4L2_INT_WRAPPER_1(queryctrl, struct v4l2_queryctrl, *); | ||
263 | V4L2_INT_WRAPPER_1(g_ctrl, struct v4l2_control, *); | ||
264 | V4L2_INT_WRAPPER_1(s_ctrl, struct v4l2_control, *); | ||
265 | V4L2_INT_WRAPPER_1(g_parm, struct v4l2_streamparm, *); | ||
266 | V4L2_INT_WRAPPER_1(s_parm, struct v4l2_streamparm, *); | ||
267 | |||
268 | V4L2_INT_WRAPPER_0(dev_init); | ||
269 | V4L2_INT_WRAPPER_0(dev_exit); | ||
270 | V4L2_INT_WRAPPER_1(s_power, int, ); | ||
271 | V4L2_INT_WRAPPER_1(g_ifparm, struct v4l2_ifparm, *); | ||
272 | V4L2_INT_WRAPPER_1(g_needs_reset, void, *); | ||
273 | |||
274 | V4L2_INT_WRAPPER_0(reset); | ||
275 | V4L2_INT_WRAPPER_0(init); | ||
276 | V4L2_INT_WRAPPER_1(g_chip_ident, int, *); | ||
277 | |||
278 | #endif | ||
diff --git a/include/media/video-buf.h b/include/media/videobuf-core.h index d6f079476db3..9fa09fb800a1 100644 --- a/include/media/video-buf.h +++ b/include/media/videobuf-core.h | |||
@@ -1,48 +1,26 @@ | |||
1 | /* | 1 | /* |
2 | * generic helper functions for handling video4linux capture buffers | ||
2 | * | 3 | * |
3 | * generic helper functions for video4linux capture buffers, to handle | 4 | * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org> |
4 | * memory management and PCI DMA. | ||
5 | * Right now, bttv, saa7134, saa7146 and cx88 use it. | ||
6 | * | ||
7 | * The functions expect the hardware being able to scatter gatter | ||
8 | * (i.e. the buffers are not linear in physical memory, but fragmented | ||
9 | * into PAGE_SIZE chunks). They also assume the driver does not need | ||
10 | * to touch the video data. | ||
11 | * | ||
12 | * device specific map/unmap/sync stuff now are mapped as file operations | ||
13 | * to allow its usage by USB and virtual devices. | ||
14 | * | 5 | * |
6 | * Highly based on video-buf written originally by: | ||
15 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> | 7 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> |
16 | * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org> | 8 | * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org> |
17 | * (c) 2006 Ted Walther and John Sokol | 9 | * (c) 2006 Ted Walther and John Sokol |
18 | * | 10 | * |
19 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
20 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
21 | * the Free Software Foundation; either version 2 of the License, or | 13 | * the Free Software Foundation; either version 2 |
22 | * (at your option) any later version. | ||
23 | */ | 14 | */ |
24 | 15 | ||
25 | #include <linux/videodev2.h> | ||
26 | #include <linux/poll.h> | 16 | #include <linux/poll.h> |
17 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
18 | #include <linux/videodev.h> | ||
19 | #endif | ||
20 | #include <linux/videodev2.h> | ||
27 | 21 | ||
28 | #define UNSET (-1U) | 22 | #define UNSET (-1U) |
29 | 23 | ||
30 | /* --------------------------------------------------------------------- */ | ||
31 | |||
32 | /* | ||
33 | * Return a scatterlist for some page-aligned vmalloc()'ed memory | ||
34 | * block (NULL on errors). Memory for the scatterlist is allocated | ||
35 | * using kmalloc. The caller must free the memory. | ||
36 | */ | ||
37 | struct scatterlist* videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages); | ||
38 | |||
39 | /* | ||
40 | * Return a scatterlist for a an array of userpages (NULL on errors). | ||
41 | * Memory for the scatterlist is allocated using kmalloc. The caller | ||
42 | * must free the memory. | ||
43 | */ | ||
44 | struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages, | ||
45 | int offset); | ||
46 | 24 | ||
47 | struct videobuf_buffer; | 25 | struct videobuf_buffer; |
48 | struct videobuf_queue; | 26 | struct videobuf_queue; |
@@ -50,69 +28,6 @@ struct videobuf_queue; | |||
50 | /* --------------------------------------------------------------------- */ | 28 | /* --------------------------------------------------------------------- */ |
51 | 29 | ||
52 | /* | 30 | /* |
53 | * A small set of helper functions to manage buffers (both userland | ||
54 | * and kernel) for DMA. | ||
55 | * | ||
56 | * videobuf_dma_init_*() | ||
57 | * creates a buffer. The userland version takes a userspace | ||
58 | * pointer + length. The kernel version just wants the size and | ||
59 | * does memory allocation too using vmalloc_32(). | ||
60 | * | ||
61 | * videobuf_dma_*() | ||
62 | * see Documentation/DMA-mapping.txt, these functions to | ||
63 | * basically the same. The map function does also build a | ||
64 | * scatterlist for the buffer (and unmap frees it ...) | ||
65 | * | ||
66 | * videobuf_dma_free() | ||
67 | * no comment ... | ||
68 | * | ||
69 | */ | ||
70 | |||
71 | struct videobuf_dmabuf { | ||
72 | u32 magic; | ||
73 | |||
74 | /* for userland buffer */ | ||
75 | int offset; | ||
76 | struct page **pages; | ||
77 | |||
78 | /* for kernel buffers */ | ||
79 | void *vmalloc; | ||
80 | |||
81 | /* Stores the userspace pointer to vmalloc area */ | ||
82 | void *varea; | ||
83 | |||
84 | /* for overlay buffers (pci-pci dma) */ | ||
85 | dma_addr_t bus_addr; | ||
86 | |||
87 | /* common */ | ||
88 | struct scatterlist *sglist; | ||
89 | int sglen; | ||
90 | int nr_pages; | ||
91 | int direction; | ||
92 | }; | ||
93 | |||
94 | void videobuf_dma_init(struct videobuf_dmabuf *dma); | ||
95 | int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, | ||
96 | unsigned long data, unsigned long size); | ||
97 | int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, | ||
98 | int nr_pages); | ||
99 | int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, | ||
100 | dma_addr_t addr, int nr_pages); | ||
101 | int videobuf_dma_free(struct videobuf_dmabuf *dma); | ||
102 | |||
103 | int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma); | ||
104 | int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma); | ||
105 | int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma); | ||
106 | |||
107 | /*FIXME: these variants are used only on *-alsa code, where videobuf is | ||
108 | * used without queue | ||
109 | */ | ||
110 | int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma); | ||
111 | int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma); | ||
112 | |||
113 | /* --------------------------------------------------------------------- */ | ||
114 | |||
115 | /* | ||
116 | * A small set of helper functions to manage video4linux buffers. | 31 | * A small set of helper functions to manage video4linux buffers. |
117 | * | 32 | * |
118 | * struct videobuf_buffer holds the data structures used by the helper | 33 | * struct videobuf_buffer holds the data structures used by the helper |
@@ -162,26 +77,33 @@ struct videobuf_buffer { | |||
162 | unsigned int input; | 77 | unsigned int input; |
163 | enum v4l2_field field; | 78 | enum v4l2_field field; |
164 | enum videobuf_state state; | 79 | enum videobuf_state state; |
165 | struct videobuf_dmabuf dma; | ||
166 | struct list_head stream; /* QBUF/DQBUF list */ | 80 | struct list_head stream; /* QBUF/DQBUF list */ |
167 | 81 | ||
168 | /* for mmap'ed buffers */ | ||
169 | enum v4l2_memory memory; | ||
170 | size_t boff; /* buffer offset (mmap + overlay) */ | ||
171 | size_t bsize; /* buffer size */ | ||
172 | unsigned long baddr; /* buffer addr (userland ptr!) */ | ||
173 | struct videobuf_mapping *map; | ||
174 | |||
175 | /* touched by irq handler */ | 82 | /* touched by irq handler */ |
176 | struct list_head queue; | 83 | struct list_head queue; |
177 | wait_queue_head_t done; | 84 | wait_queue_head_t done; |
178 | unsigned int field_count; | 85 | unsigned int field_count; |
179 | struct timeval ts; | 86 | struct timeval ts; |
180 | }; | ||
181 | 87 | ||
182 | typedef int (vb_map_sg_t)(void *dev,struct scatterlist *sglist,int nr_pages, | 88 | /* Memory type */ |
183 | int direction); | 89 | enum v4l2_memory memory; |
90 | |||
91 | /* buffer size */ | ||
92 | size_t bsize; | ||
93 | |||
94 | /* buffer offset (mmap + overlay) */ | ||
95 | size_t boff; | ||
184 | 96 | ||
97 | /* buffer addr (userland ptr!) */ | ||
98 | unsigned long baddr; | ||
99 | |||
100 | /* for mmap'ed buffers */ | ||
101 | struct videobuf_mapping *map; | ||
102 | |||
103 | /* Private pointer to allow specific methods to store their data */ | ||
104 | int privsize; | ||
105 | void *priv; | ||
106 | }; | ||
185 | 107 | ||
186 | struct videobuf_queue_ops { | 108 | struct videobuf_queue_ops { |
187 | int (*buf_setup)(struct videobuf_queue *q, | 109 | int (*buf_setup)(struct videobuf_queue *q, |
@@ -193,14 +115,37 @@ struct videobuf_queue_ops { | |||
193 | struct videobuf_buffer *vb); | 115 | struct videobuf_buffer *vb); |
194 | void (*buf_release)(struct videobuf_queue *q, | 116 | void (*buf_release)(struct videobuf_queue *q, |
195 | struct videobuf_buffer *vb); | 117 | struct videobuf_buffer *vb); |
118 | }; | ||
196 | 119 | ||
197 | /* Helper operations - device dependent. | 120 | #define MAGIC_QTYPE_OPS 0x12261003 |
198 | * If null, videobuf_init defaults all to PCI handling | 121 | |
199 | */ | 122 | /* Helper operations - device type dependent */ |
123 | struct videobuf_qtype_ops { | ||
124 | u32 magic; | ||
200 | 125 | ||
201 | vb_map_sg_t *vb_map_sg; | 126 | void* (*alloc) (size_t size); |
202 | vb_map_sg_t *vb_dma_sync_sg; | 127 | int (*iolock) (struct videobuf_queue* q, |
203 | vb_map_sg_t *vb_unmap_sg; | 128 | struct videobuf_buffer *vb, |
129 | struct v4l2_framebuffer *fbuf); | ||
130 | int (*mmap) (struct videobuf_queue *q, | ||
131 | unsigned int *count, | ||
132 | unsigned int *size, | ||
133 | enum v4l2_memory memory); | ||
134 | int (*sync) (struct videobuf_queue* q, | ||
135 | struct videobuf_buffer *buf); | ||
136 | int (*copy_to_user) (struct videobuf_queue *q, | ||
137 | char __user *data, | ||
138 | size_t count, | ||
139 | int nonblocking); | ||
140 | int (*copy_stream) (struct videobuf_queue *q, | ||
141 | char __user *data, | ||
142 | size_t count, | ||
143 | size_t pos, | ||
144 | int vbihack, | ||
145 | int nonblocking); | ||
146 | int (*mmap_free) (struct videobuf_queue *q); | ||
147 | int (*mmap_mapper) (struct videobuf_queue *q, | ||
148 | struct vm_area_struct *vma); | ||
204 | }; | 149 | }; |
205 | 150 | ||
206 | struct videobuf_queue { | 151 | struct videobuf_queue { |
@@ -215,6 +160,7 @@ struct videobuf_queue { | |||
215 | enum v4l2_field last; /* for field=V4L2_FIELD_ALTERNATE */ | 160 | enum v4l2_field last; /* for field=V4L2_FIELD_ALTERNATE */ |
216 | struct videobuf_buffer *bufs[VIDEO_MAX_FRAME]; | 161 | struct videobuf_buffer *bufs[VIDEO_MAX_FRAME]; |
217 | struct videobuf_queue_ops *ops; | 162 | struct videobuf_queue_ops *ops; |
163 | struct videobuf_qtype_ops *int_ops; | ||
218 | 164 | ||
219 | /* capture via mmap() + ioctl(QBUF/DQBUF) */ | 165 | /* capture via mmap() + ioctl(QBUF/DQBUF) */ |
220 | unsigned int streaming; | 166 | unsigned int streaming; |
@@ -229,28 +175,25 @@ struct videobuf_queue { | |||
229 | void *priv_data; | 175 | void *priv_data; |
230 | }; | 176 | }; |
231 | 177 | ||
232 | void* videobuf_alloc(unsigned int size); | ||
233 | int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); | 178 | int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); |
234 | int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, | 179 | int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, |
235 | struct v4l2_framebuffer *fbuf); | 180 | struct v4l2_framebuffer *fbuf); |
236 | 181 | ||
237 | /* Maps fops to PCI stuff */ | 182 | void *videobuf_alloc(struct videobuf_queue* q); |
238 | void videobuf_queue_pci(struct videobuf_queue* q); | ||
239 | 183 | ||
240 | void videobuf_queue_init(struct videobuf_queue *q, | 184 | void videobuf_queue_core_init(struct videobuf_queue *q, |
241 | struct videobuf_queue_ops *ops, | 185 | struct videobuf_queue_ops *ops, |
242 | void *dev, | 186 | void *dev, |
243 | spinlock_t *irqlock, | 187 | spinlock_t *irqlock, |
244 | enum v4l2_buf_type type, | 188 | enum v4l2_buf_type type, |
245 | enum v4l2_field field, | 189 | enum v4l2_field field, |
246 | unsigned int msize, | 190 | unsigned int msize, |
247 | void *priv); | 191 | void *priv, |
192 | struct videobuf_qtype_ops *int_ops); | ||
248 | int videobuf_queue_is_busy(struct videobuf_queue *q); | 193 | int videobuf_queue_is_busy(struct videobuf_queue *q); |
249 | void videobuf_queue_cancel(struct videobuf_queue *q); | 194 | void videobuf_queue_cancel(struct videobuf_queue *q); |
250 | 195 | ||
251 | enum v4l2_field videobuf_next_field(struct videobuf_queue *q); | 196 | enum v4l2_field videobuf_next_field(struct videobuf_queue *q); |
252 | void videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb, | ||
253 | enum v4l2_buf_type type); | ||
254 | int videobuf_reqbufs(struct videobuf_queue *q, | 197 | int videobuf_reqbufs(struct videobuf_queue *q, |
255 | struct v4l2_requestbuffers *req); | 198 | struct v4l2_requestbuffers *req); |
256 | int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b); | 199 | int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b); |
@@ -258,6 +201,10 @@ int videobuf_qbuf(struct videobuf_queue *q, | |||
258 | struct v4l2_buffer *b); | 201 | struct v4l2_buffer *b); |
259 | int videobuf_dqbuf(struct videobuf_queue *q, | 202 | int videobuf_dqbuf(struct videobuf_queue *q, |
260 | struct v4l2_buffer *b, int nonblocking); | 203 | struct v4l2_buffer *b, int nonblocking); |
204 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
205 | int videobuf_cgmbuf(struct videobuf_queue *q, | ||
206 | struct video_mbuf *mbuf, int count); | ||
207 | #endif | ||
261 | int videobuf_streamon(struct videobuf_queue *q); | 208 | int videobuf_streamon(struct videobuf_queue *q); |
262 | int videobuf_streamoff(struct videobuf_queue *q); | 209 | int videobuf_streamoff(struct videobuf_queue *q); |
263 | 210 | ||
diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h new file mode 100644 index 000000000000..38105031db23 --- /dev/null +++ b/include/media/videobuf-dma-sg.h | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * helper functions for PCI DMA video4linux capture buffers | ||
3 | * | ||
4 | * The functions expect the hardware being able to scatter gatter | ||
5 | * (i.e. the buffers are not linear in physical memory, but fragmented | ||
6 | * into PAGE_SIZE chunks). They also assume the driver does not need | ||
7 | * to touch the video data. | ||
8 | * | ||
9 | * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org> | ||
10 | * | ||
11 | * Highly based on video-buf written originally by: | ||
12 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> | ||
13 | * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org> | ||
14 | * (c) 2006 Ted Walther and John Sokol | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 | ||
19 | */ | ||
20 | |||
21 | #include <media/videobuf-core.h> | ||
22 | |||
23 | /* --------------------------------------------------------------------- */ | ||
24 | |||
25 | /* | ||
26 | * Return a scatterlist for some page-aligned vmalloc()'ed memory | ||
27 | * block (NULL on errors). Memory for the scatterlist is allocated | ||
28 | * using kmalloc. The caller must free the memory. | ||
29 | */ | ||
30 | struct scatterlist* videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages); | ||
31 | |||
32 | /* | ||
33 | * Return a scatterlist for a an array of userpages (NULL on errors). | ||
34 | * Memory for the scatterlist is allocated using kmalloc. The caller | ||
35 | * must free the memory. | ||
36 | */ | ||
37 | struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages, | ||
38 | int offset); | ||
39 | |||
40 | /* --------------------------------------------------------------------- */ | ||
41 | |||
42 | /* | ||
43 | * A small set of helper functions to manage buffers (both userland | ||
44 | * and kernel) for DMA. | ||
45 | * | ||
46 | * videobuf_dma_init_*() | ||
47 | * creates a buffer. The userland version takes a userspace | ||
48 | * pointer + length. The kernel version just wants the size and | ||
49 | * does memory allocation too using vmalloc_32(). | ||
50 | * | ||
51 | * videobuf_dma_*() | ||
52 | * see Documentation/DMA-mapping.txt, these functions to | ||
53 | * basically the same. The map function does also build a | ||
54 | * scatterlist for the buffer (and unmap frees it ...) | ||
55 | * | ||
56 | * videobuf_dma_free() | ||
57 | * no comment ... | ||
58 | * | ||
59 | */ | ||
60 | |||
61 | struct videobuf_dmabuf { | ||
62 | u32 magic; | ||
63 | |||
64 | /* for userland buffer */ | ||
65 | int offset; | ||
66 | struct page **pages; | ||
67 | |||
68 | /* for kernel buffers */ | ||
69 | void *vmalloc; | ||
70 | |||
71 | /* Stores the userspace pointer to vmalloc area */ | ||
72 | void *varea; | ||
73 | |||
74 | /* for overlay buffers (pci-pci dma) */ | ||
75 | dma_addr_t bus_addr; | ||
76 | |||
77 | /* common */ | ||
78 | struct scatterlist *sglist; | ||
79 | int sglen; | ||
80 | int nr_pages; | ||
81 | int direction; | ||
82 | }; | ||
83 | |||
84 | struct videbuf_pci_sg_memory | ||
85 | { | ||
86 | u32 magic; | ||
87 | |||
88 | /* for mmap'ed buffers */ | ||
89 | struct videobuf_dmabuf dma; | ||
90 | }; | ||
91 | |||
92 | void videobuf_dma_init(struct videobuf_dmabuf *dma); | ||
93 | int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, | ||
94 | unsigned long data, unsigned long size); | ||
95 | int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, | ||
96 | int nr_pages); | ||
97 | int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, | ||
98 | dma_addr_t addr, int nr_pages); | ||
99 | int videobuf_dma_free(struct videobuf_dmabuf *dma); | ||
100 | |||
101 | int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma); | ||
102 | int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma); | ||
103 | int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma); | ||
104 | struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf); | ||
105 | |||
106 | void *videobuf_pci_alloc (size_t size); | ||
107 | |||
108 | void videobuf_queue_pci_init(struct videobuf_queue* q, | ||
109 | struct videobuf_queue_ops *ops, | ||
110 | void *dev, | ||
111 | spinlock_t *irqlock, | ||
112 | enum v4l2_buf_type type, | ||
113 | enum v4l2_field field, | ||
114 | unsigned int msize, | ||
115 | void *priv); | ||
116 | |||
117 | /*FIXME: these variants are used only on *-alsa code, where videobuf is | ||
118 | * used without queue | ||
119 | */ | ||
120 | int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma); | ||
121 | int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma); | ||
122 | |||
diff --git a/include/media/video-buf-dvb.h b/include/media/videobuf-dvb.h index 8233cafdeef6..8233cafdeef6 100644 --- a/include/media/video-buf-dvb.h +++ b/include/media/videobuf-dvb.h | |||
diff --git a/include/media/videobuf-vmalloc.h b/include/media/videobuf-vmalloc.h new file mode 100644 index 000000000000..26a8958d23d1 --- /dev/null +++ b/include/media/videobuf-vmalloc.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * helper functions for vmalloc capture buffers | ||
3 | * | ||
4 | * The functions expect the hardware being able to scatter gatter | ||
5 | * (i.e. the buffers are not linear in physical memory, but fragmented | ||
6 | * into PAGE_SIZE chunks). They also assume the driver does not need | ||
7 | * to touch the video data. | ||
8 | * | ||
9 | * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 | ||
14 | */ | ||
15 | |||
16 | #include <media/videobuf-core.h> | ||
17 | |||
18 | /* --------------------------------------------------------------------- */ | ||
19 | |||
20 | struct videbuf_vmalloc_memory | ||
21 | { | ||
22 | u32 magic; | ||
23 | |||
24 | void *vmalloc; | ||
25 | |||
26 | /* remap_vmalloc_range seems to need to run after mmap() on some cases */ | ||
27 | struct vm_area_struct *vma; | ||
28 | }; | ||
29 | |||
30 | void videobuf_queue_vmalloc_init(struct videobuf_queue* q, | ||
31 | struct videobuf_queue_ops *ops, | ||
32 | void *dev, | ||
33 | spinlock_t *irqlock, | ||
34 | enum v4l2_buf_type type, | ||
35 | enum v4l2_field field, | ||
36 | unsigned int msize, | ||
37 | void *priv); | ||
38 | |||
39 | void *videobuf_to_vmalloc (struct videobuf_buffer *buf); | ||
40 | |||
41 | void videobuf_vmalloc_free (struct videobuf_buffer *buf); | ||