GIT c0767172662bf1434331b6b9e65dd67fb2c1c24b git+ssh://master.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git#devel commit Author: Robert Fitzsimons Date: Tue Feb 26 22:44:27 2008 -0300 V4L/DVB (7278): bttv: Re-enable radio tuner support for VIDIOCGFREQ/VIDIOCSFREQ ioctls Signed-off-by: Robert Fitzsimons Signed-off-by: Mauro Carvalho Chehab commit 90336ed21b3e23b0626c56ab93cd0be2ab904c41 Author: Robert Fitzsimons Date: Tue Feb 26 22:47:29 2008 -0300 V4L/DVB (7277): bttv: Re-enabling radio support requires the use of struct bttv_fh A number of the radio tuner ioctl functions are shared with the TV tuner, these functions require a struct bttv_fh data structure to be allocated and initialized. Signed-off-by: Robert Fitzsimons Signed-off-by: Mauro Carvalho Chehab commit 11c207adf864ccf4211d442a9f5b75b98665a228 Author: Guennadi Liakhovetski Date: Mon Feb 25 09:12:17 2008 -0300 V4L/DVB (7276): soc-camera: deactivate cameras when not used Only attach cameras to the host interface for probing, then detach until open. This allows platforms with several cameras on an interface, physically supporting only one camera, to handle multiple cameras and activate them selectively after initial probing. The first attach during probe is needed to activate the host interface to be able to physically communicate with cameras. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab commit af88fd1aa1e15f9dd60f490f06571dea2aed204f Author: Harvey Harrison Date: Mon Feb 25 03:54:21 2008 -0300 V4L/DVB (7275): fix integer as NULL pointer warning in mt20xx.c drivers/media/video/mt20xx.c:650:10: warning: Using plain integer as NULL pointer Signed-off-by: Harvey Harrison Signed-off-by: Mauro Carvalho Chehab commit 094c1e5f9dcc4059f2bc9cdfb2f166805c2e965d Author: Harvey Harrison Date: Mon Feb 25 03:54:23 2008 -0300 V4L/DVB (7274): dabusb: fix shadowed variable warning in dabusb.c drivers/media/video/dabusb.c:208:6: warning: symbol 'buffers' shadows an earlier one drivers/media/video/dabusb.c:63:12: originally declared here Signed-off-by: Harvey Harrison Signed-off-by: Mauro Carvalho Chehab commit 87ca8dcdbb759b40c009385dbb3028c7f90fe3a3 Author: Harvey Harrison Date: Mon Feb 25 01:17:08 2008 -0300 V4L/DVB (7273): suppress compound statement warning in dvb-bt8xx.c Prevailing kernel style seems to prefer always using braces for do {} while (). Add braces to dprintk to suppress the sparse warnings: drivers/media/dvb/bt8xx/dvb-bt8xx.c:73:2: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:93:2: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:529:2: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:614:4: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:629:4: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:639:4: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:883:2: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:917:2: warning: do-while statement is not a compound statement Signed-off-by: Harvey Harrison Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 94b49d2bc55d2d6d53e97b012e36a82c6007d2a1 Author: Tobias Klauser Date: Sat Feb 23 09:47:41 2008 -0300 V4L/DVB (7272): V4L: Storage class should be before const qualifier The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser CC: Luca Risolia Signed-off-by: Mauro Carvalho Chehab commit 67a54a7203839d3df51c50a21405c3054e41703e Author: Mauro Carvalho Chehab Date: Mon Feb 25 03:03:03 2008 -0300 V4L/DVB (7271): cx88-cards: Fix powerangel gpio1 With this gpio, audio works properly. Thanks to Daniel Fraga for helping on fixing the code for Powerangel Real board. Signed-off-by: Mauro Carvalho Chehab commit 361708c280a85144ee465f7d2b7ceb67b279ef8f Author: Mauro Carvalho Chehab Date: Mon Feb 25 02:59:29 2008 -0300 V4L/DVB (7270): cx88-dvb: Renames pci_nano callback This callback is specific to pci_nano, since supports only dvb. Renames it to avoid future mistakes. Signed-off-by: Mauro Carvalho Chehab commit a7266bf0562a36fd8b525185681ac60f9c5da5c7 Author: Mauro Carvalho Chehab Date: Tue Feb 19 17:03:28 2008 -0300 V4L/DVB (7269): cx88: Powercolor Angel works only with firmware version 2.5 Signed-off-by: Mauro Carvalho Chehab commit 3ab7b44edd3c352e5d528a46797ba6c873e024a2 Author: Mauro Carvalho Chehab Date: Tue Feb 19 13:26:33 2008 -0300 V4L/DVB (7268): saa7134: fix: tuner should be loaded before calling saa7134_board_init2() There are several parts of saa7134_board_init2() that calls tuner modules. We should first load tuner, otherwise, the commands will fail. Signed-off-by: Mauro Carvalho Chehab commit 2e53fe975de0fe560db2a7d6560a5fb66c0f66c7 Author: Mauro Carvalho Chehab Date: Tue Feb 19 13:22:25 2008 -0300 V4L/DVB (7267): cx88: Fix: Loads tuner module before sending commands to it Signed-off-by: Mauro Carvalho Chehab commit 3fbd83bdda0b9ec60c9ce8a9a2e36b6da76f5bdc Author: Mauro Carvalho Chehab Date: Tue Feb 19 13:09:37 2008 -0300 V4L/DVB (7266): cx88-dvb: convert attach_xc3028 into a function Signed-off-by: Mauro Carvalho Chehab commit b0adf7a7ce261d02a69d2d094ca99f3e98b2cbcd Author: Mauro Carvalho Chehab Date: Tue Feb 19 13:00:19 2008 -0300 V4L/DVB (7265): cx88: prints an info when xc2028 is set or is attached Signed-off-by: Mauro Carvalho Chehab commit b4a937cbb0e40dd579966f6174490451040b196b Author: Mauro Carvalho Chehab Date: Tue Feb 19 12:51:27 2008 -0300 V4L/DVB (7264): cx88-cards: always use a level on printk messages Signed-off-by: Mauro Carvalho Chehab commit 674c5faceb83470a15ae76ebda6a1f3d4666d054 Author: Mauro Carvalho Chehab Date: Tue Feb 19 12:29:06 2008 -0300 V4L/DVB (7263): Some cleanups at cx88 callback methods Signed-off-by: Mauro Carvalho Chehab commit 27e794f2b7f144ee841fba48947ac294b20f4fec Author: Mauro Carvalho Chehab Date: Tue Feb 5 06:31:26 2008 -0300 V4L/DVB (7262): Add support for xc3028-based boards This patch adds support for the following saa7134 xc3028 based boards: 132 -> AVerMedia Cardbus TV/Radio (E506R) [1461:f436] 133 -> AVerMedia Hybrid TV/Radio (A16D) [1461:f936] 134 -> Avermedia M115 [1461:a836] 135 -> Compro VideoMate T750 [185b:c900] This is based on a original patch thanks to Markus Rechberger that added xc3028 gpio init code for the above boards. This patch moves saa7134_tuner_callback to saa7134-cards, originally used only by tda8290 DVB-S boards. The callback was made more generic to support other tuners. Currently, it supports both tda8290 and xc2028/xc3028 tuners. Added also the basis for xc5000 tuner callback. Signed-off-by: Mauro Carvalho Chehab commit 39f7eed694e5d0bb39e77ef934887a1dc00476c4 Author: Mauro Carvalho Chehab Date: Tue Feb 5 06:01:18 2008 -0300 V4L/DVB (7261): Use the same callback argument as xc3028 and xc5000 Signed-off-by: Mauro Carvalho Chehab commit 2ba9bfedca24b1d29d1cfe42e6bae6c4afe5f39a Author: Mauro Carvalho Chehab Date: Tue Jan 29 11:30:43 2008 -0300 V4L/DVB (7260): tuner-xc3028: Don't check return code for clock reset Only tm6000 needs to be aware when a frequency is being changed. This seems to improve channel change detection. Other bridges don't need this. So, better to discard any errors if this fails, and proceed changing the channels. Signed-off-by: Mauro Carvalho Chehab commit 9395cbeda55acf781d5c783202183d6a5c3bc4a2 Author: Chris Pascoe Date: Tue Jan 29 11:02:23 2008 -0300 V4L/DVB (7259): FusionHDTV DVB-T Pro tuning problem fixes It seems that on this board, the demodulator provides the pullup on the I2C bus, which means that calling i2c_gate_ctrl crashes the bus. Turn this off and the xc3028 can talk OK. Also fix some GPIO related settings that became more clear through working on this. Some changes made by Mauro Chehab to allow merging it with some other xc3028 patches. Signed-off-by: Chris Pascoe Signed-off-by: Mauro Carvalho Chehab commit 1adbf1c90f74eda0702586e59a5e21692165cce6 Author: Chris Pascoe Date: Tue Jan 29 10:54:35 2008 -0300 V4L/DVB (7258): Support DVB-T tuning on the DViCO FusionHDTV DVB-T Pro Add support for tuning DVB-T channels on DViCO's FusionHDTV DVB-T Pro board. The IR remote and analog tuner are not supported at this time. Some changes made by Mauro Chehab to allow merging it with some other xc3028 patches. Signed-off-by: Chris Pascoe Signed-off-by: Mauro Carvalho Chehab commit d8a78d908c84572e49210a7054011d7532281a76 Author: Mauro Carvalho Chehab Date: Tue Jan 29 10:27:16 2008 -0300 V4L/DVB (7257): cx88: Add xc2028/3028 boards This patch ports a patch from Markus Rechberger to work with tuner-xc2028. It adds entries for several cx88 boards with xc2038/3028 tuners. Signed-off-by: Mauro Carvalho Chehab commit d2ef0e0ebde066b3b6cc91aba9e67505e2ece3f8 Author: Mauro Carvalho Chehab Date: Mon Feb 25 02:31:02 2008 -0300 V4L/DVB (7256): cx88: Add support for tuner-xc3028 Callback gpio's based on Markus Rechberger, Christopher Pascoe and Steven Toth patches. Signed-off-by: Mauro Carvalho Chehab commit 2ee563a43da72edd15c7bf6a8858d4cd45ce3795 Author: Michael Krufky Date: Sun Feb 17 02:10:25 2008 -0300 V4L/DVB (7254): cx88: fix FusionHDTV 5 PCI nano name and enable IR support load ir-kbd-i2c for IR remote control support on DViCO FusionHDTV 5 PCI nano Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit b31408016ecc90c6339426fcb64b5dd02f5273b3 Author: Steven Toth Date: Wed Jan 16 01:08:18 2008 -0300 V4L/DVB (7252): cx88: Add support for the Dvico PCI Nano ATSC is known to work. SVideo / Composite should work (I have no cable to test). Analog tuner support does not work. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab commit 5c392dea276b213d5504f81e8acadc1da8f1f05a Author: Adrian Bunk Date: Sun Feb 24 21:08:10 2008 -0300 V4L/DVB (7251): VIDEO_VIVI must depend on VIDEO_DEV This patch fixes the following compile error with VIDEO_VIVI=y, VIDEO_DEV=m reported by Toralf Förster: <-- snip --> ... LD .tmp_vmlinux1 drivers/built-in.o: In function `vivi_release': vivi.c:(.text+0x322f5): undefined reference to `video_unregister_device' vivi.c:(.text+0x32337): undefined reference to `video_device_release' drivers/built-in.o: In function `vivi_open': vivi.c:(.text+0x32845): undefined reference to `v4l2_type_names' drivers/built-in.o: In function `vivi_init': vivi.c:(.init.text+0x1d20): undefined reference to `video_device_alloc' vivi.c:(.init.text+0x1d48): undefined reference to `video_register_device' drivers/built-in.o:(.rodata+0x1b40): undefined reference to `video_ioctl2'drivers/built-in.o:(.data+0x140c): undefined reference to `video_device_release' <-- snip --> Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab commit 280a3fbf066114601766f110f32585b178c4ae45 Author: Guennadi Liakhovetski Date: Sat Feb 23 21:12:57 2008 -0300 V4L/DVB (7250): Clean up pxa-camera driver, remove non-functional and never tested pm-support This patch addresses most issues pointed out by Russell and Erik, moves recently introduced into pxa-regs.h camera-specific defines into pxa_camera.c, removes dummy power-management functions, improves function-naming, etc. Signed-off-by: Guennadi Liakhovetski Acked-by: Russell King Signed-off-by: Mauro Carvalho Chehab commit 0ca164f4a008bc2df41184f86ef17782cdbc64c3 Author: Guennadi Liakhovetski Date: Sat Feb 23 20:59:23 2008 -0300 V4L/DVB (7249): Fix advertised pixel formats in mt9m001 and mt9v022 Only advertise pixel formats, that we actually can support in the present configuration. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab commit 64bf02a0686cd30bfa6c98df69919580796399bc Author: maximilian attems Date: Sat Feb 23 08:49:25 2008 -0300 V4L/DVB (7248): dabfirmware.h add missing license Received written ack from the dabusb author that the firmware is BSD licensed. As bonus clarify copyright holder. Signed-off-by: maximilian attems Acked-by: Deti Fliegl Signed-off-by: Mauro Carvalho Chehab commit 23685850c7cf06d65ea2e357b303d8b9dffcecf5 Author: Tobias Klauser Date: Thu Feb 21 20:34:49 2008 -0300 V4L/DVB (7247): V4L: Storage class should be before const qualifier The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser Signed-off-by: Mauro Carvalho Chehab commit bc93cd8813f7c3482d758eb9bcf3f3481d1cf8b0 Author: Hans Verkuil Date: Thu Feb 21 16:10:07 2008 -0300 V4L/DVB (7245): ivtv: start timer for each DMA transfer The DMA timeout timer was started once for each set of DMA transfers, but it should be started for each single DMA transfer. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 605aef8ef71e82a0cdc3736e5b01f012bccc15ce Author: Hans Verkuil Date: Thu Feb 21 16:03:37 2008 -0300 V4L/DVB (7244): ivtv: CROP is not supported for video capture CROPCAP suggests that video capture supports cropping, but this is not the case. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit d5ca89651bf533764b1ac29ccb136ab8fe398182 Author: Ian Armstrong Date: Thu Feb 21 15:55:02 2008 -0300 V4L/DVB (7243): ivtv: yuv framebuffer tracking The existing yuv code limits output to the display area occupied by the framebuffer. This patch allows the yuv output to be 'detached' via V4L2_FBUF_FLAG_OVERLAY. By default, the yuv output window will be restricted to the framebuffer dimensions and the output position is relative to the top left corner of the framebuffer. This matches the behaviour of previous versions. If V4L2_FBUF_FLAG_OVERLAY is cleared, the yuv output will no longer be linked to the framebuffer. The maximum dimensions are either 720x576 or 720x480 depending on the current broadcast standard, with the output position relative to the top left corner of the display. The framebuffer itself can be resized, moved and panned without affecting the yuv output. Signed-off-by: Ian Armstrong Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 760c8ad62c18daa875f53aaf19524b318e2395ae Author: Ian Armstrong Date: Sat Jan 26 05:52:58 2008 -0300 V4L/DVB (7242): ivtv: fix for yuv filter table check As the result of a previous change that delayed the loading of the firmware, the driver can sometimes report a bogus error regarding the yuv output filter table not being found in the firmware. This patch moves the filter table check to ensure it's only done after the firmware has been loaded. Signed-off-by: Ian Armstrong Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit c4bee7af12a2ee0e642790a1e8a24378c9d2b008 Author: Tyler Trafford Date: Sat Jan 26 05:49:50 2008 -0300 V4L/DVB (7241): cx25840: code cleanup - Use min() - Eliminate extraneous variables Signed-off-by: Tyler Trafford Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 1cee696f414add293b938f052a5dd568cf5d31bf Author: Hans Verkuil Date: Mon Jan 14 18:58:05 2008 -0300 V4L/DVB (7240): tveeprom: remove obsolete i2c driver code The i2c driver code was once added for the out-of-tree ivtv driver, but the ivtv driver hasn't used that for a long time so this code can now be removed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit a8bd5684abd126f2a8373e26721bc032bac72340 Author: Harvey Harrison Date: Thu Feb 21 14:52:36 2008 -0300 V4L/DVB (7239): saa7146: fix sparse warnings Went along with the existing file style. drivers/media/common/saa7146_core.c:309:6: warning: Using plain integer as NULL pointer drivers/media/common/saa7146_core.c:311:8: warning: Using plain integer as NULL pointer drivers/media/common/saa7146_core.c:319:7: warning: Using plain integer as NULL pointer drivers/media/common/saa7146_core.c:319:28: warning: Using plain integer as NULL pointer drivers/media/common/saa7146_core.c:325:7: warning: Using plain integer as NULL pointer drivers/media/common/saa7146_core.c:325:28: warning: Using plain integer as NULL pointer drivers/media/common/saa7146_fops.c:275:12: warning: Using plain integer as NULL pointer Signed-off-by: Harvey Harrison Signed-off-by: Mauro Carvalho Chehab commit 486e467c2a6419b2a7aefb9d225deb267cbc7ab6 Author: Adrian Bunk Date: Tue Feb 19 16:29:08 2008 -0300 V4L/DVB (7238): make stk_camera_{suspend,resume}() static This patch makes the needlessly global stk_camera_{suspend,resume}() static. Signed-off-by: Adrian Bunk Acked-by: Jaime Velasco Juan Signed-off-by: Mauro Carvalho Chehab commit 3a6a3c777829b50b1ab2608a90457b8e8011e799 Author: Guennadi Liakhovetski Date: Tue Feb 19 09:40:54 2008 -0300 V4L/DVB (7237): Convert videobuf-dma-sg to generic DMA API videobuf-dma-sg does not need to depend on PCI. Switch it to using generic DMA API, convert all affected drivers, relax Kconfig restriction, improve compile-time type checking, fix some Coding Style violations while at it. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab commit 794a7b6d8f7a03fffcaf2791d5dc83fce37f6961 Author: Harvey Harrison Date: Sat Feb 23 04:29:16 2008 -0300 V4L/DVB (7236): bttv: struct member initialized twice fixes sparse warning: drivers/media/video/bt8xx/bttv-driver.c:3391:3: warning: Initializer entry defined twice drivers/media/video/bt8xx/bttv-driver.c:3392:3: also defined here Signed-off-by: Harvey Harrison Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit 8c154580e8424407071754162f58b54de3e9cf74 Author: Mauro Carvalho Chehab Date: Sun Feb 24 21:35:59 2008 -0300 V4L/DVB (7235): tuner-simple: fix a buffer overflow simple_set_tv() creates a buffer with 4 elements, and calls simple_std_setup(), passing &buffer[1]. This makes the 5th element of buffer to be initialized to 0, overriding some area outside the buffer. Also, simple_std_setup() receives a buffer as parameter, but the buffer is just overriden after the call, so, it doesn't make much sense to pass it as a parameter. This patch removes buffer[] from the function call, creating, instead, a local var to be used internally. Thanks to Axel Rometsch for pointing the issue. Reviewed-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 60841701ebcd9613ee0125df7d9a5d646040519d Author: Russell Kliese Date: Sun Feb 17 15:45:49 2008 -0300 V4L/DVB (7230): saa7134: add support for the MSI TV@nywhere A/D v1.1 card Signed-off-by: Russell Kliese Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab commit d58a3768808ff46e61c16d132fa84fdcef8f847a Author: Hermann Pitton Date: Sat Feb 16 22:36:30 2008 -0300 V4L/DVB (7229): saa7134: add support for the Creatix CTX953_V.1.4.3 Hybrid Signed-off-by: Hermann Pitton Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab commit 81741f5924ff0328670ffc6a24c553f2ca6832a0 Author: Yuri Funduryan Date: Sat Feb 16 22:22:37 2008 -0300 V4L/DVB (7228): saa7134: fix FM radio support for the Pinnacle PCTV 110i This also has some coding style fixes. Signed-off-by: Yuri Funduryan Signed-off-by: Hartmut Hackmann Reviewed-by: Hermann Pitton Signed-off-by: Mauro Carvalho Chehab commit 735586345a40a98b53cd38d8500042329feb6274 Author: Hartmut Hackmann Date: Wed Feb 13 20:49:41 2008 -0300 V4L/DVB (7227): saa7134: fixed DVB-S support for Medion/Creatix CTX948 The I2C bus interface of the LNB supply sits behind the i2c gate of the tda10086, so wrappers were necessary for the set_voltage functions. For the time being, the board will show up as MD8800 Many thanks to Hermann Pitton for his help Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab commit 88429eabdaf81821435e8ea77109b33e0fa253b5 Author: Hartmut Hackmann Date: Sat Feb 16 18:54:06 2008 -0300 V4L/DVB (7226): saa7134: add support for the NXP Snake DVB-S reference design Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab commit 67747e27e0f1eb87dc5aa71b328ee59036afccc1 Author: Hartmut Hackmann Date: Sun Jan 20 19:21:32 2008 -0300 V4L/DVB (7224): Initial DVB-S support for MD8800 /CTX948 Support is not complete yet and untested. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab commit 40a30ec99270bfcdefecfade99eda16e66596e12 Author: Hartmut Hackmann Date: Sun Jan 20 16:57:58 2008 -0300 V4L/DVB (7223): Add support for the ISL6405 dual LNB supply chip The chip can control 2 LNBs independently. The driver distinguishes them by evaluating the MSB of the override_set parameter of the isl6405_attach function. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab commit 7facc7ba796ec8b60b07e7f41c87a6cdc7c161d3 Author: Roel Kluin <12o3l@tiscali.nl> Date: Mon Feb 18 06:57:24 2008 -0300 V4L/DVB (7220): drivers/media/video/sn9c102/sn9c102_core.c Fix Unlikely(x) == y Fix Unlikely(x) == y Signed-off-by: Roel Kluin <12o3l@tiscali.nl> Reviewed-by: Luca Risolia Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit 8c9c367628d049b7271745b717e97362129b4040 Author: Guennadi Liakhovetski Date: Fri Feb 15 11:17:03 2008 -0300 V4L/DVB (7218): Fix breakage in mt9m001 and mt9v022 driver if "CONFIG_GENERIC_GPIO is not set" Both camera drivers can function without GPIO support, in which case they will only support the 10 bit data width mode. But the two respective switch have to depend on CONFIG_GENERIC_GPIO. Additionally remove redundant gpio_is_valid tests - they are repeated in bus_switch_request() functions. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab commit 6c4d8b7160afcc100137a7545de0474f16eb98ce Author: Guennadi Liakhovetski Date: Fri Feb 15 11:15:57 2008 -0300 V4L/DVB (7217): Replace NO_GPIO with gpio_is_valid() Upon suggestion by David Brownell use a gpio_is_valid() predicate instead of an explicit NO_GPIO macro. The respective patch to include/asm-generic/gpio.h has been accepted upstream. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab commit b6fe042e1ffbfc00159ee4cc3e173978f03bd8b0 Author: Michael Krufky Date: Thu Feb 14 03:29:32 2008 -0300 V4L/DVB (7214): tda18271: move init functions to directly above tda18271_tune Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 8968d0f21a9d0bc5114469578942eac4be9615cb Author: Michael Krufky Date: Thu Feb 14 03:17:02 2008 -0300 V4L/DVB (7213): tda18271: consolidate tune functions combine tda18271c1_tune and tda18271c2_tune into a single function Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 6ea9b87da531181d0645a18e01182032d62de6d3 Author: Michael Krufky Date: Thu Feb 14 02:07:57 2008 -0300 V4L/DVB (7212): tda18271: move rf calibration code from tda18271c1_tune into a new function move rf calibration code from tda18271c1_tune into a new function, tda18271c1_rf_tracking_filter_calibration Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit eb00f602d56fdcce5ef8d87197af6edfd868ed98 Author: Michael Krufky Date: Thu Feb 14 02:06:35 2008 -0300 V4L/DVB (7211): tda18271: remove duplicated channel configuration code from tda18271c1_tune remove duplicated channel configuration code from tda18271c1_tune, instead call function tda18271_channel_configuration Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 12e66333a8a8cf1a3c9eb221dd81f05e5a110eaf Author: Brandon Philips Date: Wed Feb 13 18:57:54 2008 -0300 V4L/DVB (7204): remove V4L2_CID_SHARPNESS from meye.h and report private control as DISABLED - Continue to support the V4L2_CID_PRIVATE_BASE + 1 control in the ABI - Report the same control as V4L2_CID_SHARPNESS - Report the private control disabled via QUERYCTRL Signed-off-by: Brandon Philips Acked-by: Stelian Pop Signed-off-by: Mauro Carvalho Chehab commit 1280cfbfb4e02ca25da4dd81ca5445f185bcc041 Author: Guennadi Liakhovetski Date: Mon Feb 11 18:08:12 2008 -0300 V4L/DVB (7196): Lift videobuf-dma-sg's PCI dependency, until it is fixed videobuf-dma-sg.c should be converted to the generic DMA API to make it also useful for non-PCI configurations. Even now it can be used thanks to compatibility macros in include/asm-generic/pci-dma-compat.h. This has been verified to work on PXA270 CPU with the pxa_camera.c soc-camera driver. For this the following temporary work-around is needed. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab commit ddd539f60869f71acd5c6e7643858707ee09a2bb Author: Michael Krufky Date: Sun Feb 10 21:02:59 2008 -0300 V4L/DVB (7184): make hybrid_tuner_request_state tolerant of devices without i2c adapters Some dvb demodulators access the tuner directly without using i2c. In these cases, i2c_adap may be NULL. This patch fixes hybrid_tuner_request_state to allow for NULL i2c_adapters. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 2447d1f1c9d7b2004e9a7e199f8bbd59903139b1 Author: Steven Whitehouse Date: Thu Feb 7 17:46:16 2008 -0300 V4L/DVB (7178): Add two new fourcc codes for 16bpp formats This adds two new fourcc codes (as per info at fourcc.org) for 16bpp mono and 16bpp Bayer formats. Signed-off-by: Steven Whitehouse Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab commit 394b5edfc7bd1c79ed6f8808e9dc48672e02ee0b Author: Guennadi Liakhovetski Date: Tue Feb 5 14:47:33 2008 -0300 V4L/DVB (7176): Phycore pcm-990-specific code for the PXA270 Quick Capture driver Platform-specific code for Phytec's phyCORE-PXA270 platform Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab commit 34e5e5630252f3f1c49c763a9dd335aa7fc37c3d Author: Guennadi Liakhovetski Date: Tue Feb 5 14:47:24 2008 -0300 V4L/DVB (7174): Add support for the MT9V022 camera This driver supports Micron MT9V022 colour camera. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab commit 75078e465bae1b640b1bfd409702b31b8bedc7b4 Author: Guennadi Liakhovetski Date: Tue Feb 5 14:47:05 2008 -0300 V4L/DVB (7173): Add support for the MT9M001 camera This driver supports Micron MT9M001 monochrome and colour cameras. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab commit 9aa0042890f2764895e24232f81404e9b646ba39 Author: Guennadi Liakhovetski Date: Tue Feb 5 14:46:25 2008 -0300 V4L/DVB (7172): V4L2 soc_camera driver for PXA27x processors This patch adds a driver for the Quick Capture Interface on the PXA270. It is based on the original driver from Intel, but has been re-worked multiple times since then, now for the first time it supports the V4L2 API. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab commit 33a638ce34b8f82d02df9bca2a38ccf248c2ef3b Author: Guennadi Liakhovetski Date: Tue Feb 5 14:46:13 2008 -0300 V4L/DVB (7170): soc_camera V4L2 driver for directly-connected SoC-based cameras This driver provides an interface between platform-specific camera busses and camera devices. It should be used if the camera is connected not over a "proper" bus like PCI or USB, but over a special bus, like, for example, the Quick Capture interface on PXA270 SoCs. Later it should also be used for i.MX31 SoCs from Freescale. It can handle multiple cameras and / or multiple busses, which can be used, e.g., in stereo-vision applications. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab commit f1138d2d941b6e7f4b3ca4dd380cd235e43bd948 Author: Guennadi Liakhovetski Date: Tue Feb 5 14:46:39 2008 -0300 V4L/DVB (7169): Add chip IDs for Micron mt9m001 and mt9v022 CMOS cameras Add V4L2_IDENT chip IDs for mt9m001 and mt9v022 cameras, will be used by future patches, primarily to implement the g_chip_ident ioctl. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab commit 018e48adee3f1addca85aeaa1c256fb2bf59ec58 Author: Brandon Philips Date: Mon Jan 28 05:49:26 2008 -0300 V4L/DVB (7167): [v4l] Add camera class control definitions Add all of the recently proposed camera class controls. These controls should appear in the next version of the v4l2spec. Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab commit f7fd1f6fcd3eb6f6c8d5e63251ba667083634651 Author: Brandon Philips Date: Mon Feb 4 22:41:54 2008 -0300 V4L/DVB (7166): [v4l] Add new user class controls and deprecate others These changes should appear in the next update of the v4l2spec. HCENTER and VCENTER are unused in the tree so I added a _DEPRECATED postfix so applications can remove their use. Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab commit 9cb393f072a3d006c33243bc240092fcc62cd2cd Author: Jan Engelhardt Date: Sun Jan 27 14:24:26 2008 -0300 V4L/DVB: constify function pointer tables Signed-off-by: Jan Engelhardt Signed-off-by: Mauro Carvalho Chehab commit 283c5d668c30a0bf5c269504309422629ca4100b Author: Michael Krufky Date: Sun Feb 3 19:58:26 2008 -0300 V4L/DVB (7137): tuner: return number of instances remaining after hybrid_tuner_release_state Assign the number of instances remaining as the return value of hybrid_tuner_release_state, in case there is any extra cleanup that the tuner driver needs to do after an instance has been destroyed. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 4a36df5b68e3a9c3f9fc3b899bb9b1b9db925b78 Author: Michael Krufky Date: Wed Jan 16 01:51:22 2008 -0300 V4L/DVB (7136): tda18271: use hybrid_tuner_request_state to manage tuner instances Convert tda18271 to use the new hybrid_tuner_request_state and hybrid_tuner_release_state macros to manage state sharing between hybrid tuner instances. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit cab02d5d02b45ab2078d6ad28baf4723bc1cb531 Author: Michael Krufky Date: Sun Feb 3 00:58:38 2008 -0300 V4L/DVB (7135): remove PREFIX from users of tuner_foo printk macros Store a pointer to the device name in the name field of struct tuner_i2c_props, so that we can remove the printk macros defined in tuner-i2c.h Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 85e05b29f448ad1c7da3ce01ce3b73179a6d56ba Author: Michael Krufky Date: Wed Jan 16 01:49:32 2008 -0300 V4L/DVB (7134): tuner: create a macro for sharing state between hybrid tuner instances Create a macro implementing a standard method to share state amongst multiple instances of a hybrid tuner object. Also, prepare tuner_foo printk macros for the removal of PREFIX Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit c860fd85da00afb38b1b0c4fe5be31188d8c1d70 Author: Michael Krufky Date: Thu Jan 31 10:42:00 2008 -0300 V4L/DVB (7130): tuner: remove emacs c-basic-offset override block I'd prefer to leave this here, but official CodingStyle doesn't care what I think :-/ Remove the emacs format override block to comply with Kernel CodingStyle. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 89a7f1c325cd6f7707463d795c556a7e3712d5d6 Author: Michael Krufky Date: Sun Jan 27 01:52:34 2008 -0300 V4L/DVB (7129): tuner-simple: move device-specific code into three separate functions Move the switch..case blocks with device-specific code from functions simple_set_tv_freq and simple_set_radio_freq ...into three new functions: simple_std_setup, simple_post_tune and simple_radio_bandswitch Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 011de27929604f87b036f3c988b872b48d94bc11 Author: Michael Krufky Date: Mon Jan 28 10:55:06 2008 -0300 V4L/DVB (7128): tuner: properly handle failed calls to simple_tuner_attach If simple_tuner_attach fails, set t->type to TUNER_ABSENT, set t->mode_mask to T_UNINITIALIZED, and exit the set_type function. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 845f14c4a4bd5d510f6c0648a56945e6575e03a4 Author: Michael Krufky Date: Tue Jan 29 03:47:25 2008 -0300 V4L/DVB (7127): tuner: remove dependency of tuner-core on tuner-types This patch fully removes the dependency of tuner-core on tuner-types. There is no longer any need to pass struct tunertype in attach-time config structure - instead pass the tuner type ID. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 616ed09ed38923e8feaf0a72e7759435df6821c6 Author: Michael Krufky Date: Mon Jan 28 10:50:21 2008 -0300 V4L/DVB (7126): tuner: move tuner type ID check to simple_tuner_attach Move tuner type ID check from tuner-core::set_type to simple_tuner_attach. Since tuner-core forwards all attach requests to tuner-simple as the default case, unless a specific attach function is specified in set_type, this change is an appropriate cleanup. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 0efa5f732a93026661ea6f5227a0cad88b6b58af Author: Michael Krufky Date: Sun Jan 27 20:18:04 2008 -0300 V4L/DVB (7125): tuner: build tuner-types independently of tuner-core tuner-types is needed for tuner-simple, and does not need to be bound to tuner-core. Any caller of tuner-simple, including tuner-core, needs to pass a structure from tuner-types into tuner-simple at attach-time. Export the two needed symbols from tuner-types for now, so that card-level drivers can attach tuner-simple for hybrid dvb_frontend devices. We will remove this dependency altogether as tuner refactoring phase 3 progresses. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit bed026f59d67abdcde379a2c16bf62f0232757d0 Author: Michael Krufky Date: Sun Jan 27 22:21:05 2008 -0300 V4L/DVB (7124): tuner-simple: display frequency in MHz fix debug in simple_config_lookup to display frequency in MHz Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 02085a5d90f7a57c1a5288e75f776a9c8496b695 Author: Michael Krufky Date: Sun Jan 27 17:01:16 2008 -0300 V4L/DVB (7123): tuner-simple: create separate t_params and ranges lookup functions Move some reuseable code out of simple_set_tv_freq into separate functions. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit e0a2aa37bd9114940ddd5f85ff43d6975e15ec9e Author: Douglas Schilling Landgraf Date: Sun Jan 27 12:10:44 2008 -0300 V4L/DVB (7094): static memory - Static memory is always initialized with 0. - Replaced in some cases C99 comments for /* */ Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab commit 69cd6bfdce475b1a90805ce54bf1a817bf12f808 Author: Adrian Bunk Date: Mon Jan 28 19:11:19 2008 -0300 V4L/DVB (7114): tuner-xc2028.c: make a function static dump_firm_type_and_int_freq() can become static. Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab commit 4ed04c0ba248bb60db16f21c9e4d20107cead57f Author: Adrian Bunk Date: Mon Jan 28 19:10:31 2008 -0300 V4L/DVB (7107): frontends/xc5000.c: make a struct static struct XC5000_Standard[] can become static. Signed-off-by: Adrian Bunk Reviewed-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab commit 67fffb580a21f03457e2c73fb7ca5fef3d878423 Author: Adrian Bunk Date: Mon Jan 28 19:10:53 2008 -0300 V4L/DVB (7105): ivtv-yuv.c: make 3 functions static This patch makes the following needlessly global functions static: - ivtv_yuv_next_free() - ivtv_yuv_setup_frame() - ivtv_yuv_udma_frame() Signed-off-by: Adrian Bunk Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 4f9592055fea17729c7e974ad3d922edb13102c6 Author: Michael Krufky Date: Sat Nov 3 14:10:08 2007 -0300 V4L/DVB (7087): tuner-simple: whitespace / comments / codingstyle cleanups Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Documentation/video4linux/CARDLIST.cx88 | 6 + Documentation/video4linux/CARDLIST.saa7134 | 7 + arch/arm/mach-pxa/devices.c | 32 + arch/arm/mach-pxa/pcm990-baseboard.c | 86 ++ drivers/media/Kconfig | 7 +- drivers/media/common/ir-functions.c | 2 +- drivers/media/common/saa7146_core.c | 8 +- drivers/media/common/saa7146_fops.c | 2 +- drivers/media/common/saa7146_vbi.c | 4 +- drivers/media/common/saa7146_video.c | 4 +- drivers/media/dvb/b2c2/flexcop-pci.c | 2 +- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 4 +- drivers/media/dvb/dvb-core/dvb_net.c | 2 +- drivers/media/dvb/dvb-core/dvbdev.c | 2 +- drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/cx22702.c | 2 +- drivers/media/dvb/frontends/dvb-pll.c | 2 +- drivers/media/dvb/frontends/isl6405.c | 164 ++++ drivers/media/dvb/frontends/isl6405.h | 74 ++ drivers/media/dvb/frontends/lgdt330x.c | 2 +- drivers/media/dvb/frontends/nxt6000.c | 2 +- drivers/media/dvb/frontends/s5h1409.c | 2 +- drivers/media/dvb/frontends/s5h1420.c | 2 +- drivers/media/dvb/frontends/sp8870.c | 12 +- drivers/media/dvb/frontends/tda10086.c | 2 +- drivers/media/dvb/frontends/tda18271-common.c | 19 +- drivers/media/dvb/frontends/tda18271-fe.c | 230 ++---- drivers/media/dvb/frontends/tda18271-priv.h | 7 +- drivers/media/dvb/frontends/tda826x.c | 2 +- drivers/media/dvb/frontends/tda827x.c | 8 +- drivers/media/dvb/frontends/ves1x93.c | 2 +- drivers/media/dvb/frontends/xc5000.c | 2 +- drivers/media/dvb/frontends/zl10353.c | 2 +- drivers/media/dvb/ttpci/budget-ci.c | 2 +- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 4 +- drivers/media/radio/miropcm20-rds.c | 2 +- drivers/media/radio/radio-cadet.c | 10 +- drivers/media/radio/radio-typhoon.c | 2 +- drivers/media/video/Kconfig | 47 +- drivers/media/video/Makefile | 8 +- drivers/media/video/adv7170.c | 2 +- drivers/media/video/adv7175.c | 2 +- drivers/media/video/arv.c | 4 +- drivers/media/video/bt819.c | 2 +- drivers/media/video/bt856.c | 2 +- drivers/media/video/bt8xx/bttv-driver.c | 43 +- drivers/media/video/bt8xx/bttv-vbi.c | 2 +- drivers/media/video/bw-qcam.c | 4 +- drivers/media/video/c-qcam.c | 4 +- drivers/media/video/cafe_ccic.c | 4 +- drivers/media/video/cpia2/cpia2_core.c | 4 +- drivers/media/video/cpia2/cpia2_usb.c | 2 +- drivers/media/video/cx23885/cx23885-dvb.c | 2 +- drivers/media/video/cx23885/cx23885-i2c.c | 2 +- drivers/media/video/cx23885/cx23885-video.c | 4 +- drivers/media/video/cx25840/cx25840-firmware.c | 11 +- drivers/media/video/cx88/cx88-alsa.c | 8 +- drivers/media/video/cx88/cx88-blackbird.c | 6 +- drivers/media/video/cx88/cx88-cards.c | 426 ++++++++- drivers/media/video/cx88/cx88-core.c | 6 +- drivers/media/video/cx88/cx88-dvb.c | 158 ++++- drivers/media/video/cx88/cx88-i2c.c | 4 +- drivers/media/video/cx88/cx88-input.c | 2 +- drivers/media/video/cx88/cx88-mpeg.c | 4 +- drivers/media/video/cx88/cx88-tvaudio.c | 6 +- drivers/media/video/cx88/cx88-vbi.c | 2 +- drivers/media/video/cx88/cx88-video.c | 18 +- drivers/media/video/cx88/cx88.h | 6 + drivers/media/video/dabfirmware.h | 7 + drivers/media/video/dabusb.c | 8 +- drivers/media/video/dpc7146.c | 4 +- drivers/media/video/em28xx/em28xx-core.c | 6 +- drivers/media/video/em28xx/em28xx-i2c.c | 4 +- drivers/media/video/em28xx/em28xx-video.c | 2 +- drivers/media/video/et61x251/et61x251_core.c | 2 +- drivers/media/video/hexium_gemini.c | 4 +- drivers/media/video/hexium_orion.c | 4 +- drivers/media/video/ir-kbd-i2c.c | 2 +- drivers/media/video/ivtv/ivtv-driver.c | 11 +- drivers/media/video/ivtv/ivtv-driver.h | 2 + drivers/media/video/ivtv/ivtv-firmware.c | 8 +- drivers/media/video/ivtv/ivtv-ioctl.c | 36 +- drivers/media/video/ivtv/ivtv-irq.c | 25 +- drivers/media/video/ivtv/ivtv-yuv.c | 38 +- drivers/media/video/meye.c | 12 +- drivers/media/video/mt20xx.c | 9 +- drivers/media/video/mt9m001.c | 703 +++++++++++++++ drivers/media/video/mt9v022.c | 819 +++++++++++++++++ drivers/media/video/mxb.c | 4 +- drivers/media/video/pms.c | 4 +- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 6 +- drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 2 +- drivers/media/video/pwc/pwc-if.c | 8 +- drivers/media/video/pxa_camera.c | 915 +++++++++++++++++++ drivers/media/video/saa6588.c | 8 +- drivers/media/video/saa7110.c | 2 +- drivers/media/video/saa7111.c | 2 +- drivers/media/video/saa7114.c | 2 +- drivers/media/video/saa7115.c | 2 +- drivers/media/video/saa711x.c | 2 +- drivers/media/video/saa7134/saa7134-alsa.c | 12 +- drivers/media/video/saa7134/saa7134-cards.c | 364 +++++++- drivers/media/video/saa7134/saa7134-core.c | 48 +- drivers/media/video/saa7134/saa7134-dvb.c | 122 +++- drivers/media/video/saa7134/saa7134-empress.c | 6 +- drivers/media/video/saa7134/saa7134-i2c.c | 4 +- drivers/media/video/saa7134/saa7134-input.c | 6 +- drivers/media/video/saa7134/saa7134-ts.c | 2 +- drivers/media/video/saa7134/saa7134-tvaudio.c | 6 +- drivers/media/video/saa7134/saa7134-vbi.c | 2 +- drivers/media/video/saa7134/saa7134-video.c | 10 +- drivers/media/video/saa7134/saa7134.h | 16 +- drivers/media/video/saa7185.c | 2 +- drivers/media/video/se401.c | 2 +- drivers/media/video/sn9c102/sn9c102_core.c | 4 +- drivers/media/video/sn9c102/sn9c102_sensor.h | 2 +- drivers/media/video/soc_camera.c | 999 +++++++++++++++++++++ drivers/media/video/stk-webcam.c | 4 +- drivers/media/video/stradis.c | 4 +- drivers/media/video/stv680.c | 9 +- drivers/media/video/tda8290.c | 3 +- drivers/media/video/tda9840.c | 2 +- drivers/media/video/tda9887.c | 3 +- drivers/media/video/tea5761.c | 7 +- drivers/media/video/tea5767.c | 34 +- drivers/media/video/tea6415c.c | 2 +- drivers/media/video/tea6420.c | 2 +- drivers/media/video/tuner-core.c | 44 +- drivers/media/video/tuner-i2c.h | 118 +++- drivers/media/video/tuner-simple.c | 513 +++++++---- drivers/media/video/tuner-simple.h | 11 +- drivers/media/video/tuner-types.c | 6 + drivers/media/video/tuner-xc2028.c | 18 +- drivers/media/video/tvaudio.c | 8 +- drivers/media/video/tveeprom.c | 103 --- drivers/media/video/tvp5150.c | 2 +- drivers/media/video/usbvideo/ibmcam.c | 2 +- drivers/media/video/usbvideo/konicawc.c | 2 +- drivers/media/video/usbvideo/quickcam_messenger.c | 2 +- drivers/media/video/usbvideo/ultracam.c | 4 +- drivers/media/video/usbvideo/usbvideo.c | 2 +- drivers/media/video/usbvision/usbvision-core.c | 14 +- drivers/media/video/usbvision/usbvision-i2c.c | 2 +- drivers/media/video/usbvision/usbvision-video.c | 4 +- drivers/media/video/v4l1-compat.c | 4 +- drivers/media/video/videobuf-dma-sg.c | 119 ++-- drivers/media/video/videobuf-dvb.c | 2 +- drivers/media/video/videobuf-vmalloc.c | 4 +- drivers/media/video/videocodec.c | 4 +- drivers/media/video/vino.c | 10 +- drivers/media/video/vpx3220.c | 2 +- drivers/media/video/w9966.c | 4 +- drivers/media/video/w9968cf.c | 2 +- drivers/media/video/zc0301/zc0301_core.c | 2 +- drivers/media/video/zoran_card.c | 6 +- drivers/media/video/zoran_device.c | 5 +- drivers/media/video/zoran_driver.c | 2 +- drivers/media/video/zr36016.c | 5 +- drivers/media/video/zr36050.c | 5 +- drivers/media/video/zr36060.c | 6 +- drivers/media/video/zr364xx.c | 4 +- include/asm-arm/arch-pxa/camera.h | 48 + include/asm-arm/arch-pxa/pxa-regs.h | 147 +++- include/linux/meye.h | 2 +- include/linux/videodev2.h | 52 +- include/media/soc_camera.h | 149 +++ include/media/v4l2-chip-ident.h | 6 + include/media/videobuf-dma-sg.h | 14 +- 169 files changed, 6220 insertions(+), 1106 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index bc5593b..423da15 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -57,3 +57,9 @@ 56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder [0070:9600,0070:9601,0070:9602] 57 -> ADS Tech Instant Video PCI [1421:0390] 58 -> Pinnacle PCTV HD 800i [11bd:0051] + 59 -> DViCO FusionHDTV 5 PCI nano [18ac:d530] + 60 -> Pinnacle Hybrid PCTV [12ab:1788] + 61 -> Winfast TV2000 XP Global [107d:6f18] + 62 -> PowerColor Real Angel 330 [14f1:ea3d] + 63 -> Geniatech X8000-MT DVBT [14f1:8852] + 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30] diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 0424901..c1f9f13 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -131,3 +131,10 @@ 130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193] 131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022] 132 -> Genius TVGO AM11MCE +133 -> NXP Snake DVB-S reference design +134 -> Medion/Creatix CTX953 Hybrid [16be:0010] +135 -> MSI TV@nywhere A/D v1.1 [1462:8625] +136 -> AVerMedia Cardbus TV/Radio (E506R) [1461:f436] +137 -> AVerMedia Hybrid TV/Radio (A16D) [1461:f936] +138 -> Avermedia M115 [1461:a836] +139 -> Compro VideoMate T750 [185b:c900] diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index bfccb80..3838aab 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "devices.h" @@ -540,6 +541,37 @@ struct platform_device pxa27x_device_ssp3 = { .resource = pxa27x_resource_ssp3, .num_resources = ARRAY_SIZE(pxa27x_resource_ssp3), }; + +static struct resource pxa27x_resource_camera[] = { + [0] = { + .start = 0x50000000, + .end = 0x50000fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_CAMERA, + .end = IRQ_CAMERA, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 pxa27x_dma_mask_camera = DMA_BIT_MASK(32); + +static struct platform_device pxa27x_device_camera = { + .name = "pxa27x-camera", + .id = 0, /* This is used to put cameras on this interface */ + .dev = { + .dma_mask = &pxa27x_dma_mask_camera, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(pxa27x_resource_camera), + .resource = pxa27x_resource_camera, +}; + +void __init pxa_set_camera_info(struct pxacamera_platform_data *info) +{ + pxa_register_device(&pxa27x_device_camera, info); +} #endif /* CONFIG_PXA27x || CONFIG_PXA3xx */ #ifdef CONFIG_PXA3xx diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c index 3dda16a..07ac050 100644 --- a/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/arch/arm/mach-pxa/pcm990-baseboard.c @@ -23,6 +23,13 @@ #include #include #include +#include + +#include + +#include +#include +#include #include #include #include @@ -258,6 +265,76 @@ static struct pxaohci_platform_data pcm990_ohci_platform_data = { }; /* + * PXA27x Camera specific stuff + */ +#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE) +static int pcm990_pxacamera_init(struct device *dev) +{ + pxa_gpio_mode(GPIO98_CIF_DD0_MD); + pxa_gpio_mode(GPIO105_CIF_DD1_MD); + pxa_gpio_mode(GPIO104_CIF_DD2_MD); + pxa_gpio_mode(GPIO103_CIF_DD3_MD); + pxa_gpio_mode(GPIO95_CIF_DD4_MD); + pxa_gpio_mode(GPIO94_CIF_DD5_MD); + pxa_gpio_mode(GPIO93_CIF_DD6_MD); + pxa_gpio_mode(GPIO108_CIF_DD7_MD); + pxa_gpio_mode(GPIO107_CIF_DD8_MD); + pxa_gpio_mode(GPIO106_CIF_DD9_MD); + pxa_gpio_mode(GPIO42_CIF_MCLK_MD); + pxa_gpio_mode(GPIO45_CIF_PCLK_MD); + pxa_gpio_mode(GPIO43_CIF_FV_MD); + pxa_gpio_mode(GPIO44_CIF_LV_MD); + + return 0; +} + +/* + * CICR4: PCLK_EN: Pixel clock is supplied by the sensor + * MCLK_EN: Master clock is generated by PXA + * PCP: Data sampled on the falling edge of pixel clock + */ +struct pxacamera_platform_data pcm990_pxacamera_platform_data = { + .init = pcm990_pxacamera_init, + .flags = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 | PXA_CAMERA_DATAWIDTH_10 | + PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN/* | PXA_CAMERA_PCP*/, + .mclk_10khz = 1000, +}; + +#include + +static struct pca953x_platform_data pca9536_data = { + .gpio_base = NR_BUILTIN_GPIO + 1, +}; + +static struct soc_camera_link iclink[] = { + { + .bus_id = 0, /* Must match with the camera ID above */ + .gpio = NR_BUILTIN_GPIO + 1, + }, { + .bus_id = 0, /* Must match with the camera ID above */ + } +}; + +/* Board I2C devices. */ +static struct i2c_board_info __initdata pcm990_i2c_devices[] = { + { + /* Must initialize before the camera(s) */ + I2C_BOARD_INFO("pca953x", 0x41), + .type = "pca9536", + .platform_data = &pca9536_data, + }, { + I2C_BOARD_INFO("mt9v022", 0x48), + .type = "mt9v022", + .platform_data = &iclink[0], /* With extender */ + }, { + I2C_BOARD_INFO("mt9m001", 0x5d), + .type = "mt9m001", + .platform_data = &iclink[0], /* With extender */ + }, +}; +#endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */ + +/* * AC97 support * Note: The connected AC97 mixer also reports interrupts at PCM990_AC97_IRQ */ @@ -326,5 +403,14 @@ void __init pcm990_baseboard_init(void) /* USB host */ pxa_set_ohci_info(&pcm990_ohci_platform_data); + pxa_set_i2c_info(NULL); + +#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE) + pxa_set_camera_info(&pcm990_pxacamera_platform_data); + + i2c_register_board_info(0, pcm990_i2c_devices, + ARRAY_SIZE(pcm990_i2c_devices)); +#endif + printk(KERN_INFO"PCM-990 Evaluation baseboard initialized\n"); } diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 1195069..b9b38d9 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -71,9 +71,13 @@ source "drivers/media/dvb/Kconfig" source "drivers/media/common/Kconfig" +config VIDEO_TUNER_TYPES + tristate + config VIDEO_TUNER tristate depends on I2C + select VIDEO_TUNER_TYPES select TUNER_XC2028 if !VIDEO_TUNER_CUSTOMIZE select TUNER_MT20XX if !VIDEO_TUNER_CUSTOMIZE select TUNER_TDA8290 if !VIDEO_TUNER_CUSTOMIZE @@ -136,6 +140,7 @@ config TUNER_TEA5767 config TUNER_SIMPLE tristate "Simple tuner support" depends on I2C + select VIDEO_TUNER_TYPES select TUNER_TDA9887 default m if VIDEO_TUNER_CUSTOMIZE help @@ -155,7 +160,7 @@ config VIDEOBUF_GEN tristate config VIDEOBUF_DMA_SG - depends on PCI + depends on HAS_DMA select VIDEOBUF_GEN tristate diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c index bb2a027..2665052 100644 --- a/drivers/media/common/ir-functions.c +++ b/drivers/media/common/ir-functions.c @@ -34,7 +34,7 @@ static int repeat = 1; module_param(repeat, int, 0444); MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); -static int debug = 0; /* debug level (0,1,2) */ +static int debug; /* debug level (0,1,2) */ module_param(debug, int, 0644); #define dprintk(level, fmt, arg...) if (debug >= level) \ diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 168a8d3..8c755a1 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -306,9 +306,9 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id) return IRQ_NONE; } - if( 0 != (dev->ext)) { + if( NULL != (dev->ext)) { if( 0 != (dev->ext->irq_mask & isr )) { - if( 0 != dev->ext->irq_func ) { + if( NULL != dev->ext->irq_func ) { dev->ext->irq_func(dev, &isr); } isr &= ~dev->ext->irq_mask; @@ -316,13 +316,13 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id) } if (0 != (isr & (MASK_27))) { DEB_INT(("irq: RPS0 (0x%08x).\n",isr)); - if( 0 != dev->vv_data && 0 != dev->vv_callback) { + if( NULL != dev->vv_data && NULL != dev->vv_callback) { dev->vv_callback(dev,isr); } isr &= ~MASK_27; } if (0 != (isr & (MASK_28))) { - if( 0 != dev->vv_data && 0 != dev->vv_callback) { + if( NULL != dev->vv_data && NULL != dev->vv_callback) { dev->vv_callback(dev,isr); } isr &= ~MASK_28; diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index f0703d8..a73db79 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -272,7 +272,7 @@ static int fops_open(struct inode *inode, struct file *file) result = 0; out: - if( fh != 0 && result != 0 ) { + if( fh != NULL && result != 0 ) { kfree(fh); file->private_data = NULL; } diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c index bfbd5a8..74e2b56 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146_vbi.c @@ -407,8 +407,8 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) fh->vbi_fmt.start[1] = 312; fh->vbi_fmt.count[1] = 16; - videobuf_queue_pci_init(&fh->vbi_q, &vbi_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, // FIXME: does this really work? sizeof(struct saa7146_buf), diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 66fdbd0..3cbc6eb 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -1410,8 +1410,8 @@ static int video_open(struct saa7146_dev *dev, struct file *file) sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8; - videobuf_queue_pci_init(&fh->video_q, &video_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->video_q, &video_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct saa7146_buf), diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 01af4d2..5b30dfc 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c @@ -32,7 +32,7 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently jus #define deb_irq(args...) dprintk(0x08,args) #define deb_chk(args...) dprintk(0x10,args) -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS); diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index dedd30a..209356b 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -41,9 +41,9 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); #define dprintk( args... ) \ - do \ + do { \ if (debug) printk(KERN_DEBUG args); \ - while (0) + } while (0) #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index ed3f826..ba4db89 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -354,7 +354,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) #ifdef ULE_DEBUG /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */ static unsigned char ule_hist[100*TS_SZ]; - static unsigned char *ule_where = ule_hist, ule_dump = 0; + static unsigned char *ule_where = ule_hist, ule_dump; #endif /* For all TS cells in current buffer. diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 18738fa..ce5122e 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -97,7 +97,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) } -static struct file_operations dvb_device_fops = +static const struct file_operations dvb_device_fops = { .owner = THIS_MODULE, .open = dvb_device_open, diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 9ad86ce..0209644 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -379,6 +379,13 @@ config DVB_LNBP21 help An SEC control chip. +config DVB_ISL6405 + tristate "ISL6405 SEC controller" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + An SEC control chip. + config DVB_ISL6421 tristate "ISL6421 SEC controller" depends on DVB_CORE && I2C diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 16bd107..23304b3 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_DVB_S5H1420) += s5h1420.o obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o obj-$(CONFIG_DVB_CX24123) += cx24123.o obj-$(CONFIG_DVB_LNBP21) += lnbp21.o +obj-$(CONFIG_DVB_ISL6405) += isl6405.o obj-$(CONFIG_DVB_ISL6421) += isl6421.o obj-$(CONFIG_DVB_TDA10086) += tda10086.o obj-$(CONFIG_DVB_TDA826X) += tda826x.o diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c index 1dc164d..406c4cf 100644 --- a/drivers/media/dvb/frontends/cx22702.c +++ b/drivers/media/dvb/frontends/cx22702.c @@ -48,7 +48,7 @@ struct cx22702_state { u8 prevUCBlocks; }; -static int debug = 0; +static int debug; #define dprintk if (debug) printk /* Register values to initialise the demod */ diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 8c8d734..decf798 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -44,7 +44,7 @@ struct dvb_pll_priv { static unsigned int dvb_pll_devcount; -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); diff --git a/drivers/media/dvb/frontends/isl6405.c b/drivers/media/dvb/frontends/isl6405.c new file mode 100644 index 0000000..33d33f4 --- /dev/null +++ b/drivers/media/dvb/frontends/isl6405.c @@ -0,0 +1,164 @@ +/* + * isl6405.c - driver for dual lnb supply and control ic ISL6405 + * + * Copyright (C) 2008 Hartmut Hackmann + * Copyright (C) 2006 Oliver Endriss + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ +#include +#include +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "isl6405.h" + +struct isl6405 { + u8 config; + u8 override_or; + u8 override_and; + struct i2c_adapter *i2c; + u8 i2c_addr; +}; + +static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv; + struct i2c_msg msg = { .addr = isl6405->i2c_addr, .flags = 0, + .buf = &isl6405->config, + .len = sizeof(isl6405->config) }; + + if (isl6405->override_or & 0x80) { + isl6405->config &= ~(ISL6405_VSEL2 | ISL6405_EN2); + switch (voltage) { + case SEC_VOLTAGE_OFF: + break; + case SEC_VOLTAGE_13: + isl6405->config |= ISL6405_EN2; + break; + case SEC_VOLTAGE_18: + isl6405->config |= (ISL6405_EN2 | ISL6405_VSEL2); + break; + default: + return -EINVAL; + } + } else { + isl6405->config &= ~(ISL6405_VSEL1 | ISL6405_EN1); + switch (voltage) { + case SEC_VOLTAGE_OFF: + break; + case SEC_VOLTAGE_13: + isl6405->config |= ISL6405_EN1; + break; + case SEC_VOLTAGE_18: + isl6405->config |= (ISL6405_EN1 | ISL6405_VSEL1); + break; + default: + return -EINVAL; + }; + } + isl6405->config |= isl6405->override_or; + isl6405->config &= isl6405->override_and; + + return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static int isl6405_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) +{ + struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv; + struct i2c_msg msg = { .addr = isl6405->i2c_addr, .flags = 0, + .buf = &isl6405->config, + .len = sizeof(isl6405->config) }; + + if (isl6405->override_or & 0x80) { + if (arg) + isl6405->config |= ISL6405_LLC2; + else + isl6405->config &= ~ISL6405_LLC2; + } else { + if (arg) + isl6405->config |= ISL6405_LLC1; + else + isl6405->config &= ~ISL6405_LLC1; + } + isl6405->config |= isl6405->override_or; + isl6405->config &= isl6405->override_and; + + return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static void isl6405_release(struct dvb_frontend *fe) +{ + /* power off */ + isl6405_set_voltage(fe, SEC_VOLTAGE_OFF); + + /* free */ + kfree(fe->sec_priv); + fe->sec_priv = NULL; +} + +struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, + u8 i2c_addr, u8 override_set, u8 override_clear) +{ + struct isl6405 *isl6405 = kmalloc(sizeof(struct isl6405), GFP_KERNEL); + if (!isl6405) + return NULL; + + /* default configuration */ + if (override_set & 0x80) + isl6405->config = ISL6405_ISEL2; + else + isl6405->config = ISL6405_ISEL1; + isl6405->i2c = i2c; + isl6405->i2c_addr = i2c_addr; + fe->sec_priv = isl6405; + + /* bits which should be forced to '1' */ + isl6405->override_or = override_set; + + /* bits which should be forced to '0' */ + isl6405->override_and = ~override_clear; + + /* detect if it is present or not */ + if (isl6405_set_voltage(fe, SEC_VOLTAGE_OFF)) { + kfree(isl6405); + fe->sec_priv = NULL; + return NULL; + } + + /* install release callback */ + fe->ops.release_sec = isl6405_release; + + /* override frontend ops */ + fe->ops.set_voltage = isl6405_set_voltage; + fe->ops.enable_high_lnb_voltage = isl6405_enable_high_lnb_voltage; + + return fe; +} +EXPORT_SYMBOL(isl6405_attach); + +MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6405"); +MODULE_AUTHOR("Hartmut Hackmann & Oliver Endriss"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/isl6405.h b/drivers/media/dvb/frontends/isl6405.h new file mode 100644 index 0000000..9d4001a --- /dev/null +++ b/drivers/media/dvb/frontends/isl6405.h @@ -0,0 +1,74 @@ +/* + * isl6405.h - driver for dual lnb supply and control ic ISL6405 + * + * Copyright (C) 2008 Hartmut Hackmann + * Copyright (C) 2006 Oliver Endriss + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ + +#ifndef _ISL6405_H +#define _ISL6405_H + +#include + +/* system register bits */ + +/* this bit selects register (control) 1 or 2 + note that the bit maps are different */ + +#define ISL6405_SR 0x80 + +/* SR = 0 */ +#define ISL6405_OLF1 0x01 +#define ISL6405_EN1 0x02 +#define ISL6405_VSEL1 0x04 +#define ISL6405_LLC1 0x08 +#define ISL6405_ENT1 0x10 +#define ISL6405_ISEL1 0x20 +#define ISL6405_DCL 0x40 + +/* SR = 1 */ +#define ISL6405_OLF2 0x01 +#define ISL6405_OTF 0x02 +#define ISL6405_EN2 0x04 +#define ISL6405_VSEL2 0x08 +#define ISL6405_LLC2 0x10 +#define ISL6405_ENT2 0x20 +#define ISL6405_ISEL2 0x40 + +#if defined(CONFIG_DVB_ISL6405) || (defined(CONFIG_DVB_ISL6405_MODULE) && defined(MODULE)) +/* override_set and override_clear control which system register bits (above) + * to always set & clear + */ +extern struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, + u8 i2c_addr, u8 override_set, u8 override_clear); +#else +static inline struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, u8 i2c_addr, + u8 override_set, u8 override_clear) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif /* CONFIG_DVB_ISL6405 */ + +#endif diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index bdc9fa8..dc897a3 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -49,7 +49,7 @@ /* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */ /* #define USE_EQMSE */ -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off)."); #define dprintk(args...) \ diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c index d313d7d..0eef22d 100644 --- a/drivers/media/dvb/frontends/nxt6000.c +++ b/drivers/media/dvb/frontends/nxt6000.c @@ -38,7 +38,7 @@ struct nxt6000_state { struct dvb_frontend frontend; }; -static int debug = 0; +static int debug; #define dprintk if (debug) printk static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data) diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c index 8194334..c5232e8 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb/frontends/s5h1409.c @@ -48,7 +48,7 @@ struct s5h1409_state { u32 qam_state; }; -static int debug = 0; +static int debug; #define dprintk if (debug) printk /* Register values to initialise the demod, this will set VSB by default */ diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c index 2c2c344..7c64af9 100644 --- a/drivers/media/dvb/frontends/s5h1420.c +++ b/drivers/media/dvb/frontends/s5h1420.c @@ -53,7 +53,7 @@ static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings); -static int debug = 0; +static int debug; #define dprintk if (debug) printk static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data) diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c index da876f7..f5b3bfc 100644 --- a/drivers/media/dvb/frontends/sp8870.c +++ b/drivers/media/dvb/frontends/sp8870.c @@ -449,15 +449,15 @@ static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks return 0; } -// number of trials to recover from lockup +/* number of trials to recover from lockup */ #define MAXTRIALS 5 -// maximum checks for data valid signal +/* maximum checks for data valid signal */ #define MAXCHECKS 100 -// only for debugging: counter for detected lockups -static int lockups = 0; -// only for debugging: counter for channel switches -static int switches = 0; +/* only for debugging: counter for detected lockups */ +static int lockups; +/* only for debugging: counter for channel switches */ +static int switches; static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c index 0d2b69a..143af96 100644 --- a/drivers/media/dvb/frontends/tda10086.c +++ b/drivers/media/dvb/frontends/tda10086.c @@ -43,7 +43,7 @@ struct tda10086_state { bool has_lock; }; -static int debug = 0; +static int debug; #define dprintk(args...) \ do { \ if (debug) printk(KERN_DEBUG "tda10086: " args); \ diff --git a/drivers/media/dvb/frontends/tda18271-common.c b/drivers/media/dvb/frontends/tda18271-common.c index bca5709..3949646 100644 --- a/drivers/media/dvb/frontends/tda18271-common.c +++ b/drivers/media/dvb/frontends/tda18271-common.c @@ -125,16 +125,16 @@ int tda18271_read_regs(struct dvb_frontend *fe) unsigned char buf = 0x00; int ret; struct i2c_msg msg[] = { - { .addr = priv->i2c_addr, .flags = 0, + { .addr = priv->i2c_props.addr, .flags = 0, .buf = &buf, .len = 1 }, - { .addr = priv->i2c_addr, .flags = I2C_M_RD, + { .addr = priv->i2c_props.addr, .flags = I2C_M_RD, .buf = regs, .len = 16 } }; tda18271_i2c_gate_ctrl(fe, 1); /* read all registers */ - ret = i2c_transfer(priv->i2c_adap, msg, 2); + ret = i2c_transfer(priv->i2c_props.adap, msg, 2); tda18271_i2c_gate_ctrl(fe, 0); @@ -155,16 +155,16 @@ int tda18271_read_extended(struct dvb_frontend *fe) unsigned char buf = 0x00; int ret, i; struct i2c_msg msg[] = { - { .addr = priv->i2c_addr, .flags = 0, + { .addr = priv->i2c_props.addr, .flags = 0, .buf = &buf, .len = 1 }, - { .addr = priv->i2c_addr, .flags = I2C_M_RD, + { .addr = priv->i2c_props.addr, .flags = I2C_M_RD, .buf = regdump, .len = TDA18271_NUM_REGS } }; tda18271_i2c_gate_ctrl(fe, 1); /* read all registers */ - ret = i2c_transfer(priv->i2c_adap, msg, 2); + ret = i2c_transfer(priv->i2c_props.adap, msg, 2); tda18271_i2c_gate_ctrl(fe, 0); @@ -192,7 +192,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; unsigned char buf[TDA18271_NUM_REGS + 1]; - struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, + struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0, .buf = buf, .len = len + 1 }; int i, ret; @@ -205,7 +205,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) tda18271_i2c_gate_ctrl(fe, 1); /* write registers */ - ret = i2c_transfer(priv->i2c_adap, &msg, 1); + ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); tda18271_i2c_gate_ctrl(fe, 0); @@ -223,7 +223,8 @@ int tda18271_init_regs(struct dvb_frontend *fe) unsigned char *regs = priv->tda18271_regs; tda_dbg("initializing registers for device @ %d-%04x\n", - i2c_adapter_id(priv->i2c_adap), priv->i2c_addr); + i2c_adapter_id(priv->i2c_props.adap), + priv->i2c_props.addr); /* initialize registers */ switch (priv->id) { diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index dfe72aa..b5d69a8 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -31,27 +31,11 @@ static int tda18271_cal_on_startup; module_param_named(cal, tda18271_cal_on_startup, int, 0644); MODULE_PARM_DESC(cal, "perform RF tracking filter calibration on startup"); -static LIST_HEAD(tda18271_list); static DEFINE_MUTEX(tda18271_list_mutex); +static LIST_HEAD(hybrid_tuner_instance_list); /*---------------------------------------------------------------------*/ -static int tda18271_ir_cal_init(struct dvb_frontend *fe) -{ - struct tda18271_priv *priv = fe->tuner_priv; - unsigned char *regs = priv->tda18271_regs; - - tda18271_read_regs(fe); - - /* test IR_CAL_OK to see if we need init */ - if ((regs[R_EP1] & 0x08) == 0) - tda18271_init_regs(fe); - - return 0; -} - -/* ------------------------------------------------------------------ */ - static int tda18271_channel_configuration(struct dvb_frontend *fe, u32 ifc, u32 freq, u32 bw, u8 std, int radio) @@ -195,8 +179,10 @@ static int tda18271_read_thermometer(struct dvb_frontend *fe) return tm; } -static int tda18271_rf_tracking_filters_correction(struct dvb_frontend *fe, - u32 freq) +/* ------------------------------------------------------------------ */ + +static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe, + u32 freq) { struct tda18271_priv *priv = fe->tuner_priv; struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state; @@ -587,7 +573,7 @@ static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe) /* ------------------------------------------------------------------ */ -static int tda18271_rf_cal_init(struct dvb_frontend *fe) +static int tda18271c2_rf_cal_init(struct dvb_frontend *fe) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; @@ -610,63 +596,13 @@ static int tda18271_rf_cal_init(struct dvb_frontend *fe) return 0; } -static int tda18271_init(struct dvb_frontend *fe) -{ - struct tda18271_priv *priv = fe->tuner_priv; - - mutex_lock(&priv->lock); - - /* power up */ - tda18271_set_standby_mode(fe, 0, 0, 0); - - /* initialization */ - tda18271_ir_cal_init(fe); - - if (priv->id == TDA18271HDC2) - tda18271_rf_cal_init(fe); - - mutex_unlock(&priv->lock); - - return 0; -} - -static int tda18271c2_tune(struct dvb_frontend *fe, - u32 ifc, u32 freq, u32 bw, u8 std, int radio) -{ - struct tda18271_priv *priv = fe->tuner_priv; - - tda_dbg("freq = %d, ifc = %d\n", freq, ifc); - - tda18271_init(fe); - - mutex_lock(&priv->lock); - - tda18271_rf_tracking_filters_correction(fe, freq); - - tda18271_channel_configuration(fe, ifc, freq, bw, std, radio); - - mutex_unlock(&priv->lock); - - return 0; -} - -/* ------------------------------------------------------------------ */ - -static int tda18271c1_tune(struct dvb_frontend *fe, - u32 ifc, u32 freq, u32 bw, u8 std, int radio) +static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe, + u32 freq, u32 bw) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; u32 N = 0; - tda18271_init(fe); - - mutex_lock(&priv->lock); - - tda_dbg("freq = %d, ifc = %d\n", freq, ifc); - - /* RF tracking filter calibration */ - /* calculate bp filter */ tda18271_calc_bp_filter(fe, &freq); tda18271_write_regs(fe, R_EP1, 1); @@ -737,7 +673,7 @@ static int tda18271c1_tune(struct dvb_frontend *fe, regs[R_EB7] = 0x40; tda18271_write_regs(fe, R_EB7, 1); - msleep(10); + msleep(10); /* pll locking */ regs[R_EB20] = 0xec; tda18271_write_regs(fe, R_EB20, 1); @@ -752,74 +688,70 @@ static int tda18271c1_tune(struct dvb_frontend *fe, if (0 == tda18271_calc_rf_cal(fe, &freq)) tda18271_write_regs(fe, R_EB14, 1); - /* Channel Configuration */ + return 0; +} - switch (priv->mode) { - case TDA18271_ANALOG: - regs[R_EB22] = 0x2c; - break; - case TDA18271_DIGITAL: - regs[R_EB22] = 0x37; - break; - } - tda18271_write_regs(fe, R_EB22, 1); +/* ------------------------------------------------------------------ */ - regs[R_EP1] |= 0x40; /* set dis power level on */ +static int tda18271_ir_cal_init(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; - /* set standard */ - regs[R_EP3] &= ~0x1f; /* clear std bits */ + tda18271_read_regs(fe); - /* see table 22 */ - regs[R_EP3] |= std; + /* test IR_CAL_OK to see if we need init */ + if ((regs[R_EP1] & 0x08) == 0) + tda18271_init_regs(fe); - regs[R_EP4] &= ~0x03; /* set cal mode to normal */ + return 0; +} - regs[R_EP4] &= ~0x1c; /* clear if level bits */ - switch (priv->mode) { - case TDA18271_ANALOG: - regs[R_MPD] &= ~0x80; /* IF notch = 0 */ - break; - case TDA18271_DIGITAL: - regs[R_EP4] |= 0x04; - regs[R_MPD] |= 0x80; - break; - } +static int tda18271_init(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; - if (radio) - regs[R_EP4] |= 0x80; - else - regs[R_EP4] &= ~0x80; + mutex_lock(&priv->lock); - /* image rejection validity */ - tda18271_calc_ir_measure(fe, &freq); + /* power up */ + tda18271_set_standby_mode(fe, 0, 0, 0); - /* calculate MAIN PLL */ - N = freq + ifc; + /* initialization */ + tda18271_ir_cal_init(fe); - tda18271_calc_main_pll(fe, N); + if (priv->id == TDA18271HDC2) + tda18271c2_rf_cal_init(fe); - tda18271_write_regs(fe, R_TM, 15); - msleep(5); mutex_unlock(&priv->lock); return 0; } -static inline int tda18271_tune(struct dvb_frontend *fe, - u32 ifc, u32 freq, u32 bw, u8 std, int radio) +static int tda18271_tune(struct dvb_frontend *fe, + u32 ifc, u32 freq, u32 bw, u8 std, int radio) { struct tda18271_priv *priv = fe->tuner_priv; - int ret = -EINVAL; + + tda_dbg("freq = %d, ifc = %d, bw = %d, std = 0x%02x\n", + freq, ifc, bw, std); + + tda18271_init(fe); + + mutex_lock(&priv->lock); switch (priv->id) { case TDA18271HDC1: - ret = tda18271c1_tune(fe, ifc, freq, bw, std, radio); + tda18271c1_rf_tracking_filter_calibration(fe, freq, bw); break; case TDA18271HDC2: - ret = tda18271c2_tune(fe, ifc, freq, bw, std, radio); + tda18271c2_rf_tracking_filters_correction(fe, freq); break; } - return ret; + tda18271_channel_configuration(fe, ifc, freq, bw, std, radio); + + mutex_unlock(&priv->lock); + + return 0; } /* ------------------------------------------------------------------ */ @@ -986,16 +918,9 @@ static int tda18271_release(struct dvb_frontend *fe) mutex_lock(&tda18271_list_mutex); - priv->count--; - - if (!priv->count) { - tda_dbg("destroying instance @ %d-%04x\n", - i2c_adapter_id(priv->i2c_adap), - priv->i2c_addr); - list_del(&priv->tda18271_list); + if (priv) + hybrid_tuner_release_state(priv); - kfree(priv); - } mutex_unlock(&tda18271_list_mutex); fe->tuner_priv = NULL; @@ -1109,7 +1034,8 @@ static int tda18271_get_id(struct dvb_frontend *fe) } tda_info("%s detected @ %d-%04x%s\n", name, - i2c_adapter_id(priv->i2c_adap), priv->i2c_addr, + i2c_adapter_id(priv->i2c_props.adap), + priv->i2c_props.addr, (0 == ret) ? "" : ", device not supported."); return ret; @@ -1136,46 +1062,25 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, struct tda18271_config *cfg) { struct tda18271_priv *priv = NULL; - int state_found = 0; + int instance; mutex_lock(&tda18271_list_mutex); - list_for_each_entry(priv, &tda18271_list, tda18271_list) { - if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) && - (priv->i2c_addr == addr)) { - tda_dbg("attaching existing tuner @ %d-%04x\n", - i2c_adapter_id(priv->i2c_adap), - priv->i2c_addr); - priv->count++; - fe->tuner_priv = priv; - state_found = 1; - /* allow dvb driver to override i2c gate setting */ - if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG)) - priv->gate = cfg->gate; - break; - } - } - if (state_found == 0) { - tda_dbg("creating new tuner instance @ %d-%04x\n", - i2c_adapter_id(i2c), addr); - - priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL); - if (priv == NULL) { - mutex_unlock(&tda18271_list_mutex); - return NULL; - } - - priv->i2c_addr = addr; - priv->i2c_adap = i2c; + instance = hybrid_tuner_request_state(struct tda18271_priv, priv, + hybrid_tuner_instance_list, + i2c, addr, "tda18271"); + switch (instance) { + case 0: + goto fail; + break; + case 1: + /* new tuner instance */ priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; priv->cal_initialized = false; mutex_init(&priv->lock); - priv->count++; fe->tuner_priv = priv; - list_add_tail(&priv->tda18271_list, &tda18271_list); - if (tda18271_get_id(fe) < 0) goto fail; @@ -1186,9 +1091,18 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, tda18271_init_regs(fe); if ((tda18271_cal_on_startup) && (priv->id == TDA18271HDC2)) - tda18271_rf_cal_init(fe); + tda18271c2_rf_cal_init(fe); mutex_unlock(&priv->lock); + break; + default: + /* existing tuner instance */ + fe->tuner_priv = priv; + + /* allow dvb driver to override i2c gate setting */ + if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG)) + priv->gate = cfg->gate; + break; } /* override default std map with values in config struct */ diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h index 7b939a5..840b180 100644 --- a/drivers/media/dvb/frontends/tda18271-priv.h +++ b/drivers/media/dvb/frontends/tda18271-priv.h @@ -24,6 +24,7 @@ #include #include #include +#include "tuner-i2c.h" #include "tda18271.h" #define R_ID 0x00 /* ID byte */ @@ -98,17 +99,15 @@ enum tda18271_ver { }; struct tda18271_priv { - u8 i2c_addr; - struct i2c_adapter *i2c_adap; unsigned char tda18271_regs[TDA18271_NUM_REGS]; - struct list_head tda18271_list; + struct list_head hybrid_tuner_instance_list; + struct tuner_i2c_props i2c_props; enum tda18271_mode mode; enum tda18271_i2c_gate gate; enum tda18271_ver id; - unsigned int count; unsigned int tm_rfcal; unsigned int cal_initialized:1; diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c index bd3ebc2..9a91eb0 100644 --- a/drivers/media/dvb/frontends/tda826x.c +++ b/drivers/media/dvb/frontends/tda826x.c @@ -26,7 +26,7 @@ #include "tda826x.h" -static int debug = 0; +static int debug; #define dprintk(args...) \ do { \ if (debug) printk(KERN_DEBUG "tda826x: " args); \ diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c index 229b119..967ac8b 100644 --- a/drivers/media/dvb/frontends/tda827x.c +++ b/drivers/media/dvb/frontends/tda827x.c @@ -25,7 +25,7 @@ #include "tda827x.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); @@ -578,8 +578,7 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, else arg = 0; if (priv->cfg->tuner_callback) - priv->cfg->tuner_callback(priv->i2c_adap->algo_data, - 1, arg); + priv->cfg->tuner_callback(priv, 1, arg); buf[1] = high ? 0 : 1; if (*priv->cfg->config == 2) buf[1] = high ? 1 : 0; @@ -587,8 +586,7 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, break; case 3: /* switch with GPIO of saa713x */ if (priv->cfg->tuner_callback) - priv->cfg->tuner_callback(priv->i2c_adap->algo_data, - 0, high); + priv->cfg->tuner_callback(priv, 0, high); break; } } diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c index 23fd030..c041c81 100644 --- a/drivers/media/dvb/frontends/ves1x93.c +++ b/drivers/media/dvb/frontends/ves1x93.c @@ -48,7 +48,7 @@ struct ves1x93_state { u8 demod_type; }; -static int debug = 0; +static int debug; #define dprintk if (debug) printk #define DEMOD_VES1893 0 diff --git a/drivers/media/dvb/frontends/xc5000.c b/drivers/media/dvb/frontends/xc5000.c index f642ca2..a5094b7 100644 --- a/drivers/media/dvb/frontends/xc5000.c +++ b/drivers/media/dvb/frontends/xc5000.c @@ -151,7 +151,7 @@ typedef struct { #define FM_Radio_INPUT2 21 #define FM_Radio_INPUT1 22 -XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { +static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020}, {"M/N-NTSC/PAL-A2", 0x0600, 0x8020}, {"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020}, diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index 276e3b6..3d508ff 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c @@ -46,7 +46,7 @@ static int debug; if (debug) printk(KERN_DEBUG "zl10353: " args); \ } while (0) -static int debug_regs = 0; +static int debug_regs; static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val) { diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 5093492..0f476f7 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -86,7 +86,7 @@ static int rc5_device = -1; module_param(rc5_device, int, 0644); MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)"); -static int ir_debug = 0; +static int ir_debug; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 7902ae1..1b3b6c1 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -542,7 +542,7 @@ static void ttusb_handle_sec_data(struct ttusb_channel *channel, const u8 * data, int len); #endif -static int numpkt = 0, numts, numstuff, numsec, numinvalid; +static int numpkt, numts, numstuff, numsec, numinvalid; static unsigned long lastj; static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack, @@ -1005,7 +1005,7 @@ static int stc_release(struct inode *inode, struct file *file) return 0; } -static struct file_operations stc_fops = { +static const struct file_operations stc_fops = { .owner = THIS_MODULE, .read = stc_read, .open = stc_open, diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c index aed1147..06dfed9 100644 --- a/drivers/media/radio/miropcm20-rds.c +++ b/drivers/media/radio/miropcm20-rds.c @@ -19,7 +19,7 @@ #include "miropcm20-rds-core.h" static char * text_buffer; -static int rds_users = 0; +static int rds_users; static int rds_f_open(struct inode *in, struct file *fi) diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 34e317c..cf68a70 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -69,13 +69,13 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io=-1; /* default to isapnp activation */ static int radio_nr = -1; -static int users=0; -static int curtuner=0; -static int tunestat=0; -static int sigstrength=0; +static int users; +static int curtuner; +static int tunestat; +static int sigstrength; static wait_queue_head_t read_queue; static struct timer_list readtimer; -static __u8 rdsin=0,rdsout=0,rdsstat=0; +static __u8 rdsin, rdsout, rdsstat; static unsigned char rdsbuf[RDS_BUFFER]; static spinlock_t cadet_io_lock; diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index 1366326..02e3a2f 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -404,7 +404,7 @@ MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)"); module_param(radio_nr, int, 0); #ifdef MODULE -static unsigned long mutefreq = 0; +static unsigned long mutefreq; module_param(mutefreq, ulong, 0); MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)"); #endif diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 37072a2..b29f527 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -382,7 +382,7 @@ endmenu # encoder / decoder chips config VIDEO_VIVI tristate "Virtual Video Driver" - depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 + depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 select VIDEOBUF_VMALLOC default n ---help--- @@ -836,4 +836,49 @@ config USB_STKWEBCAM endif # V4L_USB_DRIVERS +config SOC_CAMERA + tristate "SoC camera support" + depends on VIDEO_V4L2 + select VIDEOBUF_DMA_SG + help + SoC Camera is a common API to several cameras, not connecting + over a bus like PCI or USB. For example some i2c camera connected + directly to the data bus of an SoC. + +config SOC_CAMERA_MT9M001 + tristate "mt9m001 support" + depends on SOC_CAMERA + select GPIO_PCA953X if MT9M001_PCA9536_SWITCH + help + This driver supports MT9M001 cameras from Micron, monochrome + and colour models. + +config MT9M001_PCA9536_SWITCH + bool "pca9536 datawidth switch for mt9m001" + depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO + help + Select this if your MT9M001 camera uses a PCA9536 I2C GPIO + extender to switch between 8 and 10 bit datawidth modes + +config SOC_CAMERA_MT9V022 + tristate "mt9v022 support" + depends on SOC_CAMERA + select GPIO_PCA953X if MT9V022_PCA9536_SWITCH + help + This driver supports MT9V022 cameras from Micron + +config MT9V022_PCA9536_SWITCH + bool "pca9536 datawidth switch for mt9v022" + depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO + help + Select this if your MT9V022 camera uses a PCA9536 I2C GPIO + extender to switch between 8 and 10 bit datawidth modes + +config VIDEO_PXA27x + tristate "PXA27x Quick Capture Interface driver" + depends on VIDEO_DEV && PXA27x + select SOC_CAMERA + ---help--- + This is a v4l2 driver for the PXA27x Quick Capture Interface + endif # VIDEO_CAPTURE_DRIVERS diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 3f209b3..77cfaff 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -4,7 +4,7 @@ zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o -tuner-objs := tuner-core.o tuner-types.o +tuner-objs := tuner-core.o msp3400-objs := msp3400-driver.o msp3400-kthreads.o @@ -84,6 +84,7 @@ obj-$(CONFIG_VIDEO_DPC) += dpc7146.o obj-$(CONFIG_TUNER_3036) += tuner-3036.o obj-$(CONFIG_VIDEO_TUNER) += tuner.o +obj-$(CONFIG_VIDEO_TUNER_TYPES) += tuner-types.o obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o @@ -135,5 +136,10 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o obj-$(CONFIG_VIDEO_CX23885) += cx23885/ +obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o +obj-$(CONFIG_SOC_CAMERA) += soc_camera.o +obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o +obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index cbab53f..92327fd 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -56,7 +56,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(x) (x)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 0d0c554..9ed4e5e 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -52,7 +52,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index c94a4d0..e4d891b 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -125,8 +125,8 @@ static unsigned char yuv[MAX_AR_FRAME_BYTES]; /* default frequency */ #define DEFAULT_FREQ 50 /* 50 or 75 (MHz) is available as BCLK */ static int freq = DEFAULT_FREQ; /* BCLK: available 50 or 70 (MHz) */ -static int vga = 0; /* default mode(0:QVGA mode, other:VGA mode) */ -static int vga_interlace = 0; /* 0 is normal mode for, else interlace mode */ +static int vga; /* default mode(0:QVGA mode, other:VGA mode) */ +static int vga_interlace; /* 0 is normal mode for, else interlace mode */ module_param(freq, int, 0); module_param(vga, int, 0); module_param(vga_interlace, int, 0); diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index 12d1b92..34d4383 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -57,7 +57,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index e1028a7..df0c41b 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -56,7 +56,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 5404fcc..dec33f2 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1990,7 +1990,7 @@ static int bttv_g_frequency(struct file *file, void *priv, if (0 != err) return err; - f->type = V4L2_TUNER_ANALOG_TV; + f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = btv->freq; return 0; @@ -2009,7 +2009,8 @@ static int bttv_s_frequency(struct file *file, void *priv, if (unlikely(f->tuner != 0)) return -EINVAL; - if (unlikely(f->type != V4L2_TUNER_ANALOG_TV)) + if (unlikely(f->type != (btv->radio_user + ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV))) return -EINVAL; mutex_lock(&btv->lock); btv->freq = f->frequency; @@ -2371,7 +2372,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, if (check_btres(fh, RESOURCE_OVERLAY)) { struct bttv_buffer *new; - new = videobuf_pci_alloc(sizeof(*new)); + new = videobuf_sg_alloc(sizeof(*new)); new->crop = btv->crop[!!fh->do_crop].rect; bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); retval = bttv_switch_overlay(btv,fh,new); @@ -2759,7 +2760,7 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on) mutex_lock(&fh->cap.vb_lock); if (on) { fh->ov.tvnorm = btv->tvnorm; - new = videobuf_pci_alloc(sizeof(*new)); + new = videobuf_sg_alloc(sizeof(*new)); new->crop = btv->crop[!!fh->do_crop].rect; bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); } else { @@ -2833,7 +2834,7 @@ static int bttv_s_fbuf(struct file *file, void *f, if (check_btres(fh, RESOURCE_OVERLAY)) { struct bttv_buffer *new; - new = videobuf_pci_alloc(sizeof(*new)); + new = videobuf_sg_alloc(sizeof(*new)); new->crop = btv->crop[!!fh->do_crop].rect; bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); retval = bttv_switch_overlay(btv, fh, new); @@ -3183,7 +3184,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) /* need to capture a new frame */ if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM)) goto err; - fh->cap.read_buf = videobuf_pci_alloc(fh->cap.msize); + fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize); if (NULL == fh->cap.read_buf) goto err; fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR; @@ -3250,14 +3251,14 @@ static int bttv_open(struct inode *inode, struct file *file) fh->ov.setup_ok = 0; v4l2_prio_open(&btv->prio,&fh->prio); - videobuf_queue_pci_init(&fh->cap, &bttv_video_qops, - btv->c.pci, &btv->s_lock, + videobuf_queue_sg_init(&fh->cap, &bttv_video_qops, + &btv->c.pci->dev, &btv->s_lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct bttv_buffer), fh); - videobuf_queue_pci_init(&fh->vbi, &bttv_vbi_qops, - btv->c.pci, &btv->s_lock, + videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops, + &btv->c.pci->dev, &btv->s_lock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct bttv_buffer), @@ -3389,7 +3390,6 @@ static struct video_device bttv_video_template = .vidiocgmbuf = vidiocgmbuf, #endif .vidioc_g_crop = bttv_g_crop, - .vidioc_g_crop = bttv_g_crop, .vidioc_s_crop = bttv_s_crop, .vidioc_g_fbuf = bttv_g_fbuf, .vidioc_s_fbuf = bttv_s_fbuf, @@ -3416,6 +3416,7 @@ static int radio_open(struct inode *inode, struct file *file) { int minor = iminor(inode); struct bttv *btv = NULL; + struct bttv_fh *fh; unsigned int i; dprintk("bttv: open minor=%d\n",minor); @@ -3430,12 +3431,19 @@ static int radio_open(struct inode *inode, struct file *file) return -ENODEV; dprintk("bttv%d: open called (radio)\n",btv->c.nr); + + /* allocate per filehandle data */ + fh = kmalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) + return -ENOMEM; + file->private_data = fh; + *fh = btv->init; + v4l2_prio_open(&btv->prio, &fh->prio); + mutex_lock(&btv->lock); btv->radio_user++; - file->private_data = btv; - bttv_call_i2c_clients(btv,AUDC_SET_RADIO,NULL); audio_input(btv,TVAUDIO_INPUT_RADIO); @@ -3445,7 +3453,8 @@ static int radio_open(struct inode *inode, struct file *file) static int radio_release(struct inode *inode, struct file *file) { - struct bttv *btv = file->private_data; + struct bttv_fh *fh = file->private_data; + struct bttv *btv = fh->btv; struct rds_command cmd; btv->radio_user--; @@ -3570,7 +3579,8 @@ static int radio_g_input(struct file *filp, void *priv, unsigned int *i) static ssize_t radio_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { - struct bttv *btv = file->private_data; + struct bttv_fh *fh = file->private_data; + struct bttv *btv = fh->btv; struct rds_command cmd; cmd.block_count = count/3; cmd.buffer = data; @@ -3584,7 +3594,8 @@ static ssize_t radio_read(struct file *file, char __user *data, static unsigned int radio_poll(struct file *file, poll_table *wait) { - struct bttv *btv = file->private_data; + struct bttv_fh *fh = file->private_data; + struct bttv *btv = fh->btv; struct rds_command cmd; cmd.instance = file; cmd.event_list = wait; diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c index 75fa82c..bfdbc46 100644 --- a/drivers/media/video/bt8xx/bttv-vbi.c +++ b/drivers/media/video/bt8xx/bttv-vbi.c @@ -54,7 +54,7 @@ #define VBI_DEFLINES 16 static unsigned int vbibufs = 4; -static unsigned int vbi_debug = 0; +static unsigned int vbi_debug; module_param(vbibufs, int, 0444); module_param(vbi_debug, int, 0644); diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 0322653..40a8e92 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -523,7 +523,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[]) int ret=1; unsigned int hi, lo; unsigned int hi2, lo2; - static int state = 0; + static int state; if (buffer == NULL) { @@ -912,7 +912,7 @@ static struct video_device qcam_template= #define MAX_CAMS 4 static struct qcam_device *qcams[MAX_CAMS]; -static unsigned int num_cams = 0; +static unsigned int num_cams; static int init_bwqcam(struct parport *port) { diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index cf1546b..d4d5adf 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -69,7 +69,7 @@ struct qcam_device { static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 }; static int probe = 2; -static int force_rgb = 0; +static int force_rgb; static int video_nr = -1; static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i) @@ -741,7 +741,7 @@ static struct qcam_device *qcam_init(struct parport *port) } static struct qcam_device *qcams[MAX_CAMS]; -static unsigned int num_cams = 0; +static unsigned int num_cams; static int init_cqcam(struct parport *port) { diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 7ae499c..5195b1f 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -65,7 +65,7 @@ MODULE_SUPPORTED_DEVICE("Video"); */ #define MAX_DMA_BUFS 3 -static int alloc_bufs_at_read = 0; +static int alloc_bufs_at_read; module_param(alloc_bufs_at_read, bool, 0444); MODULE_PARM_DESC(alloc_bufs_at_read, "Non-zero value causes DMA buffers to be allocated when the " @@ -99,7 +99,7 @@ MODULE_PARM_DESC(max_buffers, "will be allowed to allocate. These buffers are big and live " "in vmalloc space."); -static int flip = 0; +static int flip; module_param(flip, bool, 0444); MODULE_PARM_DESC(flip, "If set, the sensor will be instructed to flip the image " diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c index a76bd78..a439a56 100644 --- a/drivers/media/video/cpia2/cpia2_core.c +++ b/drivers/media/video/cpia2/cpia2_core.c @@ -34,7 +34,7 @@ #include #include -//#define _CPIA2_DEBUG_ +/* #define _CPIA2_DEBUG_ */ #include "cpia2patch.h" @@ -48,7 +48,7 @@ static const char *block_name[] = { }; #endif -static unsigned int debugs_on = 0;//DEBUG_REG; +static unsigned int debugs_on; /* default 0 - DEBUG_REG */ /****************************************************************************** diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c index d8e9298..a457474 100644 --- a/drivers/media/video/cpia2/cpia2_usb.c +++ b/drivers/media/video/cpia2/cpia2_usb.c @@ -84,7 +84,7 @@ static struct usb_driver cpia2_driver = { *****************************************************************************/ static void process_frame(struct camera_data *cam) { - static int frame_count = 0; + static int frame_count; unsigned char *inbuff = cam->workbuff->data; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index ed465c0..6c21779 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -349,7 +349,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port) /* dvb stuff */ printk("%s: cx23885 based dvb card\n", dev->name); - videobuf_queue_pci_init(&port->dvb.dvbq, &dvb_qops, dev->pci, &port->slock, + videobuf_queue_sg_init(&port->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx23885_buffer), port); err = dvb_register(port); diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 92fe0bd..748c79a 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -33,7 +33,7 @@ static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index d3c4d2c..45bf214 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -765,8 +765,8 @@ static int video_open(struct inode *inode, struct file *file) fh->height = 240; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); - videobuf_queue_pci_init(&fh->vidq, &cx23885_video_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx23885_buffer), diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index 1ddf724..620d295 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c @@ -79,11 +79,9 @@ static int check_fw_load(struct i2c_client *client, int size) return 0; } -static int fw_write(struct i2c_client *client, u8 * data, int size) +static int fw_write(struct i2c_client *client, u8 *data, int size) { - int sent; - - if ((sent = i2c_master_send(client, data, size)) < size) { + if (i2c_master_send(client, data, size) < size) { v4l_err(client, "firmware load i2c failure\n"); return -ENOSYS; } @@ -96,7 +94,7 @@ int cx25840_loadfw(struct i2c_client *client) struct cx25840_state *state = i2c_get_clientdata(client); const struct firmware *fw = NULL; u8 buffer[4], *ptr; - int size, send, retval; + int size, retval; if (state->is_cx23885) firmware = FWFILE_CX23885; @@ -124,8 +122,7 @@ int cx25840_loadfw(struct i2c_client *client) while (size > 0) { ptr[0] = 0x08; ptr[1] = 0x02; - send = size > (FWSEND - 2) ? FWSEND : size + 2; - retval = fw_write(client, ptr, send); + retval = fw_write(client, ptr, min(FWSEND, size + 2)); if (retval < 0) { release_firmware(fw); diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 316b106..2f5a4a4 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -283,7 +283,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip) BUG_ON(!chip->dma_size); dprintk(2,"Freeing buffer\n"); - videobuf_pci_dma_unmap(chip->pci, chip->dma_risc); + videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc); videobuf_dma_free(chip->dma_risc); btcx_riscmem_free(chip->pci,&chip->buf->risc); kfree(chip->buf); @@ -385,7 +385,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, BUG_ON(!chip->dma_size); BUG_ON(chip->num_periods & (chip->num_periods-1)); - buf = videobuf_pci_alloc(sizeof(*buf)); + buf = videobuf_sg_alloc(sizeof(*buf)); if (NULL == buf) return -ENOMEM; @@ -396,14 +396,14 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, buf->vb.height = chip->num_periods; buf->vb.size = chip->dma_size; - dma=videobuf_to_dma(&buf->vb); + dma = videobuf_to_dma(&buf->vb); videobuf_dma_init(dma); ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); if (ret < 0) goto error; - ret = videobuf_pci_dma_map(chip->pci,dma); + ret = videobuf_sg_dma_map(&chip->pci->dev, dma); if (ret < 0) goto error; diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index a99e9d5..d582395 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -45,7 +45,7 @@ static unsigned int mpegbufs = 32; module_param(mpegbufs,int,0644); MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug,int,0644); MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); @@ -1087,8 +1087,8 @@ static int mpeg_open(struct inode *inode, struct file *file) file->private_data = fh; fh->dev = dev; - videobuf_queue_pci_init(&fh->mpegq, &blackbird_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx88_buffer), diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index e6b7f51..bf58f35 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -27,6 +27,7 @@ #include "cx88.h" #include "tea5767.h" +#include "tuner-xc2028.h" static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; @@ -44,6 +45,16 @@ static unsigned int latency = UNSET; module_param(latency,int,0444); MODULE_PARM_DESC(latency,"pci latency timer"); +#define info_printk(core, fmt, arg...) \ + printk(KERN_INFO "%s: " fmt, core->name , ## arg) + +#define warn_printk(core, fmt, arg...) \ + printk(KERN_WARNING "%s: " fmt, core->name , ## arg) + +#define err_printk(core, fmt, arg...) \ + printk(KERN_ERR "%s: " fmt, core->name , ## arg) + + /* ------------------------------------------------------------------ */ /* board config info */ @@ -1401,6 +1412,165 @@ static const struct cx88_board cx88_boards[] = { }}, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = { + .name = "DViCO FusionHDTV 5 PCI nano", + /* xc3008 tuner, digital only for now */ + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x000027df, /* Unconfirmed */ + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000027df, /* Unconfirmed */ + .audioroute = 1, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000027df, /* Unconfirmed */ + .audioroute = 1, + } }, + .mpeg = CX88_MPEG_DVB, + }, + [CX88_BOARD_PINNACLE_HYBRID_PCTV] = { + .name = "Pinnacle Hybrid PCTV", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x0ff, + }, + }, + [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { + .name = "Winfast TV2000 XP Global", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ + .gpio1 = 0x0000, + .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ + + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ + .gpio1 = 0x0000, + .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ + + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x0ff, + }, + }, + [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { + .name = "PowerColor Real Angel 330", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ + .gpio1 = 0xf35d, + .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ + .gpio1 = 0x0000, + .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000ff, + .gpio1 = 0x0f37d, + .gpio2 = 0x00019, + .gpio3 = 0x00000, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x000ff, + .gpio1 = 0x0f35d, + .gpio2 = 0x00019, + .gpio3 = 0x00000, + }, + }, + [CX88_BOARD_GENIATECH_X8000_MT] = { + /* Also PowerColor Real Angel 330 and Geniatech X800 OEM */ + .name = "Geniatech X8000-MT DVBT", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e341, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e361, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e361, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e341, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + }, + .mpeg = CX88_MPEG_DVB, + }, + [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = { + .name = "DViCO FusionHDTV DVB-T PRO", + .tuner_type = TUNER_ABSENT, /* XXX: Has XC3028 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = { { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000067df, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000067df, + } }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -1605,7 +1775,11 @@ static const struct cx88_subid cx88_subids[] = { .subdevice = 0xdb11, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, /* Re-branded DViCO: UltraView DVB-T Plus */ - },{ + }, { + .subvendor = 0x18ac, + .subdevice = 0xdb30, + .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO, + }, { .subvendor = 0x17de, .subdevice = 0x0840, .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, @@ -1714,7 +1888,27 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x11bd, .subdevice = 0x0051, .card = CX88_BOARD_PINNACLE_PCTV_HD_800i, - }, + }, { + .subvendor = 0x18ac, + .subdevice = 0xd530, + .card = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO, + }, { + .subvendor = 0x12ab, + .subdevice = 0x1788, + .card = CX88_BOARD_PINNACLE_HYBRID_PCTV, + }, { + .subvendor = 0x14f1, + .subdevice = 0xea3d, + .card = CX88_BOARD_POWERCOLOR_REAL_ANGEL, + }, { + .subvendor = 0x107d, + .subdevice = 0x6f18, + .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, + }, { + .subvendor = 0x14f1, + .subdevice = 0x8852, + .card = CX88_BOARD_GENIATECH_X8000_MT, + } }; /* ----------------------------------------------------------------------- */ @@ -1731,17 +1925,16 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) if (eeprom_data[4] != 0x7d || eeprom_data[5] != 0x10 || eeprom_data[7] != 0x66) { - printk(KERN_WARNING "%s: Leadtek eeprom invalid.\n", - core->name); + warn_printk(core, "Leadtek eeprom invalid.\n"); return; } core->board.tuner_type = (eeprom_data[6] == 0x13) ? TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3; - printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: " - "tuner=%d, eeprom[0]=0x%02x\n", - core->name, core->board.tuner_type, eeprom_data[0]); + info_printk(core, "Leadtek Winfast 2000XP Expert config: " + "tuner=%d, eeprom[0]=0x%02x\n", + core->board.tuner_type, eeprom_data[0]); } static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) @@ -1785,13 +1978,12 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) /* known */ break; default: - printk("%s: warning: unknown hauppauge model #%d\n", - core->name, tv.model); + warn_printk(core, "warning: unknown hauppauge model #%d\n", + tv.model); break; } - printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n", - core->name, tv.model); + info_printk(core, "hauppauge eeprom: model=%d\n", tv.model); } /* ----------------------------------------------------------------------- */ @@ -1837,8 +2029,7 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner)) ? gdi_tuner[eeprom_data[0x0d]].name : NULL; - printk(KERN_INFO "%s: GDI: tuner=%s\n", core->name, - name ? name : "unknown"); + info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown"); if (NULL == name) return; core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id; @@ -1846,6 +2037,58 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) CX88_RADIO : 0; } +/* ------------------------------------------------------------------- */ +/* some Divco specific stuff */ +static int cx88_dvico_xc2028_callback(void *ptr, int command, int arg) +{ + struct cx88_core *core = ptr; + + switch (command) { + case XC2028_TUNER_RESET: + cx_write(MO_GP0_IO, 0x101000); + mdelay(5); + cx_set(MO_GP0_IO, 0x101010); + break; + default: + return -EINVAL; + } + + return 0; +} + + +/* ----------------------------------------------------------------------- */ +/* some Geniatech specific stuff */ + +static int cx88_xc3028_geniatech_tuner_callback(void *priv, int command, int mode) +{ + struct i2c_algo_bit_data *i2c_algo = priv; + struct cx88_core *core = i2c_algo->data; + + switch (command) { + case XC2028_TUNER_RESET: + switch (INPUT(core->input).type) { + case CX88_RADIO: + break; + case CX88_VMUX_DVB: + cx_write(MO_GP1_IO, 0x030302); + mdelay(50); + break; + default: + cx_write(MO_GP1_IO, 0x030301); + mdelay(50); + } + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + cx_write(MO_GP1_IO, 0x101000); + mdelay(50); + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + return 0; + } + return -EINVAL; +} + /* ----------------------------------------------------------------------- */ /* some DViCO specific stuff */ @@ -1874,40 +2117,99 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core) msg.len = (i != 12 ? 5 : 2); err = i2c_transfer(&core->i2c_adap, &msg, 1); if (err != 1) { - printk("dvico_fusionhdtv_hybrid_init buf %d failed (err = %d)!\n", i, err); + warn_printk(core, "dvico_fusionhdtv_hybrid_init buf %d " + "failed (err = %d)!\n", i, err); return; } } } +static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) +{ + struct i2c_algo_bit_data *i2c_algo = priv; + struct cx88_core *core = i2c_algo->data; + + /* Board-specific callbacks */ + switch (core->boardnr) { + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: + case CX88_BOARD_POWERCOLOR_REAL_ANGEL: + case CX88_BOARD_GENIATECH_X8000_MT: + return cx88_xc3028_geniatech_tuner_callback(priv, command, arg); + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + return cx88_dvico_xc2028_callback(priv, command, arg); + } + + switch (command) { + case XC2028_TUNER_RESET: + switch (INPUT(core->input).type) { + case CX88_RADIO: + info_printk(core, "setting GPIO to radio!\n"); + cx_write(MO_GP0_IO, 0x4ff); + mdelay(250); + cx_write(MO_GP2_IO, 0xff); + mdelay(250); + break; + case CX88_VMUX_DVB: /* Digital TV*/ + default: /* Analog TV */ + info_printk(core, "setting GPIO to TV!\n"); + break; + } + cx_write(MO_GP1_IO, 0x101010); + mdelay(250); + cx_write(MO_GP1_IO, 0x101000); + mdelay(250); + cx_write(MO_GP1_IO, 0x101010); + mdelay(250); + return 0; + } + return -EINVAL; +} + /* ----------------------------------------------------------------------- */ /* Tuner callback function. Currently only needed for the Pinnacle * * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both * * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c) */ -int cx88_tuner_callback(void *priv, int command, int arg) +static int cx88_xc5000_tuner_callback(void *priv, int command, int arg) { struct i2c_algo_bit_data *i2c_algo = priv; struct cx88_core *core = i2c_algo->data; - switch(core->boardnr) { + switch (core->boardnr) { case CX88_BOARD_PINNACLE_PCTV_HD_800i: - if(command == 0) { /* This is the reset command from xc5000 */ + if (command == 0) { /* This is the reset command from xc5000 */ /* Reset XC5000 tuner via SYS_RSTO_pin */ cx_write(MO_SRST_IO, 0); msleep(10); cx_write(MO_SRST_IO, 1); return 0; - } - else { - printk(KERN_ERR - "xc5000: unknown tuner callback command.\n"); + } else { + err_printk(core, "xc5000: unknown tuner " + "callback command.\n"); return -EINVAL; } break; } return 0; /* Should never be here */ } + +int cx88_tuner_callback(void *priv, int command, int arg) +{ + struct i2c_algo_bit_data *i2c_algo = priv; + struct cx88_core *core = i2c_algo->data; + + switch (core->board.tuner_type) { + case TUNER_XC2028: + info_printk(core, "Calling XC2028/3028 callback\n"); + return cx88_xc2028_tuner_callback(priv, command, arg); + case TUNER_XC5000: + info_printk(core, "Calling XC5000 callback\n"); + return cx88_xc5000_tuner_callback(priv, command, arg); + } + err_printk(core, "Error: Calling callback for tuner %d\n", + core->board.tuner_type); + return -EINVAL; +} EXPORT_SYMBOL(cx88_tuner_callback); /* ----------------------------------------------------------------------- */ @@ -1918,23 +2220,25 @@ static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci) if (0 == pci->subsystem_vendor && 0 == pci->subsystem_device) { - printk("%s: Your board has no valid PCI Subsystem ID and thus can't\n" + printk(KERN_ERR + "%s: Your board has no valid PCI Subsystem ID and thus can't\n" "%s: be autodetected. Please pass card= insmod option to\n" "%s: workaround that. Redirect complaints to the vendor of\n" "%s: the TV card. Best regards,\n" "%s: -- tux\n", core->name,core->name,core->name,core->name,core->name); } else { - printk("%s: Your board isn't known (yet) to the driver. You can\n" + printk(KERN_ERR + "%s: Your board isn't known (yet) to the driver. You can\n" "%s: try to pick one of the existing card configs via\n" "%s: card= insmod option. Updating to the latest\n" "%s: version might help as well.\n", core->name,core->name,core->name,core->name); } - printk("%s: Here is a list of valid choices for the card= insmod option:\n", - core->name); + err_printk(core, "Here is a list of valid choices for the card= " + "insmod option:\n"); for (i = 0; i < ARRAY_SIZE(cx88_boards); i++) - printk("%s: card=%d -> %s\n", + printk(KERN_ERR "%s: card=%d -> %s\n", core->name, i, cx88_boards[i].name); } @@ -1991,6 +2295,13 @@ static void cx88_card_setup(struct cx88_core *core) cx_write(MO_GP0_IO, 0x000007f8); cx_write(MO_GP1_IO, 0x00000001); break; + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + /* GPIO0:0 is hooked to demod reset */ + /* GPIO0:4 is hooked to xc3028 reset */ + cx_write(MO_GP0_IO, 0x00111100); + msleep(1); + cx_write(MO_GP0_IO, 0x00111111); + break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: /* GPIO0:6 is hooked to FX2 reset pin */ cx_set(MO_GP0_IO, 0x00004040); @@ -2038,10 +2349,8 @@ static void cx88_card_setup(struct cx88_core *core) for (i = 0; i < ARRAY_SIZE(buffer); i++) if (2 != i2c_master_send(&core->i2c_client, buffer[i],2)) - printk(KERN_WARNING - "%s: Unable to enable " - "tuner(%i).\n", - core->name, i); + warn_printk(core, "Unable to enable " + "tuner(%i).\n", i); } break; case CX88_BOARD_MSI_TVANYWHERE_MASTER: @@ -2062,6 +2371,40 @@ static void cx88_card_setup(struct cx88_core *core) cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg); } } + + if (core->board.tuner_type == TUNER_XC2028) { + struct v4l2_priv_tun_config xc2028_cfg; + struct xc2028_ctrl ctl; + + memset(&xc2028_cfg, 0, sizeof(ctl)); + memset(&ctl, 0, sizeof(ctl)); + + ctl.fname = XC2028_DEFAULT_FIRMWARE; + ctl.max_len = 64; + + switch (core->boardnr) { + case CX88_BOARD_POWERCOLOR_REAL_ANGEL: + /* Doesn't work with firmware version 2.7 */ + ctl.fname = "xc3028-v25.fw"; + break; + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + ctl.scode_table = XC3028_FE_ZARLINK456; + break; + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + ctl.demod = XC3028_FE_OREN538; + break; + default: + ctl.demod = XC3028_FE_OREN538; + ctl.mts = 1; + } + + xc2028_cfg.tuner = TUNER_XC2028; + xc2028_cfg.priv = &ctl; + + info_printk(core, "Asking xc2028/3028 to load firmware %s\n", + ctl.fname); + cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg); + } } /* ------------------------------------------------------------------ */ @@ -2178,9 +2521,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board)); - printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", - core->name,pci->subsystem_vendor, - pci->subsystem_device, core->board.name, + info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + pci->subsystem_vendor, pci->subsystem_device, core->board.name, core->boardnr, card[core->nr] == core->boardnr ? "insmod option" : "autodetected"); @@ -2189,25 +2531,21 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) if (radio[core->nr] != UNSET) core->board.radio_type = radio[core->nr]; - printk(KERN_INFO "%s: TV tuner type %d, Radio tuner type %d\n", - core->name, core->board.tuner_type, core->board.radio_type); + info_printk(core, "TV tuner type %d, Radio tuner type %d\n", + core->board.tuner_type, core->board.radio_type); /* init hardware */ cx88_reset(core); cx88_card_setup_pre_i2c(core); cx88_i2c_init(core, pci); + + /* load tuner module, if needed */ + if (TUNER_ABSENT != core->board.tuner_type) + request_module("tuner"); + cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL); cx88_card_setup(core); cx88_ir_init(core, pci); return core; } - -/* ------------------------------------------------------------------ */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - * 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 - */ diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 01e2ac9..12440b9 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -47,15 +47,15 @@ MODULE_LICENSE("GPL"); /* ------------------------------------------------------------------ */ -static unsigned int core_debug = 0; +static unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); -static unsigned int nicam = 0; +static unsigned int nicam; module_param(nicam,int,0644); MODULE_PARM_DESC(nicam,"tv audio is nicam"); -static unsigned int nocomb = 0; +static unsigned int nocomb; module_param(nocomb,int,0644); MODULE_PARM_DESC(nocomb,"disable comb filter"); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index f7b41eb..cf6b9b0 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -45,13 +45,15 @@ #include "nxt200x.h" #include "cx24123.h" #include "isl6421.h" +#include "tuner-xc2028.h" +#include "tuner-xc2028-types.h" MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); MODULE_AUTHOR("Chris Pascoe "); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); @@ -235,6 +237,19 @@ static struct zl10353_config dvico_fusionhdtv_hybrid = { .no_tuner = 1, }; +static struct zl10353_config dvico_fusionhdtv_xc3028 = { + .demod_address = 0x0f, + .if2 = 45600, + .no_tuner = 1, +}; + +static struct mt352_config dvico_fusionhdtv_mt352_xc3028 = { + .demod_address = 0x0f, + .if2 = 4560, + .no_tuner = 1, + .demod_init = dvico_fusionhdtv_demod_init, +}; + static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { .demod_address = 0x0f, }; @@ -357,6 +372,40 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, return 0; } +static int cx88_pci_nano_callback(void *ptr, int command, int arg) +{ + struct cx88_core *core = ptr; + + switch (command) { + case XC2028_TUNER_RESET: + /* Send the tuner in then out of reset */ + dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg); + + switch (core->boardnr) { + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + /* GPIO-4 xc3028 tuner */ + + cx_set(MO_GP0_IO, 0x00001000); + cx_clear(MO_GP0_IO, 0x00000010); + msleep(100); + cx_set(MO_GP0_IO, 0x00000010); + msleep(100); + break; + } + + break; + case XC2028_RESET_CLK: + dprintk(1, "%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg); + break; + default: + dprintk(1, "%s: unknown command %d, arg %d\n", __FUNCTION__, + command, arg); + return -EINVAL; + } + + return 0; +} + static struct cx24123_config geniatech_dvbs_config = { .demod_address = 0x55, .set_ts_params = cx24123_set_ts_param, @@ -383,12 +432,51 @@ static struct s5h1409_config pinnacle_pctv_hd_800i_config = { .mpeg_timing = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK, }; +static struct s5h1409_config dvico_hdtv5_pci_nano_config = { + .demod_address = 0x32 >> 1, + .output_mode = S5H1409_SERIAL_OUTPUT, + .gpio = S5H1409_GPIO_OFF, + .inversion = S5H1409_INVERSION_OFF, + .status_mode = S5H1409_DEMODLOCKING, + .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, +}; + static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { .i2c_address = 0x64, .if_khz = 5380, .tuner_callback = cx88_tuner_callback, }; +static struct zl10353_config cx88_geniatech_x8000_mt = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, +}; + +static int attach_xc3028(u8 addr, struct cx8802_dev *dev) +{ + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &dev->core->i2c_adap, + .i2c_addr = addr, + .video_dev = dev->core, + }; + + fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); + if (!fe) { + printk(KERN_ERR "%s/2: xc3028 attach failed\n", + dev->core->name); + dvb_frontend_detach(dev->dvb.frontend); + dvb_unregister_frontend(dev->dvb.frontend); + dev->dvb.frontend = NULL; + return -EINVAL; + } + + printk(KERN_INFO "%s/2: xc3028 attached\n", + dev->core->name); + + return 0; +} + static int dvb_register(struct cx8802_dev *dev) { /* init struct videobuf_dvb */ @@ -514,6 +602,24 @@ static int dvb_register(struct cx8802_dev *dev) DVB_PLL_THOMSON_FE6600); } break; + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + dev->dvb.frontend = dvb_attach(zl10353_attach, + &dvico_fusionhdtv_xc3028, + &dev->core->i2c_adap); + if (dev->dvb.frontend == NULL) + dev->dvb.frontend = dvb_attach(mt352_attach, + &dvico_fusionhdtv_mt352_xc3028, + &dev->core->i2c_adap); + /* + * On this board, the demod provides the I2C bus pullup. + * We must not permit gate_ctrl to be performed, or + * the xc3028 cannot communicate on the bus. + */ + if (dev->dvb.frontend) + dev->dvb.frontend->ops.i2c_gate_ctrl = NULL; + if (attach_xc3028(0x61, dev) < 0) + return -EINVAL; + break; case CX88_BOARD_PCHDTV_HD3000: dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, &dev->core->i2c_adap); @@ -658,14 +764,56 @@ static int dvb_register(struct cx8802_dev *dev) &pinnacle_pctv_hd_800i_tuner_config); } break; + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + dev->dvb.frontend = dvb_attach(s5h1409_attach, + &dvico_hdtv5_pci_nano_config, + &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &dev->core->i2c_adap, + .i2c_addr = 0x61, + .video_dev = dev->core, + .callback = cx88_pci_nano_callback, + }; + static struct xc2028_ctrl ctl = { + .fname = "xc3028-v27.fw", + .max_len = 64, + .scode_table = OREN538, + }; + + fe = dvb_attach(xc2028_attach, + dev->dvb.frontend, &cfg); + if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) + fe->ops.tuner_ops.set_config(fe, &ctl); + } + break; + case CX88_BOARD_PINNACLE_HYBRID_PCTV: + dev->dvb.frontend = dvb_attach(zl10353_attach, + &cx88_geniatech_x8000_mt, + &dev->core->i2c_adap); + if (attach_xc3028(0x61, dev) < 0) + return -EINVAL; + break; + case CX88_BOARD_GENIATECH_X8000_MT: + dev->ts_gen_cntrl = 0x00; + + dev->dvb.frontend = dvb_attach(zl10353_attach, + &cx88_geniatech_x8000_mt, + &dev->core->i2c_adap); + if (attach_xc3028(0x61, dev) < 0) + return -EINVAL; + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); break; } if (NULL == dev->dvb.frontend) { - printk(KERN_ERR "%s/2: frontend initialization failed\n", dev->core->name); - return -1; + printk(KERN_ERR + "%s/2: frontend initialization failed\n", + dev->core->name); + return -EINVAL; } /* Ensure all frontends negotiate bus access */ @@ -744,8 +892,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) /* dvb stuff */ printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); - videobuf_queue_pci_init(&dev->dvb.dvbq, &dvb_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx88_buffer), diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 566b26a..c6b4473 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -35,11 +35,11 @@ #include "cx88.h" #include -static unsigned int i2c_debug = 0; +static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]"); -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index bb0911b..d2e42c7 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -57,7 +57,7 @@ struct cx88_IR { u32 mask_keyup; }; -static int ir_debug = 0; +static int ir_debug; module_param(ir_debug, int, 0644); /* debug level [IR] */ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index e357f41..6467ca3 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -39,7 +39,7 @@ MODULE_AUTHOR("Chris Pascoe "); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug,int,0644); MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); @@ -613,6 +613,8 @@ static int cx8802_request_acquire(struct cx8802_driver *drv) core->active_type_id != drv->type_id) return -EBUSY; + core->input = CX88_VMUX_DVB; + if (drv->advise_acquire) { mutex_lock(&drv->core->lock); diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 76e5c78..c574f45 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -53,15 +53,15 @@ #include "cx88.h" -static unsigned int audio_debug = 0; +static unsigned int audio_debug; module_param(audio_debug, int, 0644); MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]"); -static unsigned int always_analog = 0; +static unsigned int always_analog; module_param(always_analog,int,0644); MODULE_PARM_DESC(always_analog,"force analog audio out"); -static unsigned int radio_deemphasis = 0; +static unsigned int radio_deemphasis; module_param(radio_deemphasis,int,0644); MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, " "0=None, 1=50us (elsewhere), 2=75us (USA)"); diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c index d96ecfc..0943060 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/video/cx88/cx88-vbi.c @@ -11,7 +11,7 @@ static unsigned int vbibufs = 4; module_param(vbibufs,int,0644); MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32"); -static unsigned int vbi_debug = 0; +static unsigned int vbi_debug; module_param(vbi_debug,int,0644); MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 7f1931a..191577d 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -63,11 +63,11 @@ MODULE_PARM_DESC(video_nr,"video device numbers"); MODULE_PARM_DESC(vbi_nr,"vbi device numbers"); MODULE_PARM_DESC(radio_nr,"radio device numbers"); -static unsigned int video_debug = 0; +static unsigned int video_debug; module_param(video_debug,int,0644); MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); -static unsigned int irq_debug = 0; +static unsigned int irq_debug; module_param(irq_debug,int,0644); MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]"); @@ -776,14 +776,14 @@ static int video_open(struct inode *inode, struct file *file) fh->height = 240; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); - videobuf_queue_pci_init(&fh->vidq, &cx8800_video_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx88_buffer), fh); - videobuf_queue_pci_init(&fh->vbiq, &cx8800_vbi_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct cx88_buffer), @@ -1826,16 +1826,16 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, cx_set(MO_PCI_INTMSK, core->pci_irqmask); /* load and configure helper modules */ - if (TUNER_ABSENT != core->board.tuner_type) - request_module("tuner"); if (core->board.audio_chip == AUDIO_CHIP_WM8775) request_module("wm8775"); switch (core->boardnr) { case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: - request_module("ir-kbd-i2c"); request_module("rtc-isl1208"); + /* break intentionally omitted */ + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + request_module("ir-kbd-i2c"); } /* register v4l devices */ diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 37e6d2e..9df3f19 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -211,6 +211,12 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_HAUPPAUGE_HVR1300 56 #define CX88_BOARD_ADSTECH_PTV_390 57 #define CX88_BOARD_PINNACLE_PCTV_HD_800i 58 +#define CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO 59 +#define CX88_BOARD_PINNACLE_HYBRID_PCTV 60 +#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61 +#define CX88_BOARD_POWERCOLOR_REAL_ANGEL 62 +#define CX88_BOARD_GENIATECH_X8000_MT 63 +#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, diff --git a/drivers/media/video/dabfirmware.h b/drivers/media/video/dabfirmware.h index d14d803..cbd9263 100644 --- a/drivers/media/video/dabfirmware.h +++ b/drivers/media/video/dabfirmware.h @@ -1,5 +1,12 @@ /* * dabdata.h - dab usb firmware and bitstream data + * + * Copyright (C) 1999 BayCom GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that redistributions of source + * code retain the above copyright notice and this comment without + * modification. */ static INTEL_HEX_RECORD firmware[] = { diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index a5731f9..8d1f8ee 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c @@ -205,7 +205,7 @@ static void dabusb_iso_complete (struct urb *purb) /*-------------------------------------------------------------------*/ static int dabusb_alloc_buffers (pdabusb_t s) { - int buffers = 0; + int transfer_len = 0; pbuff_t b; unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE); int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe)); @@ -216,7 +216,7 @@ static int dabusb_alloc_buffers (pdabusb_t s) dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d", pipesize, packets, transfer_buffer_length); - while (buffers < (s->total_buffer_size << 10)) { + while (transfer_len < (s->total_buffer_size << 10)) { b = kzalloc(sizeof (buff_t), GFP_KERNEL); if (!b) { err("kzalloc(sizeof(buff_t))==NULL"); @@ -251,10 +251,10 @@ static int dabusb_alloc_buffers (pdabusb_t s) b->purb->iso_frame_desc[i].length = pipesize; } - buffers += transfer_buffer_length; + transfer_len += transfer_buffer_length; list_add_tail (&b->buff_list, &s->free_buff_list); } - s->got_mem = buffers; + s->got_mem = transfer_len; return 0; diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c index 566e479..24ce5c3 100644 --- a/drivers/media/video/dpc7146.c +++ b/drivers/media/video/dpc7146.c @@ -54,11 +54,11 @@ #define DPC_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "debug verbosity"); -static int dpc_num = 0; +static int dpc_num; #define DPC_INPUTS 2 static struct v4l2_input dpc_inputs[DPC_INPUTS] = { diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 7d1537c..bc06abd 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -31,7 +31,7 @@ /* #define ENABLE_DEBUG_ISOC_FRAMES */ -static unsigned int core_debug = 0; +static unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); @@ -40,7 +40,7 @@ MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) -static unsigned int reg_debug = 0; +static unsigned int reg_debug; module_param(reg_debug,int,0644); MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); @@ -49,7 +49,7 @@ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) -static unsigned int isoc_debug = 0; +static unsigned int isoc_debug; module_param(isoc_debug,int,0644); MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index cacd04d..c3d98d8 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -33,11 +33,11 @@ /* ----------------------------------------------------------- */ -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); -static unsigned int i2c_debug = 0; +static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 4abe670..c8264f4 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -74,7 +74,7 @@ MODULE_PARM_DESC(video_nr, "video device numbers"); MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); MODULE_PARM_DESC(radio_nr, "radio device numbers"); -static unsigned int video_debug = 0; +static unsigned int video_debug; module_param(video_debug,int,0644); MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 06b6a3a..32ebb71 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -2538,7 +2538,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) { struct usb_device *udev = interface_to_usbdev(intf); struct et61x251_device* cam; - static unsigned int dev_nr = 0; + static unsigned int dev_nr; unsigned int i; int err = 0; diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index c7fed34..352f84d 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c @@ -25,12 +25,12 @@ #include -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "debug verbosity"); /* global variables */ -static int hexium_num = 0; +static int hexium_num; #define HEXIUM_GEMINI 4 #define HEXIUM_GEMINI_DUAL 5 diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index 137c473..8d3c148 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -25,12 +25,12 @@ #include -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "debug verbosity"); /* global variables */ -static int hexium_num = 0; +static int hexium_num; #define HEXIUM_HV_PCI6_ORION 1 #define HEXIUM_ORION_1SVHS_3BNC 2 diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 9851987..5084db2 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -51,7 +51,7 @@ static int debug; module_param(debug, int, 0644); /* debug level (0,1,2) */ -static int hauppauge = 0; +static int hauppauge; module_param(hauppauge, int, 0644); /* Choose Hauppauge remote */ MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)"); diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index d42f120..01d96ce 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -54,7 +54,6 @@ #include "ivtv-vbi.h" #include "ivtv-routing.h" #include "ivtv-gpio.h" -#include "ivtv-yuv.h" #include #include @@ -127,11 +126,11 @@ static int dec_mpg_buffers = IVTV_DEFAULT_DEC_MPG_BUFFERS; static int dec_yuv_buffers = IVTV_DEFAULT_DEC_YUV_BUFFERS; static int dec_vbi_buffers = IVTV_DEFAULT_DEC_VBI_BUFFERS; -static int ivtv_yuv_mode = 0; -static int ivtv_yuv_threshold=-1; +static int ivtv_yuv_mode; +static int ivtv_yuv_threshold = -1; static int ivtv_pci_latency = 1; -int ivtv_debug = 0; +int ivtv_debug; static int newi2c = -1; @@ -709,6 +708,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) itv->yuv_info.lace_mode = ivtv_yuv_mode; itv->yuv_info.lace_threshold = ivtv_yuv_threshold; itv->yuv_info.max_frames_buffered = 3; + itv->yuv_info.track_osd = 1; return 0; } @@ -1053,9 +1053,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev, goto free_io; } - /* Check yuv output filter table */ - if (itv->has_cx23415) ivtv_yuv_filter_check(itv); - ivtv_gpio_init(itv); /* active i2c */ diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 536140f..ba06e81 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -456,6 +456,8 @@ struct yuv_playback_info int v_filter_2; int h_filter; + u8 track_osd; /* Should yuv output track the OSD size & position */ + u32 osd_x_offset; u32 osd_y_offset; diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c index 425eb10..6dba55b 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ b/drivers/media/video/ivtv/ivtv-firmware.c @@ -22,6 +22,7 @@ #include "ivtv-driver.h" #include "ivtv-mailbox.h" #include "ivtv-firmware.h" +#include "ivtv-yuv.h" #include #define IVTV_MASK_SPU_ENABLE 0xFFFFFFFE @@ -225,11 +226,14 @@ int ivtv_firmware_init(struct ivtv *itv) return 0; itv->dec_mbox.mbox = ivtv_search_mailbox(itv->dec_mem, IVTV_DECODER_SIZE); - if (itv->dec_mbox.mbox == NULL) + if (itv->dec_mbox.mbox == NULL) { IVTV_ERR("Decoder mailbox not found\n"); - else if (itv->has_cx23415 && ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0)) { + } else if (itv->has_cx23415 && ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0)) { IVTV_ERR("Decoder firmware dead!\n"); itv->dec_mbox.mbox = NULL; + } else { + /* Firmware okay, so check yuv output filter table */ + ivtv_yuv_filter_check(itv); } return itv->dec_mbox.mbox ? 0 : -ENODEV; } diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index edef2a5..1beb296 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -712,6 +712,7 @@ static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg) int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg) { struct ivtv_open_id *id = NULL; + struct yuv_playback_info *yi = &itv->yuv_info; u32 data[CX2341X_MBOX_MAX_DATA]; int streamtype = 0; @@ -827,8 +828,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void case VIDIOC_CROPCAP: { struct v4l2_cropcap *cropcap = arg; - if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; cropcap->bounds.top = cropcap->bounds.left = 0; cropcap->bounds.width = 720; @@ -837,8 +837,14 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10; cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11; } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { - cropcap->bounds.width = itv->yuv_info.osd_full_w; - cropcap->bounds.height = itv->yuv_info.osd_full_h; + if (yi->track_osd) { + cropcap->bounds.width = yi->osd_full_w; + cropcap->bounds.height = yi->osd_full_h; + } else { + cropcap->bounds.width = 720; + cropcap->bounds.height = + itv->is_out_50hz ? 576 : 480; + } cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; } else { @@ -856,7 +862,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { - itv->yuv_info.main_rect = crop->c; + yi->main_rect = crop->c; return 0; } else { if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, @@ -867,9 +873,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void } return -EINVAL; } - if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - return itv->video_dec_func(itv, VIDIOC_S_CROP, arg); + return -EINVAL; } case VIDIOC_G_CROP: { @@ -878,14 +882,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) - crop->c = itv->yuv_info.main_rect; + crop->c = yi->main_rect; else crop->c = itv->main_rect; return 0; } - if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - return itv->video_dec_func(itv, VIDIOC_G_CROP, arg); + return -EINVAL; } case VIDIOC_ENUM_FMT: { @@ -1070,11 +1072,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void itv->main_rect.height = itv->params.height; ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, 720, itv->main_rect.height, 0, 0); - itv->yuv_info.main_rect = itv->main_rect; + yi->main_rect = itv->main_rect; if (!itv->osd_info) { - itv->yuv_info.osd_full_w = 720; - itv->yuv_info.osd_full_h = - itv->is_out_50hz ? 576 : 480; + yi->osd_full_w = 720; + yi->osd_full_h = itv->is_out_50hz ? 576 : 480; } } break; @@ -1272,6 +1273,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void else fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; } + if (yi->track_osd) + fb->flags |= V4L2_FBUF_FLAG_OVERLAY; break; } @@ -1285,6 +1288,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0; itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; ivtv_set_osd_alpha(itv); + yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0; break; } diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index 65604dd..a329c46 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c @@ -384,6 +384,8 @@ static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s) ivtv_stream_sync_for_device(s); write_reg(s->sg_handle, IVTV_REG_ENCDMAADDR); write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER); + itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); + add_timer(&itv->dma_timer); } static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s) @@ -398,6 +400,8 @@ static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s) ivtv_stream_sync_for_device(s); write_reg(s->sg_handle, IVTV_REG_DECDMAADDR); write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER); + itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); + add_timer(&itv->dma_timer); } /* start the encoder DMA */ @@ -459,8 +463,6 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) ivtv_dma_enc_start_xfer(s); set_bit(IVTV_F_I_DMA, &itv->i_flags); itv->cur_dma_stream = s->type; - itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); - add_timer(&itv->dma_timer); } } @@ -481,8 +483,6 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s) ivtv_dma_dec_start_xfer(s); set_bit(IVTV_F_I_DMA, &itv->i_flags); itv->cur_dma_stream = s->type; - itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); - add_timer(&itv->dma_timer); } static void ivtv_irq_dma_read(struct ivtv *itv) @@ -492,10 +492,11 @@ static void ivtv_irq_dma_read(struct ivtv *itv) int hw_stream_type = 0; IVTV_DEBUG_HI_IRQ("DEC DMA READ\n"); - if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0) { - del_timer(&itv->dma_timer); + + del_timer(&itv->dma_timer); + + if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0) return; - } if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { s = &itv->streams[itv->cur_dma_stream]; @@ -543,7 +544,6 @@ static void ivtv_irq_dma_read(struct ivtv *itv) } wake_up(&s->waitq); } - del_timer(&itv->dma_timer); clear_bit(IVTV_F_I_UDMA, &itv->i_flags); clear_bit(IVTV_F_I_DMA, &itv->i_flags); itv->cur_dma_stream = -1; @@ -557,10 +557,12 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv) ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data); IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream); - if (itv->cur_dma_stream < 0) { - del_timer(&itv->dma_timer); + + del_timer(&itv->dma_timer); + + if (itv->cur_dma_stream < 0) return; - } + s = &itv->streams[itv->cur_dma_stream]; ivtv_stream_sync_for_cpu(s); @@ -585,7 +587,6 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv) ivtv_dma_enc_start_xfer(s); return; } - del_timer(&itv->dma_timer); clear_bit(IVTV_F_I_DMA, &itv->i_flags); itv->cur_dma_stream = -1; dma_post(s); diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index 8518348..393d917 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c @@ -718,9 +718,11 @@ static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f) f->src_w -= (osd_scale * osd_crop) >> 16; } - /* The OSD can be moved. Track to it */ - f->dst_x += itv->yuv_info.osd_x_offset; - f->dst_y += itv->yuv_info.osd_y_offset; + if (itv->yuv_info.track_osd) { + /* The OSD can be moved. Track to it */ + f->dst_x += itv->yuv_info.osd_x_offset; + f->dst_y += itv->yuv_info.osd_y_offset; + } /* Width & height for both src & dst must be even. Same for coordinates. */ @@ -792,11 +794,19 @@ void ivtv_yuv_work_handler(struct ivtv *itv) IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame); f = yi->new_frame_info[frame]; - /* Update the osd pan info */ - f.pan_x = yi->osd_x_pan; - f.pan_y = yi->osd_y_pan; - f.vis_w = yi->osd_vis_w; - f.vis_h = yi->osd_vis_h; + if (yi->track_osd) { + /* Snapshot the osd pan info */ + f.pan_x = yi->osd_x_pan; + f.pan_y = yi->osd_y_pan; + f.vis_w = yi->osd_vis_w; + f.vis_h = yi->osd_vis_h; + } else { + /* Not tracking the osd, so assume full screen */ + f.pan_x = 0; + f.pan_y = 0; + f.vis_w = 720; + f.vis_h = yi->decode_height; + } /* Calculate the display window coordinates. Exit if nothing left */ if (!(yuv_update = ivtv_yuv_window_setup(itv, &f))) @@ -914,7 +924,7 @@ static void ivtv_yuv_init(struct ivtv *itv) } /* Get next available yuv buffer on PVR350 */ -void ivtv_yuv_next_free(struct ivtv *itv) +static void ivtv_yuv_next_free(struct ivtv *itv) { int draw, display; struct yuv_playback_info *yi = &itv->yuv_info; @@ -937,7 +947,7 @@ void ivtv_yuv_next_free(struct ivtv *itv) } /* Set up frame according to ivtv_dma_frame parameters */ -void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args) +static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args) { struct yuv_playback_info *yi = &itv->yuv_info; u8 frame = yi->draw_frame; @@ -965,12 +975,6 @@ void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args) /* Are we going to offset the Y plane */ nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0; - /* Snapshot the osd pan info */ - nf->pan_x = yi->osd_x_pan; - nf->pan_y = yi->osd_y_pan; - nf->vis_w = yi->osd_vis_w; - nf->vis_h = yi->osd_vis_h; - nf->update = 0; nf->interlaced_y = 0; nf->interlaced_uv = 0; @@ -1042,7 +1046,7 @@ void ivtv_yuv_frame_complete(struct ivtv *itv) (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS); } -int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args) +static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args) { DEFINE_WAIT(wait); int rc = 0; diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 3d51fa0..caa9a7a 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -789,7 +789,7 @@ static irqreturn_t meye_irq(int irq, void *dev_id) { u32 v; int reqnr; - static int sequence = 0; + static int sequence; v = mchip_read(MCHIP_MM_INTA); @@ -1239,6 +1239,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, c->default_value = 48; c->flags = 0; break; + case V4L2_CID_MEYE_SHARPNESS: case V4L2_CID_SHARPNESS: c->type = V4L2_CTRL_TYPE_INTEGER; strcpy(c->name, "Sharpness"); @@ -1246,7 +1247,12 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, c->maximum = 63; c->step = 1; c->default_value = 32; - c->flags = 0; + + /* Continue to report legacy private SHARPNESS ctrl but + * say it is disabled in preference to ctrl in the spec + */ + c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 : + V4L2_CTRL_FLAG_DISABLED; break; case V4L2_CID_PICTURE: c->type = V4L2_CTRL_TYPE_INTEGER; @@ -1312,6 +1318,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, meye.params.agc = c->value; break; case V4L2_CID_SHARPNESS: + case V4L2_CID_MEYE_SHARPNESS: sony_pic_camera_command( SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value); meye.params.sharpness = c->value; @@ -1356,6 +1363,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, c->value = meye.params.agc; break; case V4L2_CID_SHARPNESS: + case V4L2_CID_MEYE_SHARPNESS: c->value = meye.params.sharpness; break; case V4L2_CID_PICTURE: diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index 58bab65..fbcb282 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c @@ -10,12 +10,10 @@ #include "tuner-i2c.h" #include "mt20xx.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "mt20xx" - /* ---------------------------------------------------------------------- */ static unsigned int optimize_vco = 1; @@ -24,7 +22,7 @@ module_param(optimize_vco, int, 0644); static unsigned int tv_antenna = 1; module_param(tv_antenna, int, 0644); -static unsigned int radio_antenna = 0; +static unsigned int radio_antenna; module_param(radio_antenna, int, 0644); /* ---------------------------------------------------------------------- */ @@ -611,6 +609,7 @@ struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "mt20xx"; //priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ @@ -647,7 +646,7 @@ struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, default: tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n", name); - return 0; + return NULL; } strlcpy(fe->ops.tuner_ops.info.name, name, diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c new file mode 100644 index 0000000..4ad8343 --- /dev/null +++ b/drivers/media/video/mt9m001.c @@ -0,0 +1,703 @@ +/* + * Driver for MT9M001 CMOS Image Sensor from Micron + * + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_MT9M001_PCA9536_SWITCH +#include +#endif + +/* mt9m001 i2c address 0x5d + * The platform has to define i2c_board_info + * and call i2c_register_board_info() */ + +/* mt9m001 selected register addresses */ +#define MT9M001_CHIP_VERSION 0x00 +#define MT9M001_ROW_START 0x01 +#define MT9M001_COLUMN_START 0x02 +#define MT9M001_WINDOW_HEIGHT 0x03 +#define MT9M001_WINDOW_WIDTH 0x04 +#define MT9M001_HORIZONTAL_BLANKING 0x05 +#define MT9M001_VERTICAL_BLANKING 0x06 +#define MT9M001_OUTPUT_CONTROL 0x07 +#define MT9M001_SHUTTER_WIDTH 0x09 +#define MT9M001_FRAME_RESTART 0x0b +#define MT9M001_SHUTTER_DELAY 0x0c +#define MT9M001_RESET 0x0d +#define MT9M001_READ_OPTIONS1 0x1e +#define MT9M001_READ_OPTIONS2 0x20 +#define MT9M001_GLOBAL_GAIN 0x35 +#define MT9M001_CHIP_ENABLE 0xF1 + +static const struct soc_camera_data_format mt9m001_colour_formats[] = { + /* Order important: first natively supported, + * second supported with a GPIO extender */ + { + .name = "Bayer (sRGB) 10 bit", + .depth = 10, + .fourcc = V4L2_PIX_FMT_SBGGR16, + .colorspace = V4L2_COLORSPACE_SRGB, + }, { + .name = "Bayer (sRGB) 8 bit", + .depth = 8, + .fourcc = V4L2_PIX_FMT_SBGGR8, + .colorspace = V4L2_COLORSPACE_SRGB, + } +}; + +static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { + /* Order important - see above */ + { + .name = "Monochrome 10 bit", + .depth = 10, + .fourcc = V4L2_PIX_FMT_Y16, + }, { + .name = "Monochrome 8 bit", + .depth = 8, + .fourcc = V4L2_PIX_FMT_GREY, + }, +}; + +struct mt9m001 { + struct i2c_client *client; + struct soc_camera_device icd; + int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ + int switch_gpio; + unsigned char autoexposure; + unsigned char datawidth; +}; + +static int reg_read(struct soc_camera_device *icd, const u8 reg) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = mt9m001->client; + s32 data = i2c_smbus_read_word_data(client, reg); + return data < 0 ? data : swab16(data); +} + +static int reg_write(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + return i2c_smbus_write_word_data(mt9m001->client, reg, swab16(data)); +} + +static int reg_set(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret | data); +} + +static int reg_clear(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret & ~data); +} + +static int mt9m001_init(struct soc_camera_device *icd) +{ + int ret; + + /* Disable chip, synchronous option update */ + dev_dbg(icd->vdev->dev, "%s\n", __FUNCTION__); + + ret = reg_write(icd, MT9M001_RESET, 1); + if (ret >= 0) + ret = reg_write(icd, MT9M001_RESET, 0); + if (ret >= 0) + ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); + + return ret >= 0 ? 0 : -EIO; +} + +static int mt9m001_release(struct soc_camera_device *icd) +{ + /* Disable the chip */ + reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); + return 0; +} + +static int mt9m001_start_capture(struct soc_camera_device *icd) +{ + /* Switch to master "normal" mode */ + if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 2) < 0) + return -EIO; + return 0; +} + +static int mt9m001_stop_capture(struct soc_camera_device *icd) +{ + /* Stop sensor readout */ + if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 0) < 0) + return -EIO; + return 0; +} + +static int bus_switch_request(struct mt9m001 *mt9m001, + struct soc_camera_link *icl) +{ +#ifdef CONFIG_MT9M001_PCA9536_SWITCH + int ret; + unsigned int gpio = icl->gpio; + + if (gpio_is_valid(gpio)) { + /* We have a data bus switch. */ + ret = gpio_request(gpio, "mt9m001"); + if (ret < 0) { + dev_err(&mt9m001->client->dev, "Cannot get GPIO %u\n", + gpio); + return ret; + } + + ret = gpio_direction_output(gpio, 0); + if (ret < 0) { + dev_err(&mt9m001->client->dev, + "Cannot set GPIO %u to output\n", gpio); + gpio_free(gpio); + return ret; + } + } + + mt9m001->switch_gpio = gpio; +#else + mt9m001->switch_gpio = -EINVAL; +#endif + return 0; +} + +static void bus_switch_release(struct mt9m001 *mt9m001) +{ +#ifdef CONFIG_MT9M001_PCA9536_SWITCH + if (gpio_is_valid(mt9m001->switch_gpio)) + gpio_free(mt9m001->switch_gpio); +#endif +} + +static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit) +{ +#ifdef CONFIG_MT9M001_PCA9536_SWITCH + if (!gpio_is_valid(mt9m001->switch_gpio)) + return -ENODEV; + + gpio_set_value_cansleep(mt9m001->switch_gpio, go8bit); + return 0; +#else + return -ENODEV; +#endif +} + +static int mt9m001_set_capture_format(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | + IS_DATAWIDTH_8); + int ret; + const u16 hblank = 9, vblank = 25; + + /* MT9M001 has all capture_format parameters fixed */ + if (!(flags & IS_MASTER) || + !(flags & IS_PCLK_SAMPLE_RISING) || + !(flags & IS_HSYNC_ACTIVE_HIGH) || + !(flags & IS_VSYNC_ACTIVE_HIGH)) + return -EINVAL; + + /* Only one width bit may be set */ + if (!is_power_of_2(width_flag)) + return -EINVAL; + + if ((mt9m001->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || + (mt9m001->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || + (mt9m001->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { + /* Well, we actually only can do 10 or 8 bits... */ + if (width_flag == IS_DATAWIDTH_9) + return -EINVAL; + ret = bus_switch_act(mt9m001, + width_flag == IS_DATAWIDTH_8); + if (ret < 0) + return ret; + + mt9m001->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; + } + + /* Blanking and start values - default... */ + ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); + if (ret >= 0) + ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank); + + /* The caller provides a supported format, as verified per + * call to icd->try_fmt_cap() */ + if (ret >= 0) + ret = reg_write(icd, MT9M001_COLUMN_START, rect->left); + if (ret >= 0) + ret = reg_write(icd, MT9M001_ROW_START, rect->top); + if (ret >= 0) + ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1); + if (ret >= 0) + ret = reg_write(icd, MT9M001_WINDOW_HEIGHT, + rect->height + icd->y_skip_top - 1); + if (ret >= 0 && mt9m001->autoexposure) { + ret = reg_write(icd, MT9M001_SHUTTER_WIDTH, + rect->height + icd->y_skip_top + vblank); + if (ret >= 0) { + const struct v4l2_queryctrl *qctrl = + soc_camera_find_qctrl(icd->ops, + V4L2_CID_EXPOSURE); + icd->exposure = (524 + (rect->height + icd->y_skip_top + + vblank - 1) * + (qctrl->maximum - qctrl->minimum)) / + 1048 + qctrl->minimum; + } + } + + return ret < 0 ? ret : 0; +} + +static int mt9m001_try_fmt_cap(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + if (f->fmt.pix.height < 32 + icd->y_skip_top) + f->fmt.pix.height = 32 + icd->y_skip_top; + if (f->fmt.pix.height > 1024 + icd->y_skip_top) + f->fmt.pix.height = 1024 + icd->y_skip_top; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > 1280) + f->fmt.pix.width = 1280; + f->fmt.pix.width &= ~0x01; /* has to be even, unsure why was ~3 */ + + return 0; +} + +static int mt9m001_get_chip_id(struct soc_camera_device *icd, + struct v4l2_chip_ident *id) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + + if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + return -EINVAL; + + if (id->match_chip != mt9m001->client->addr) + return -ENODEV; + + id->ident = mt9m001->model; + id->revision = 0; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int mt9m001_get_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9m001->client->addr) + return -ENODEV; + + reg->val = reg_read(icd, reg->reg); + + if (reg->val > 0xffff) + return -EIO; + + return 0; +} + +static int mt9m001_set_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9m001->client->addr) + return -ENODEV; + + if (reg_write(icd, reg->reg, reg->val) < 0) + return -EIO; + + return 0; +} +#endif + +static unsigned int mt9m001_get_datawidth(struct soc_camera_device *icd) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + return mt9m001->datawidth; +} + +const struct v4l2_queryctrl mt9m001_controls[] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Vertically", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = 127, + .step = 1, + .default_value = 64, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 1, + .maximum = 255, + .step = 1, + .default_value = 255, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_EXPOSURE_AUTO, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Automatic Exposure", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + } +}; + +static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl); +static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl); + +static struct soc_camera_ops mt9m001_ops = { + .owner = THIS_MODULE, + .init = mt9m001_init, + .release = mt9m001_release, + .start_capture = mt9m001_start_capture, + .stop_capture = mt9m001_stop_capture, + .set_capture_format = mt9m001_set_capture_format, + .try_fmt_cap = mt9m001_try_fmt_cap, + .formats = NULL, /* Filled in later depending on the */ + .num_formats = 0, /* camera type and data widths */ + .get_datawidth = mt9m001_get_datawidth, + .controls = mt9m001_controls, + .num_controls = ARRAY_SIZE(mt9m001_controls), + .get_control = mt9m001_get_control, + .set_control = mt9m001_set_control, + .get_chip_id = mt9m001_get_chip_id, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .get_register = mt9m001_get_register, + .set_register = mt9m001_set_register, +#endif +}; + +static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + int data; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + data = reg_read(icd, MT9M001_READ_OPTIONS2); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x8000); + break; + case V4L2_CID_EXPOSURE_AUTO: + ctrl->value = mt9m001->autoexposure; + break; + } + return 0; +} + +static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + const struct v4l2_queryctrl *qctrl; + int data; + + qctrl = soc_camera_find_qctrl(&mt9m001_ops, ctrl->id); + + if (!qctrl) + return -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + if (ctrl->value) + data = reg_set(icd, MT9M001_READ_OPTIONS2, 0x8000); + else + data = reg_clear(icd, MT9M001_READ_OPTIONS2, 0x8000); + if (data < 0) + return -EIO; + break; + case V4L2_CID_GAIN: + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + /* See Datasheet Table 7, Gain settings. */ + if (ctrl->value <= qctrl->default_value) { + /* Pack it into 0..1 step 0.125, register values 0..8 */ + unsigned long range = qctrl->default_value - qctrl->minimum; + data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; + + dev_dbg(&icd->dev, "Setting gain %d\n", data); + data = reg_write(icd, MT9M001_GLOBAL_GAIN, data); + if (data < 0) + return -EIO; + } else { + /* Pack it into 1.125..15 variable step, register values 9..67 */ + /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */ + unsigned long range = qctrl->maximum - qctrl->default_value - 1; + unsigned long gain = ((ctrl->value - qctrl->default_value - 1) * + 111 + range / 2) / range + 9; + + if (gain <= 32) + data = gain; + else if (gain <= 64) + data = ((gain - 32) * 16 + 16) / 32 + 80; + else + data = ((gain - 64) * 7 + 28) / 56 + 96; + + dev_dbg(&icd->dev, "Setting gain from %d to %d\n", + reg_read(icd, MT9M001_GLOBAL_GAIN), data); + data = reg_write(icd, MT9M001_GLOBAL_GAIN, data); + if (data < 0) + return -EIO; + } + + /* Success */ + icd->gain = ctrl->value; + break; + case V4L2_CID_EXPOSURE: + /* mt9m001 has maximum == default */ + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + else { + unsigned long range = qctrl->maximum - qctrl->minimum; + unsigned long shutter = ((ctrl->value - qctrl->minimum) * 1048 + + range / 2) / range + 1; + + dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n", + reg_read(icd, MT9M001_SHUTTER_WIDTH), shutter); + if (reg_write(icd, MT9M001_SHUTTER_WIDTH, shutter) < 0) + return -EIO; + icd->exposure = ctrl->value; + mt9m001->autoexposure = 0; + } + break; + case V4L2_CID_EXPOSURE_AUTO: + if (ctrl->value) { + const u16 vblank = 25; + if (reg_write(icd, MT9M001_SHUTTER_WIDTH, icd->height + + icd->y_skip_top + vblank) < 0) + return -EIO; + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); + icd->exposure = (524 + (icd->height + icd->y_skip_top + vblank - 1) * + (qctrl->maximum - qctrl->minimum)) / + 1048 + qctrl->minimum; + mt9m001->autoexposure = 1; + } else + mt9m001->autoexposure = 0; + break; + } + return 0; +} + +/* Interface active, can use i2c. If it fails, it can indeed mean, that + * this wasn't our capture interface, so, we wait for the right one */ +static int mt9m001_video_probe(struct soc_camera_device *icd) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + s32 data; + int ret; + + /* We must have a parent by now. And it cannot be a wrong one. + * So this entire test is completely redundant. */ + if (!icd->dev.parent || + to_soc_camera_host(icd->dev.parent)->nr != icd->iface) + return -ENODEV; + + /* Enable the chip */ + data = reg_write(&mt9m001->icd, MT9M001_CHIP_ENABLE, 1); + dev_dbg(&icd->dev, "write: %d\n", data); + + /* Read out the chip version register */ + data = reg_read(icd, MT9M001_CHIP_VERSION); + + /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ + switch (data) { + case 0x8411: + case 0x8421: + mt9m001->model = V4L2_IDENT_MT9M001C12ST; + mt9m001_ops.formats = mt9m001_colour_formats; + if (mt9m001->client->dev.platform_data) + mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_colour_formats); + else + mt9m001_ops.num_formats = 1; + break; + case 0x8431: + mt9m001->model = V4L2_IDENT_MT9M001C12STM; + mt9m001_ops.formats = mt9m001_monochrome_formats; + if (mt9m001->client->dev.platform_data) + mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_monochrome_formats); + else + mt9m001_ops.num_formats = 1; + break; + default: + ret = -ENODEV; + dev_err(&icd->dev, + "No MT9M001 chip detected, register read %x\n", data); + goto ei2c; + } + + dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, + data == 0x8431 ? "C12STM" : "C12ST"); + + /* Now that we know the model, we can start video */ + ret = soc_camera_video_start(icd); + if (ret) + goto eisis; + + return 0; + +eisis: +ei2c: + return ret; +} + +static void mt9m001_video_remove(struct soc_camera_device *icd) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr, + mt9m001->icd.dev.parent, mt9m001->icd.vdev); + soc_camera_video_stop(&mt9m001->icd); +} + +static int mt9m001_probe(struct i2c_client *client) +{ + struct mt9m001 *mt9m001; + struct soc_camera_device *icd; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl = client->dev.platform_data; + int ret; + + if (!icl) { + dev_err(&client->dev, "MT9M001 driver needs platform data\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { + dev_warn(&adapter->dev, + "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); + return -EIO; + } + + mt9m001 = kzalloc(sizeof(struct mt9m001), GFP_KERNEL); + if (!mt9m001) + return -ENOMEM; + + mt9m001->client = client; + i2c_set_clientdata(client, mt9m001); + + /* Second stage probe - when a capture adapter is there */ + icd = &mt9m001->icd; + icd->probe = mt9m001_video_probe; + icd->remove = mt9m001_video_remove; + icd->ops = &mt9m001_ops; + icd->control = &client->dev; + icd->x_min = 20; + icd->y_min = 12; + icd->x_current = 20; + icd->y_current = 12; + icd->width_min = 48; + icd->width_max = 1280; + icd->height_min = 32; + icd->height_max = 1024; + icd->y_skip_top = 1; + icd->iface = icl->bus_id; + /* Default datawidth - this is the only width this camera (normally) + * supports. It is only with extra logic that it can support + * other widths. Therefore it seems to be a sensible default. */ + mt9m001->datawidth = 10; + /* Simulated autoexposure. If enabled, we calculate shutter width + * ourselves in the driver based on vertical blanking and frame width */ + mt9m001->autoexposure = 1; + + ret = bus_switch_request(mt9m001, icl); + if (ret) + goto eswinit; + + ret = soc_camera_device_register(icd); + if (ret) + goto eisdr; + + return 0; + +eisdr: + bus_switch_release(mt9m001); +eswinit: + kfree(mt9m001); + return ret; +} + +static int mt9m001_remove(struct i2c_client *client) +{ + struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + + soc_camera_device_unregister(&mt9m001->icd); + bus_switch_release(mt9m001); + kfree(mt9m001); + + return 0; +} + +static struct i2c_driver mt9m001_i2c_driver = { + .driver = { + .name = "mt9m001", + }, + .probe = mt9m001_probe, + .remove = mt9m001_remove, +}; + +static int __init mt9m001_mod_init(void) +{ + return i2c_add_driver(&mt9m001_i2c_driver); +} + +static void __exit mt9m001_mod_exit(void) +{ + i2c_del_driver(&mt9m001_i2c_driver); +} + +module_init(mt9m001_mod_init); +module_exit(mt9m001_mod_exit); + +MODULE_DESCRIPTION("Micron MT9M001 Camera driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c new file mode 100644 index 0000000..d677344 --- /dev/null +++ b/drivers/media/video/mt9v022.c @@ -0,0 +1,819 @@ +/* + * Driver for MT9V022 CMOS Image Sensor from Micron + * + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_MT9M001_PCA9536_SWITCH +#include +#endif + +/* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c + * The platform has to define i2c_board_info + * and call i2c_register_board_info() */ + +static char *sensor_type; +module_param(sensor_type, charp, S_IRUGO); +MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"\n"); + +/* mt9v022 selected register addresses */ +#define MT9V022_CHIP_VERSION 0x00 +#define MT9V022_COLUMN_START 0x01 +#define MT9V022_ROW_START 0x02 +#define MT9V022_WINDOW_HEIGHT 0x03 +#define MT9V022_WINDOW_WIDTH 0x04 +#define MT9V022_HORIZONTAL_BLANKING 0x05 +#define MT9V022_VERTICAL_BLANKING 0x06 +#define MT9V022_CHIP_CONTROL 0x07 +#define MT9V022_SHUTTER_WIDTH1 0x08 +#define MT9V022_SHUTTER_WIDTH2 0x09 +#define MT9V022_SHUTTER_WIDTH_CTRL 0x0a +#define MT9V022_TOTAL_SHUTTER_WIDTH 0x0b +#define MT9V022_RESET 0x0c +#define MT9V022_READ_MODE 0x0d +#define MT9V022_MONITOR_MODE 0x0e +#define MT9V022_PIXEL_OPERATION_MODE 0x0f +#define MT9V022_LED_OUT_CONTROL 0x1b +#define MT9V022_ADC_MODE_CONTROL 0x1c +#define MT9V022_ANALOG_GAIN 0x34 +#define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47 +#define MT9V022_PIXCLK_FV_LV 0x74 +#define MT9V022_DIGITAL_TEST_PATTERN 0x7f +#define MT9V022_AEC_AGC_ENABLE 0xAF +#define MT9V022_MAX_TOTAL_SHUTTER_WIDTH 0xBD + +/* Progressive scan, master, defaults */ +#define MT9V022_CHIP_CONTROL_DEFAULT 0x188 + +static const struct soc_camera_data_format mt9v022_colour_formats[] = { + /* Order important: first natively supported, + * second supported with a GPIO extender */ + { + .name = "Bayer (sRGB) 10 bit", + .depth = 10, + .fourcc = V4L2_PIX_FMT_SBGGR16, + .colorspace = V4L2_COLORSPACE_SRGB, + }, { + .name = "Bayer (sRGB) 8 bit", + .depth = 8, + .fourcc = V4L2_PIX_FMT_SBGGR8, + .colorspace = V4L2_COLORSPACE_SRGB, + } +}; + +static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { + /* Order important - see above */ + { + .name = "Monochrome 10 bit", + .depth = 10, + .fourcc = V4L2_PIX_FMT_Y16, + }, { + .name = "Monochrome 8 bit", + .depth = 8, + .fourcc = V4L2_PIX_FMT_GREY, + }, +}; + +struct mt9v022 { + struct i2c_client *client; + struct soc_camera_device icd; + int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ + int switch_gpio; + u16 chip_control; + unsigned char datawidth; +}; + +static int reg_read(struct soc_camera_device *icd, const u8 reg) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = mt9v022->client; + s32 data = i2c_smbus_read_word_data(client, reg); + return data < 0 ? data : swab16(data); +} + +static int reg_write(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + return i2c_smbus_write_word_data(mt9v022->client, reg, swab16(data)); +} + +static int reg_set(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret | data); +} + +static int reg_clear(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret & ~data); +} + +static int mt9v022_init(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + int ret; + + /* Almost the default mode: master, parallel, simultaneous, and an + * undocumented bit 0x200, which is present in table 7, but not in 8, + * plus snapshot mode to disable scan for now */ + mt9v022->chip_control |= 0x10; + ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); + if (ret >= 0) + reg_write(icd, MT9V022_READ_MODE, 0x300); + + /* All defaults */ + if (ret >= 0) + /* AEC, AGC on */ + ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3); + if (ret >= 0) + ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); + if (ret >= 0) + /* default - auto */ + ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1); + if (ret >= 0) + ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0); + + return ret >= 0 ? 0 : -EIO; +} + +static int mt9v022_release(struct soc_camera_device *icd) +{ + /* Nothing? */ + return 0; +} + +static int mt9v022_start_capture(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + /* Switch to master "normal" mode */ + mt9v022->chip_control &= ~0x10; + if (reg_write(icd, MT9V022_CHIP_CONTROL, + mt9v022->chip_control) < 0) + return -EIO; + return 0; +} + +static int mt9v022_stop_capture(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + /* Switch to snapshot mode */ + mt9v022->chip_control |= 0x10; + if (reg_write(icd, MT9V022_CHIP_CONTROL, + mt9v022->chip_control) < 0) + return -EIO; + return 0; +} + +static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *icl) +{ +#ifdef CONFIG_MT9V022_PCA9536_SWITCH + int ret; + unsigned int gpio = icl->gpio; + + if (gpio_is_valid(gpio)) { + /* We have a data bus switch. */ + ret = gpio_request(gpio, "mt9v022"); + if (ret < 0) { + dev_err(&mt9v022->client->dev, "Cannot get GPIO %u\n", gpio); + return ret; + } + + ret = gpio_direction_output(gpio, 0); + if (ret < 0) { + dev_err(&mt9v022->client->dev, + "Cannot set GPIO %u to output\n", gpio); + gpio_free(gpio); + return ret; + } + } + + mt9v022->switch_gpio = gpio; +#else + mt9v022->switch_gpio = -EINVAL; +#endif + return 0; +} + +static void bus_switch_release(struct mt9v022 *mt9v022) +{ +#ifdef CONFIG_MT9V022_PCA9536_SWITCH + if (gpio_is_valid(mt9v022->switch_gpio)) + gpio_free(mt9v022->switch_gpio); +#endif +} + +static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit) +{ +#ifdef CONFIG_MT9V022_PCA9536_SWITCH + if (!gpio_is_valid(mt9v022->switch_gpio)) + return -ENODEV; + + gpio_set_value_cansleep(mt9v022->switch_gpio, go8bit); + return 0; +#else + return -ENODEV; +#endif +} + +static int mt9v022_set_capture_format(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | + IS_DATAWIDTH_8); + u16 pixclk = 0; + int ret; + + /* Only one width bit may be set */ + if (!is_power_of_2(width_flag)) + return -EINVAL; + + /* The caller provides a supported format, as verified per call to + * icd->try_fmt_cap(), datawidth is from our supported format list */ + switch (pixfmt) { + case V4L2_PIX_FMT_GREY: + case V4L2_PIX_FMT_Y16: + if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM) + return -EINVAL; + break; + case V4L2_PIX_FMT_SBGGR8: + case V4L2_PIX_FMT_SBGGR16: + if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) + return -EINVAL; + break; + case 0: + /* No format change, only geometry */ + break; + default: + return -EINVAL; + } + + /* Like in example app. Contradicts the datasheet though */ + ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + if (ret >= 0) { + if (ret & 1) /* Autoexposure */ + ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, + rect->height + icd->y_skip_top + 43); + else + ret = reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH, + rect->height + icd->y_skip_top + 43); + } + /* Setup frame format: defaults apart from width and height */ + if (ret >= 0) + ret = reg_write(icd, MT9V022_COLUMN_START, rect->left); + if (ret >= 0) + ret = reg_write(icd, MT9V022_ROW_START, rect->top); + if (ret >= 0) + /* Default 94, Phytec driver says: + * "width + horizontal blank >= 660" */ + ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING, + rect->width > 660 - 43 ? 43 : + 660 - rect->width); + if (ret >= 0) + ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45); + if (ret >= 0) + ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width); + if (ret >= 0) + ret = reg_write(icd, MT9V022_WINDOW_HEIGHT, + rect->height + icd->y_skip_top); + + if (ret < 0) + return ret; + + dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height); + + if ((mt9v022->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || + (mt9v022->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || + (mt9v022->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { + /* Well, we actually only can do 10 or 8 bits... */ + if (width_flag == IS_DATAWIDTH_9) + return -EINVAL; + + ret = bus_switch_act(mt9v022, + width_flag == IS_DATAWIDTH_8); + if (ret < 0) + return ret; + + mt9v022->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; + } + + if (flags & IS_PCLK_SAMPLE_RISING) + pixclk |= 0x10; + + if (!(flags & IS_HSYNC_ACTIVE_HIGH)) + pixclk |= 0x1; + + if (!(flags & IS_VSYNC_ACTIVE_HIGH)) + pixclk |= 0x2; + + ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk); + if (ret < 0) + return ret; + + if (!(flags & IS_MASTER)) + mt9v022->chip_control &= ~0x8; + + ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); + if (ret < 0) + return ret; + + dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n", + pixclk, mt9v022->chip_control); + + return 0; +} + +static int mt9v022_try_fmt_cap(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + if (f->fmt.pix.height < 32 + icd->y_skip_top) + f->fmt.pix.height = 32 + icd->y_skip_top; + if (f->fmt.pix.height > 480 + icd->y_skip_top) + f->fmt.pix.height = 480 + icd->y_skip_top; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > 752) + f->fmt.pix.width = 752; + f->fmt.pix.width &= ~0x03; /* ? */ + + return 0; +} + +static int mt9v022_get_chip_id(struct soc_camera_device *icd, + struct v4l2_chip_ident *id) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + + if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + return -EINVAL; + + if (id->match_chip != mt9v022->client->addr) + return -ENODEV; + + id->ident = mt9v022->model; + id->revision = 0; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int mt9v022_get_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9v022->client->addr) + return -ENODEV; + + reg->val = reg_read(icd, reg->reg); + + if (reg->val > 0xffff) + return -EIO; + + return 0; +} + +static int mt9v022_set_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9v022->client->addr) + return -ENODEV; + + if (reg_write(icd, reg->reg, reg->val) < 0) + return -EIO; + + return 0; +} +#endif + +static unsigned int mt9v022_get_datawidth(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + return mt9v022->datawidth; +} + +const struct v4l2_queryctrl mt9v022_controls[] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Vertically", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Horizontally", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Analog Gain", + .minimum = 64, + .maximum = 127, + .step = 1, + .default_value = 64, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 1, + .maximum = 255, + .step = 1, + .default_value = 255, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Automatic Gain", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + }, { + .id = V4L2_CID_EXPOSURE_AUTO, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Automatic Exposure", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + } +}; + +static int mt9v022_get_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl); +static int mt9v022_set_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl); + +static struct soc_camera_ops mt9v022_ops = { + .owner = THIS_MODULE, + .init = mt9v022_init, + .release = mt9v022_release, + .start_capture = mt9v022_start_capture, + .stop_capture = mt9v022_stop_capture, + .set_capture_format = mt9v022_set_capture_format, + .try_fmt_cap = mt9v022_try_fmt_cap, + .formats = NULL, /* Filled in later depending on the */ + .num_formats = 0, /* sensor type and data widths */ + .get_datawidth = mt9v022_get_datawidth, + .controls = mt9v022_controls, + .num_controls = ARRAY_SIZE(mt9v022_controls), + .get_control = mt9v022_get_control, + .set_control = mt9v022_set_control, + .get_chip_id = mt9v022_get_chip_id, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .get_register = mt9v022_get_register, + .set_register = mt9v022_set_register, +#endif +}; + +static int mt9v022_get_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + int data; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + data = reg_read(icd, MT9V022_READ_MODE); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x10); + break; + case V4L2_CID_HFLIP: + data = reg_read(icd, MT9V022_READ_MODE); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x20); + break; + case V4L2_CID_EXPOSURE_AUTO: + data = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x1); + break; + case V4L2_CID_AUTOGAIN: + data = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x2); + break; + } + return 0; +} + +static int mt9v022_set_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + int data; + const struct v4l2_queryctrl *qctrl; + + qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); + + if (!qctrl) + return -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + if (ctrl->value) + data = reg_set(icd, MT9V022_READ_MODE, 0x10); + else + data = reg_clear(icd, MT9V022_READ_MODE, 0x10); + if (data < 0) + return -EIO; + break; + case V4L2_CID_HFLIP: + if (ctrl->value) + data = reg_set(icd, MT9V022_READ_MODE, 0x20); + else + data = reg_clear(icd, MT9V022_READ_MODE, 0x20); + if (data < 0) + return -EIO; + break; + case V4L2_CID_GAIN: + /* mt9v022 has minimum == default */ + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + else { + unsigned long range = qctrl->maximum - qctrl->minimum; + /* Datasheet says 16 to 64. autogain only works properly + * after setting gain to maximum 14. Larger values + * produce "white fly" noise effect. On the whole, + * manually setting analog gain does no good. */ + unsigned long gain = ((ctrl->value - qctrl->minimum) * + 10 + range / 2) / range + 4; + if (gain >= 32) + gain &= ~1; + /* The user wants to set gain manually, hope, she + * knows, what she's doing... Switch AGC off. */ + + if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) + return -EIO; + + dev_info(&icd->dev, "Setting gain from %d to %lu\n", + reg_read(icd, MT9V022_ANALOG_GAIN), gain); + if (reg_write(icd, MT9V022_ANALOG_GAIN, gain) < 0) + return -EIO; + icd->gain = ctrl->value; + } + break; + case V4L2_CID_EXPOSURE: + /* mt9v022 has maximum == default */ + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + else { + unsigned long range = qctrl->maximum - qctrl->minimum; + unsigned long shutter = ((ctrl->value - qctrl->minimum) * + 479 + range / 2) / range + 1; + /* The user wants to set shutter width manually, hope, + * she knows, what she's doing... Switch AEC off. */ + + if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1) < 0) + return -EIO; + + dev_dbg(&icd->dev, "Shutter width from %d to %lu\n", + reg_read(icd, MT9V022_TOTAL_SHUTTER_WIDTH), + shutter); + if (reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH, + shutter) < 0) + return -EIO; + icd->exposure = ctrl->value; + } + break; + case V4L2_CID_AUTOGAIN: + if (ctrl->value) + data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x2); + else + data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2); + if (data < 0) + return -EIO; + break; + case V4L2_CID_EXPOSURE_AUTO: + if (ctrl->value) + data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x1); + else + data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1); + if (data < 0) + return -EIO; + break; + } + return 0; +} + +/* Interface active, can use i2c. If it fails, it can indeed mean, that + * this wasn't our capture interface, so, we wait for the right one */ +static int mt9v022_video_probe(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + s32 data; + int ret; + + if (!icd->dev.parent || + to_soc_camera_host(icd->dev.parent)->nr != icd->iface) + return -ENODEV; + + /* Read out the chip version register */ + data = reg_read(icd, MT9V022_CHIP_VERSION); + + /* must be 0x1311 or 0x1313 */ + if (data != 0x1311 && data != 0x1313) { + ret = -ENODEV; + dev_info(&icd->dev, "No MT9V022 detected, ID register 0x%x\n", + data); + goto ei2c; + } + + /* Soft reset */ + ret = reg_write(icd, MT9V022_RESET, 1); + if (ret < 0) + goto ei2c; + /* 15 clock cycles */ + udelay(200); + if (reg_read(icd, MT9V022_RESET)) { + dev_err(&icd->dev, "Resetting MT9V022 failed!\n"); + goto ei2c; + } + + /* Set monochrome or colour sensor type */ + if (sensor_type && (!strcmp("colour", sensor_type) || + !strcmp("color", sensor_type))) { + ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); + mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; + mt9v022_ops.formats = mt9v022_colour_formats; + if (mt9v022->client->dev.platform_data) + mt9v022_ops.num_formats = ARRAY_SIZE(mt9v022_colour_formats); + else + mt9v022_ops.num_formats = 1; + } else { + ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11); + mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; + mt9v022_ops.formats = mt9v022_monochrome_formats; + if (mt9v022->client->dev.platform_data) + mt9v022_ops.num_formats = ARRAY_SIZE(mt9v022_monochrome_formats); + else + mt9v022_ops.num_formats = 1; + } + + if (ret >= 0) + ret = soc_camera_video_start(icd); + if (ret < 0) + goto eisis; + + dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", + data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? + "monochrome" : "colour"); + + return 0; + +eisis: +ei2c: + return ret; +} + +static void mt9v022_video_remove(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr, + mt9v022->icd.dev.parent, mt9v022->icd.vdev); + soc_camera_video_stop(&mt9v022->icd); +} + +static int mt9v022_probe(struct i2c_client *client) +{ + struct mt9v022 *mt9v022; + struct soc_camera_device *icd; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl = client->dev.platform_data; + int ret; + + if (!icl) { + dev_err(&client->dev, "MT9V022 driver needs platform data\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { + dev_warn(&adapter->dev, + "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); + return -EIO; + } + + mt9v022 = kzalloc(sizeof(struct mt9v022), GFP_KERNEL); + if (!mt9v022) + return -ENOMEM; + + mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; + mt9v022->client = client; + i2c_set_clientdata(client, mt9v022); + + icd = &mt9v022->icd; + icd->probe = mt9v022_video_probe; + icd->remove = mt9v022_video_remove; + icd->ops = &mt9v022_ops; + icd->control = &client->dev; + icd->x_min = 1; + icd->y_min = 4; + icd->x_current = 1; + icd->y_current = 4; + icd->width_min = 48; + icd->width_max = 752; + icd->height_min = 32; + icd->height_max = 480; + icd->y_skip_top = 1; + icd->iface = icl->bus_id; + /* Default datawidth - this is the only width this camera (normally) + * supports. It is only with extra logic that it can support + * other widths. Therefore it seems to be a sensible default. */ + mt9v022->datawidth = 10; + + ret = bus_switch_request(mt9v022, icl); + if (ret) + goto eswinit; + + ret = soc_camera_device_register(icd); + if (ret) + goto eisdr; + + return 0; + +eisdr: + bus_switch_release(mt9v022); +eswinit: + kfree(mt9v022); + return ret; +} + +static int mt9v022_remove(struct i2c_client *client) +{ + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + + soc_camera_device_unregister(&mt9v022->icd); + bus_switch_release(mt9v022); + kfree(mt9v022); + + return 0; +} + +static struct i2c_driver mt9v022_i2c_driver = { + .driver = { + .name = "mt9v022", + }, + .probe = mt9v022_probe, + .remove = mt9v022_remove, +}; + +static int __init mt9v022_mod_init(void) +{ + return i2c_add_driver(&mt9v022_i2c_driver); +} + +static void __exit mt9v022_mod_exit(void) +{ + i2c_del_driver(&mt9v022_i2c_driver); +} + +module_init(mt9v022_mod_init); +module_exit(mt9v022_mod_exit); + +MODULE_DESCRIPTION("Micron MT9V022 Camera driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index add6d0d..41207ec 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -38,7 +38,7 @@ #define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) /* global variable */ -static int mxb_num = 0; +static int mxb_num; /* initial frequence the tuner will be tuned to. in verden (lower saxony, germany) 4148 is a @@ -47,7 +47,7 @@ static int freq = 4148; module_param(freq, int, 0644); MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup"); -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 6820c2a..4a6c572 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -57,11 +57,11 @@ struct i2c_info u8 hits; }; -static int i2c_count = 0; +static int i2c_count; static struct i2c_info i2cinfo[64]; static int decoder = PHILIPS2; -static int standard = 0; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ +static int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ /* * I/O ports and Shared Memory diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 41ae980..24c4e31 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -44,13 +44,13 @@ static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL}; static DEFINE_MUTEX(pvr2_unit_mtx); -static int ctlchg = 0; +static int ctlchg; static int initusbreset = 1; -static int procreload = 0; +static int procreload; static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 }; static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 }; static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 }; -static int init_pause_msec = 0; +static int init_pause_msec; module_param(ctlchg, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value"); diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 62867fa..793c89a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -35,7 +35,7 @@ */ -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index f991d72..b4146f8 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -130,8 +130,8 @@ static int default_fbufs = 3; /* Default number of frame buffers */ #ifdef CONFIG_USB_PWC_DEBUG int pwc_trace = PWC_DEBUG_LEVEL; #endif -static int power_save = 0; -static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */ +static int power_save; +static int led_on = 100, led_off; /* defaults to LED that is on while in use */ static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */ static struct { int type; @@ -786,8 +786,8 @@ static void pwc_isoc_handler(struct urb *urb) } /* ..status == 0 */ else { /* This is normally not interesting to the user, unless - * you are really debugging something */ - static int iso_error = 0; + * you are really debugging something, default = 0 */ + static int iso_error; iso_error++; if (iso_error < 20) PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst); diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c new file mode 100644 index 0000000..a34a193 --- /dev/null +++ b/drivers/media/video/pxa_camera.c @@ -0,0 +1,915 @@ +/* + * V4L2 Driver for PXA camera host + * + * Copyright (C) 2006, Sascha Hauer, Pengutronix + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5) +#define PXA_CAM_DRV_NAME "pxa27x-camera" + +#define CICR0_SIM_MP (0 << 24) +#define CICR0_SIM_SP (1 << 24) +#define CICR0_SIM_MS (2 << 24) +#define CICR0_SIM_EP (3 << 24) +#define CICR0_SIM_ES (4 << 24) + +#define CICR1_DW_VAL(x) ((x) & CICR1_DW) /* Data bus width */ +#define CICR1_PPL_VAL(x) (((x) << 15) & CICR1_PPL) /* Pixels per line */ + +#define CICR2_BLW_VAL(x) (((x) << 24) & CICR2_BLW) /* Beginning-of-line pixel clock wait count */ +#define CICR2_ELW_VAL(x) (((x) << 16) & CICR2_ELW) /* End-of-line pixel clock wait count */ +#define CICR2_HSW_VAL(x) (((x) << 10) & CICR2_HSW) /* Horizontal sync pulse width */ +#define CICR2_BFPW_VAL(x) (((x) << 3) & CICR2_BFPW) /* Beginning-of-frame pixel clock wait count */ +#define CICR2_FSW_VAL(x) (((x) << 0) & CICR2_FSW) /* Frame stabilization wait count */ + +#define CICR3_BFW_VAL(x) (((x) << 24) & CICR3_BFW) /* Beginning-of-frame line clock wait count */ +#define CICR3_EFW_VAL(x) (((x) << 16) & CICR3_EFW) /* End-of-frame line clock wait count */ +#define CICR3_VSW_VAL(x) (((x) << 11) & CICR3_VSW) /* Vertical sync pulse width */ +#define CICR3_LPF_VAL(x) (((x) << 0) & CICR3_LPF) /* Lines per frame */ + +#define CICR0_IRQ_MASK (CICR0_TOM | CICR0_RDAVM | CICR0_FEM | CICR0_EOLM | \ + CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \ + CICR0_EOFM | CICR0_FOM) + +static DEFINE_MUTEX(camera_lock); + +/* + * Structures + */ + +/* buffer for one video frame */ +struct pxa_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + const struct soc_camera_data_format *fmt; + + /* our descriptor list needed for the PXA DMA engine */ + dma_addr_t sg_dma; + struct pxa_dma_desc *sg_cpu; + size_t sg_size; + int inwork; +}; + +struct pxa_framebuffer_queue { + dma_addr_t sg_last_dma; + struct pxa_dma_desc *sg_last_cpu; +}; + +struct pxa_camera_dev { + struct device *dev; + /* PXA27x is only supposed to handle one camera on its Quick Capture + * interface. If anyone ever builds hardware to enable more than + * one camera, they will have to modify this driver too */ + struct soc_camera_device *icd; + struct clk *clk; + + unsigned int irq; + void __iomem *base; + unsigned int dma_chan_y; + + struct pxacamera_platform_data *pdata; + struct resource *res; + unsigned long platform_flags; + unsigned long platform_mclk_10khz; + + struct list_head capture; + + spinlock_t lock; + + struct pxa_buffer *active; +}; + +static const char *pxa_cam_driver_description = "PXA_Camera"; + +static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ + +/* + * Videobuf operations + */ +static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct soc_camera_device *icd = vq->priv_data; + + dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); + + *size = icd->width * icd->height * ((icd->current_fmt->depth + 7) >> 3); + + if (0 == *count) + *count = 32; + while (*size * *count > vid_limit * 1024 * 1024) + (*count)--; + + return 0; +} + +static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); + + BUG_ON(in_interrupt()); + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + &buf->vb, buf->vb.baddr, buf->vb.bsize); + + /* This waits until this buffer is out of danger, i.e., until it is no + * longer in STATE_QUEUED or STATE_ACTIVE */ + videobuf_waiton(&buf->vb, 0, 0); + videobuf_dma_unmap(vq, dma); + videobuf_dma_free(dma); + + if (buf->sg_cpu) + dma_free_coherent(pcdev->dev, buf->sg_size, buf->sg_cpu, + buf->sg_dma); + buf->sg_cpu = NULL; + + buf->vb.state = VIDEOBUF_NEEDS_INIT; +} + +static int pxa_videobuf_prepare(struct videobuf_queue *vq, + struct videobuf_buffer *vb, enum v4l2_field field) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); + int i, ret; + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + vb, vb->baddr, vb->bsize); + + /* Added list head initialization on alloc */ + WARN_ON(!list_empty(&vb->queue)); + +#ifdef DEBUG + /* This can be useful if you want to see if we actually fill + * the buffer with something */ + memset((void *)vb->baddr, 0xaa, vb->bsize); +#endif + + BUG_ON(NULL == icd->current_fmt); + + /* I think, in buf_prepare you only have to protect global data, + * the actual buffer is yours */ + buf->inwork = 1; + + if (buf->fmt != icd->current_fmt || + vb->width != icd->width || + vb->height != icd->height || + vb->field != field) { + buf->fmt = icd->current_fmt; + vb->width = icd->width; + vb->height = icd->height; + vb->field = field; + vb->state = VIDEOBUF_NEEDS_INIT; + } + + vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3); + if (0 != vb->baddr && vb->bsize < vb->size) { + ret = -EINVAL; + goto out; + } + + if (vb->state == VIDEOBUF_NEEDS_INIT) { + unsigned int size = vb->size; + struct videobuf_dmabuf *dma = videobuf_to_dma(vb); + + ret = videobuf_iolock(vq, vb, NULL); + if (ret) + goto fail; + + if (buf->sg_cpu) + dma_free_coherent(pcdev->dev, buf->sg_size, buf->sg_cpu, + buf->sg_dma); + + buf->sg_size = (dma->sglen + 1) * sizeof(struct pxa_dma_desc); + buf->sg_cpu = dma_alloc_coherent(pcdev->dev, buf->sg_size, + &buf->sg_dma, GFP_KERNEL); + if (!buf->sg_cpu) { + ret = -ENOMEM; + goto fail; + } + + dev_dbg(&icd->dev, "nents=%d size: %d sg=0x%p\n", + dma->sglen, size, dma->sglist); + for (i = 0; i < dma->sglen; i++) { + struct scatterlist *sg = dma->sglist; + unsigned int dma_len = sg_dma_len(&sg[i]), xfer_len; + + /* CIBR0 */ + buf->sg_cpu[i].dsadr = pcdev->res->start + 0x28; + buf->sg_cpu[i].dtadr = sg_dma_address(&sg[i]); + /* PXA270 Developer's Manual 27.4.4.1: + * round up to 8 bytes */ + xfer_len = (min(dma_len, size) + 7) & ~7; + if (xfer_len & 7) + dev_err(&icd->dev, "Unaligned buffer: " + "dma_len %u, size %u\n", dma_len, size); + buf->sg_cpu[i].dcmd = DCMD_FLOWSRC | DCMD_BURST8 | + DCMD_INCTRGADDR | xfer_len; + size -= dma_len; + buf->sg_cpu[i].ddadr = buf->sg_dma + (i + 1) * + sizeof(struct pxa_dma_desc); + } + buf->sg_cpu[dma->sglen - 1].ddadr = DDADR_STOP; + buf->sg_cpu[dma->sglen - 1].dcmd |= DCMD_ENDIRQEN; + + vb->state = VIDEOBUF_PREPARED; + } + + buf->inwork = 0; + + return 0; + +fail: + free_buffer(vq, buf); +out: + buf->inwork = 0; + return ret; +} + +static void pxa_videobuf_queue(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); + struct pxa_buffer *active; + struct videobuf_dmabuf *dma = videobuf_to_dma(vb); + int nents = dma->sglen; + unsigned long flags; + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + vb, vb->baddr, vb->bsize); + spin_lock_irqsave(&pcdev->lock, flags); + + list_add_tail(&vb->queue, &pcdev->capture); + + vb->state = VIDEOBUF_ACTIVE; + active = pcdev->active; + + if (!active) { + CIFR |= CIFR_RESET_F; + DDADR(pcdev->dma_chan_y) = buf->sg_dma; + DCSR(pcdev->dma_chan_y) = DCSR_RUN; + pcdev->active = buf; + CICR0 |= CICR0_ENB; + } else { + struct videobuf_dmabuf *active_dma = + videobuf_to_dma(&active->vb); + /* Stop DMA engine */ + DCSR(pcdev->dma_chan_y) = 0; + + /* Add the descriptors we just initialized to the currently + * running chain + */ + active->sg_cpu[active_dma->sglen - 1].ddadr = buf->sg_dma; + + /* Setup a dummy descriptor with the DMA engines current + * state + */ + /* CIBR0 */ + buf->sg_cpu[nents].dsadr = pcdev->res->start + 0x28; + buf->sg_cpu[nents].dtadr = DTADR(pcdev->dma_chan_y); + buf->sg_cpu[nents].dcmd = DCMD(pcdev->dma_chan_y); + + if (DDADR(pcdev->dma_chan_y) == DDADR_STOP) { + /* The DMA engine is on the last descriptor, set the + * next descriptors address to the descriptors + * we just initialized + */ + buf->sg_cpu[nents].ddadr = buf->sg_dma; + } else { + buf->sg_cpu[nents].ddadr = DDADR(pcdev->dma_chan_y); + } + + /* The next descriptor is the dummy descriptor */ + DDADR(pcdev->dma_chan_y) = buf->sg_dma + nents * + sizeof(struct pxa_dma_desc); + +#ifdef DEBUG + if (CISR & CISR_IFO_0) { + dev_warn(pcdev->dev, "FIFO overrun\n"); + DDADR(pcdev->dma_chan_y) = pcdev->active->sg_dma; + + CICR0 &= ~CICR0_ENB; + CIFR |= CIFR_RESET_F; + DCSR(pcdev->dma_chan_y) = DCSR_RUN; + CICR0 |= CICR0_ENB; + } else +#endif + DCSR(pcdev->dma_chan_y) = DCSR_RUN; + } + + spin_unlock_irqrestore(&pcdev->lock, flags); + +} + +static void pxa_videobuf_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); +#ifdef DEBUG + struct soc_camera_device *icd = vq->priv_data; + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + vb, vb->baddr, vb->bsize); + + switch (vb->state) { + case VIDEOBUF_ACTIVE: + dev_dbg(&icd->dev, "%s (active)\n", __FUNCTION__); + break; + case VIDEOBUF_QUEUED: + dev_dbg(&icd->dev, "%s (queued)\n", __FUNCTION__); + break; + case VIDEOBUF_PREPARED: + dev_dbg(&icd->dev, "%s (prepared)\n", __FUNCTION__); + break; + default: + dev_dbg(&icd->dev, "%s (unknown)\n", __FUNCTION__); + break; + } +#endif + + free_buffer(vq, buf); +} + +static void pxa_camera_dma_irq_y(int channel, void *data) +{ + struct pxa_camera_dev *pcdev = data; + struct pxa_buffer *buf; + unsigned long flags; + unsigned int status; + struct videobuf_buffer *vb; + + spin_lock_irqsave(&pcdev->lock, flags); + + status = DCSR(pcdev->dma_chan_y); + DCSR(pcdev->dma_chan_y) = status; + + if (status & DCSR_BUSERR) { + dev_err(pcdev->dev, "DMA Bus Error IRQ!\n"); + goto out; + } + + if (!(status & DCSR_ENDINTR)) { + dev_err(pcdev->dev, "Unknown DMA IRQ source, " + "status: 0x%08x\n", status); + goto out; + } + + if (!pcdev->active) { + dev_err(pcdev->dev, "DMA End IRQ with no active buffer!\n"); + goto out; + } + + vb = &pcdev->active->vb; + buf = container_of(vb, struct pxa_buffer, vb); + WARN_ON(buf->inwork || list_empty(&vb->queue)); + dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + vb, vb->baddr, vb->bsize); + + /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ + list_del_init(&vb->queue); + vb->state = VIDEOBUF_DONE; + do_gettimeofday(&vb->ts); + vb->field_count++; + wake_up(&vb->done); + + if (list_empty(&pcdev->capture)) { + pcdev->active = NULL; + DCSR(pcdev->dma_chan_y) = 0; + CICR0 &= ~CICR0_ENB; + goto out; + } + + pcdev->active = list_entry(pcdev->capture.next, struct pxa_buffer, + vb.queue); + +out: + spin_unlock_irqrestore(&pcdev->lock, flags); +} + +static struct videobuf_queue_ops pxa_videobuf_ops = { + .buf_setup = pxa_videobuf_setup, + .buf_prepare = pxa_videobuf_prepare, + .buf_queue = pxa_videobuf_queue, + .buf_release = pxa_videobuf_release, +}; + +static int mclk_get_divisor(struct pxa_camera_dev *pcdev) +{ + unsigned int mclk_10khz = pcdev->platform_mclk_10khz; + unsigned long div; + unsigned long lcdclk; + + lcdclk = clk_get_rate(pcdev->clk) / 10000; + + /* We verify platform_mclk_10khz != 0, so if anyone breaks it, here + * they get a nice Oops */ + div = (lcdclk + 2 * mclk_10khz - 1) / (2 * mclk_10khz) - 1; + + dev_dbg(pcdev->dev, "LCD clock %lukHz, target freq %dkHz, " + "divisor %lu\n", lcdclk * 10, mclk_10khz * 10, div); + + return div; +} + +static void pxa_camera_activate(struct pxa_camera_dev *pcdev) +{ + struct pxacamera_platform_data *pdata = pcdev->pdata; + u32 cicr4 = 0; + + dev_dbg(pcdev->dev, "Registered platform device at %p data %p\n", + pcdev, pdata); + + if (pdata && pdata->init) { + dev_dbg(pcdev->dev, "%s: Init gpios\n", __FUNCTION__); + pdata->init(pcdev->dev); + } + + if (pdata && pdata->power) { + dev_dbg(pcdev->dev, "%s: Power on camera\n", __FUNCTION__); + pdata->power(pcdev->dev, 1); + } + + if (pdata && pdata->reset) { + dev_dbg(pcdev->dev, "%s: Releasing camera reset\n", + __FUNCTION__); + pdata->reset(pcdev->dev, 1); + } + + CICR0 = 0x3FF; /* disable all interrupts */ + + if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) + cicr4 |= CICR4_PCLK_EN; + if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) + cicr4 |= CICR4_MCLK_EN; + if (pcdev->platform_flags & PXA_CAMERA_PCP) + cicr4 |= CICR4_PCP; + if (pcdev->platform_flags & PXA_CAMERA_HSP) + cicr4 |= CICR4_HSP; + if (pcdev->platform_flags & PXA_CAMERA_VSP) + cicr4 |= CICR4_VSP; + + CICR4 = mclk_get_divisor(pcdev) | cicr4; + + clk_enable(pcdev->clk); +} + +static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) +{ + struct pxacamera_platform_data *board = pcdev->pdata; + + clk_disable(pcdev->clk); + + if (board && board->reset) { + dev_dbg(pcdev->dev, "%s: Asserting camera reset\n", + __FUNCTION__); + board->reset(pcdev->dev, 0); + } + + if (board && board->power) { + dev_dbg(pcdev->dev, "%s: Power off camera\n", __FUNCTION__); + board->power(pcdev->dev, 0); + } +} + +static irqreturn_t pxa_camera_irq(int irq, void *data) +{ + struct pxa_camera_dev *pcdev = data; + unsigned int status = CISR; + + dev_dbg(pcdev->dev, "Camera interrupt status 0x%x\n", status); + + CISR = status; + + return IRQ_HANDLED; +} + +/* The following two functions absolutely depend on the fact, that + * there can be only one camera on PXA quick capture interface */ +static int pxa_camera_add_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + int ret; + + mutex_lock(&camera_lock); + + if (pcdev->icd) { + ret = -EBUSY; + goto ebusy; + } + + dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n", + icd->devnum); + + pxa_camera_activate(pcdev); + ret = icd->ops->init(icd); + + if (!ret) + pcdev->icd = icd; + +ebusy: + mutex_unlock(&camera_lock); + + return ret; +} + +static void pxa_camera_remove_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + + BUG_ON(icd != pcdev->icd); + + dev_info(&icd->dev, "PXA Camera driver detached from camera %d\n", + icd->devnum); + + /* disable capture, disable interrupts */ + CICR0 = 0x3ff; + /* Stop DMA engine */ + DCSR(pcdev->dma_chan_y) = 0; + + icd->ops->release(icd); + + pxa_camera_deactivate(pcdev); + + pcdev->icd = NULL; +} + +static int pxa_camera_set_capture_format(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) +{ + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + unsigned int datawidth = 0, dw, bpp; + u32 cicr0, cicr4 = 0; + int ret; + + /* If requested data width is supported by the platform, use it */ + switch (icd->cached_datawidth) { + case 10: + if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10) + datawidth = IS_DATAWIDTH_10; + break; + case 9: + if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9) + datawidth = IS_DATAWIDTH_9; + break; + case 8: + if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8) + datawidth = IS_DATAWIDTH_8; + } + if (!datawidth) + return -EINVAL; + + ret = icd->ops->set_capture_format(icd, pixfmt, rect, + datawidth | + (pcdev->platform_flags & PXA_CAMERA_MASTER ? + IS_MASTER : 0) | + (pcdev->platform_flags & PXA_CAMERA_HSP ? + 0 : IS_HSYNC_ACTIVE_HIGH) | + (pcdev->platform_flags & PXA_CAMERA_VSP ? + 0 : IS_VSYNC_ACTIVE_HIGH) | + (pcdev->platform_flags & PXA_CAMERA_PCP ? + 0 : IS_PCLK_SAMPLE_RISING)); + if (ret < 0) + return ret; + + /* Datawidth is now guaranteed to be equal to one of the three values. + * We fix bit-per-pixel equal to data-width... */ + switch (datawidth) { + case IS_DATAWIDTH_10: + icd->cached_datawidth = 10; + dw = 4; + bpp = 0x40; + break; + case IS_DATAWIDTH_9: + icd->cached_datawidth = 9; + dw = 3; + bpp = 0x20; + break; + default: + /* Actually it can only be 8 now, + * default is just to silence compiler warnings */ + case IS_DATAWIDTH_8: + icd->cached_datawidth = 8; + dw = 2; + bpp = 0; + } + + if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) + cicr4 |= CICR4_PCLK_EN; + if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) + cicr4 |= CICR4_MCLK_EN; + if (pcdev->platform_flags & PXA_CAMERA_PCP) + cicr4 |= CICR4_PCP; + if (pcdev->platform_flags & PXA_CAMERA_HSP) + cicr4 |= CICR4_HSP; + if (pcdev->platform_flags & PXA_CAMERA_VSP) + cicr4 |= CICR4_VSP; + + cicr0 = CICR0; + if (cicr0 & CICR0_ENB) + CICR0 = cicr0 & ~CICR0_ENB; + CICR1 = CICR1_PPL_VAL(rect->width - 1) | bpp | dw; + CICR2 = 0; + CICR3 = CICR3_LPF_VAL(rect->height - 1) | + CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); + CICR4 = mclk_get_divisor(pcdev) | cicr4; + + /* CIF interrupts are not used, only DMA */ + CICR0 = (pcdev->platform_flags & PXA_CAMERA_MASTER ? + CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP)) | + CICR0_DMAEN | CICR0_IRQ_MASK | (cicr0 & CICR0_ENB); + + return 0; +} + +static int pxa_camera_try_fmt_cap(struct soc_camera_host *ici, + struct v4l2_format *f) +{ + /* limit to pxa hardware capabilities */ + if (f->fmt.pix.height < 32) + f->fmt.pix.height = 32; + if (f->fmt.pix.height > 2048) + f->fmt.pix.height = 2048; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > 2048) + f->fmt.pix.width = 2048; + f->fmt.pix.width &= ~0x01; + + return 0; +} + +static int pxa_camera_reqbufs(struct soc_camera_file *icf, + struct v4l2_requestbuffers *p) +{ + int i; + + /* This is for locking debugging only. I removed spinlocks and now I + * check whether .prepare is ever called on a linked buffer, or whether + * a dma IRQ can occur for an in-work or unlinked buffer. Until now + * it hadn't triggered */ + for (i = 0; i < p->count; i++) { + struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i], + struct pxa_buffer, vb); + buf->inwork = 0; + INIT_LIST_HEAD(&buf->vb.queue); + } + + return 0; +} + +static unsigned int pxa_camera_poll(struct file *file, poll_table *pt) +{ + struct soc_camera_file *icf = file->private_data; + struct pxa_buffer *buf; + + buf = list_entry(icf->vb_vidq.stream.next, struct pxa_buffer, + vb.stream); + + poll_wait(file, &buf->vb.done, pt); + + if (buf->vb.state == VIDEOBUF_DONE || + buf->vb.state == VIDEOBUF_ERROR) + return POLLIN|POLLRDNORM; + + return 0; +} + +static int pxa_camera_querycap(struct soc_camera_host *ici, + struct v4l2_capability *cap) +{ + /* cap->name is set by the firendly caller:-> */ + strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card)); + cap->version = PXA_CAM_VERSION_CODE; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + + return 0; +} + +/* Should beallocated dynamically too, but we have only one. */ +static struct soc_camera_host pxa_soc_camera_host = { + .drv_name = PXA_CAM_DRV_NAME, + .vbq_ops = &pxa_videobuf_ops, + .add = pxa_camera_add_device, + .remove = pxa_camera_remove_device, + .msize = sizeof(struct pxa_buffer), + .set_capture_format = pxa_camera_set_capture_format, + .try_fmt_cap = pxa_camera_try_fmt_cap, + .reqbufs = pxa_camera_reqbufs, + .poll = pxa_camera_poll, + .querycap = pxa_camera_querycap, +}; + +static int pxa_camera_probe(struct platform_device *pdev) +{ + struct pxa_camera_dev *pcdev; + struct resource *res; + void __iomem *base; + unsigned int irq; + int err = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (!res || !irq) { + err = -ENODEV; + goto exit; + } + + pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL); + if (!pcdev) { + dev_err(&pdev->dev, "Could not allocate pcdev\n"); + err = -ENOMEM; + goto exit; + } + + pcdev->clk = clk_get(&pdev->dev, "CAMCLK"); + if (IS_ERR(pcdev->clk)) { + err = PTR_ERR(pcdev->clk); + goto exit_kfree; + } + + dev_set_drvdata(&pdev->dev, pcdev); + pcdev->res = res; + + pcdev->pdata = pdev->dev.platform_data; + pcdev->platform_flags = pcdev->pdata->flags; + if (!pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | + PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10)) { + /* Platform hasn't set available data widths. This is bad. + * Warn and use a default. */ + dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " + "data widths, using default 10 bit\n"); + pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10; + } + pcdev->platform_mclk_10khz = pcdev->pdata->mclk_10khz; + if (!pcdev->platform_mclk_10khz) { + dev_warn(&pdev->dev, + "mclk_10khz == 0! Please, fix your platform data. " + "Using default 20MHz\n"); + pcdev->platform_mclk_10khz = 2000; + } + + INIT_LIST_HEAD(&pcdev->capture); + spin_lock_init(&pcdev->lock); + + /* + * Request the regions. + */ + if (!request_mem_region(res->start, res->end - res->start + 1, + PXA_CAM_DRV_NAME)) { + err = -EBUSY; + goto exit_clk; + } + + base = ioremap(res->start, res->end - res->start + 1); + if (!base) { + err = -ENOMEM; + goto exit_release; + } + pcdev->irq = irq; + pcdev->base = base; + pcdev->dev = &pdev->dev; + + /* request dma */ + pcdev->dma_chan_y = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, + pxa_camera_dma_irq_y, pcdev); + if (pcdev->dma_chan_y < 0) { + dev_err(pcdev->dev, "Can't request DMA for Y\n"); + err = -ENOMEM; + goto exit_iounmap; + } + dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chan_y); + + DRCMR68 = pcdev->dma_chan_y | DRCMR_MAPVLD; + + /* request irq */ + err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME, + pcdev); + if (err) { + dev_err(pcdev->dev, "Camera interrupt register failed \n"); + goto exit_free_dma; + } + + pxa_soc_camera_host.priv = pcdev; + pxa_soc_camera_host.dev.parent = &pdev->dev; + pxa_soc_camera_host.nr = pdev->id; + err = soc_camera_host_register(&pxa_soc_camera_host, THIS_MODULE); + if (err) + goto exit_free_irq; + + return 0; + +exit_free_irq: + free_irq(pcdev->irq, pcdev); +exit_free_dma: + pxa_free_dma(pcdev->dma_chan_y); +exit_iounmap: + iounmap(base); +exit_release: + release_mem_region(res->start, res->end - res->start + 1); +exit_clk: + clk_put(pcdev->clk); +exit_kfree: + kfree(pcdev); +exit: + return err; +} + +static int __devexit pxa_camera_remove(struct platform_device *pdev) +{ + struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev); + struct resource *res; + + clk_put(pcdev->clk); + + pxa_free_dma(pcdev->dma_chan_y); + free_irq(pcdev->irq, pcdev); + + soc_camera_host_unregister(&pxa_soc_camera_host); + + iounmap(pcdev->base); + + res = pcdev->res; + release_mem_region(res->start, res->end - res->start + 1); + + kfree(pcdev); + + dev_info(&pdev->dev, "PXA Camera driver unloaded\n"); + + return 0; +} + +static struct platform_driver pxa_camera_driver = { + .driver = { + .name = PXA_CAM_DRV_NAME, + }, + .probe = pxa_camera_probe, + .remove = __exit_p(pxa_camera_remove), +}; + + +static int __devinit pxa_camera_init(void) +{ + return platform_driver_register(&pxa_camera_driver); +} + +static void __exit pxa_camera_exit(void) +{ + return platform_driver_unregister(&pxa_camera_driver); +} + +module_init(pxa_camera_init); +module_exit(pxa_camera_exit); + +MODULE_DESCRIPTION("PXA27x SoC Camera Host driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 72e344a..716ee7f 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -44,10 +44,10 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_INSMOD; /* insmod options */ -static unsigned int debug = 0; -static unsigned int xtal = 0; -static unsigned int rbds = 0; -static unsigned int plvl = 0; +static unsigned int debug; +static unsigned int xtal; +static unsigned int rbds; +static unsigned int plvl; static unsigned int bufblocks = 100; module_param(debug, int, 0644); diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 061134a..a899300 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -46,7 +46,7 @@ MODULE_LICENSE("GPL"); #include #include -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index 7ae2d64..17a0f5f 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c @@ -55,7 +55,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c index 677df51..77e2d1e 100644 --- a/drivers/media/video/saa7114.c +++ b/drivers/media/video/saa7114.c @@ -56,7 +56,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(x) (x)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 41e5e51..aaec17f 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -57,7 +57,7 @@ MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, " "Hans Verkuil, Mauro Carvalho Chehab"); MODULE_LICENSE("GPL"); -static int debug = 0; +static int debug; module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 80bf911..cedb988 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c @@ -48,7 +48,7 @@ MODULE_LICENSE("GPL"); #include -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, " Set the default Debug level. Default: 0 (Off) - (0-1)"); diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 047add8..048081b 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -31,7 +31,7 @@ #include "saa7134.h" #include "saa7134-reg.h" -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages [alsa]"); @@ -503,7 +503,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, /* release the old buffer */ if (substream->runtime->dma_area) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); + videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); dsp_buffer_free(dev); substream->runtime->dma_area = NULL; } @@ -519,12 +519,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, return err; } - if (0 != (err = videobuf_pci_dma_map(dev->pci, &dev->dmasound.dma))) { + if (0 != (err = videobuf_sg_dma_map(&dev->pci->dev, &dev->dmasound.dma))) { dsp_buffer_free(dev); return err; } if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) { - videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); + videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); dsp_buffer_free(dev); return err; } @@ -533,7 +533,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, dev->dmasound.dma.sglen, 0))) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); + videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); dsp_buffer_free(dev); return err; } @@ -569,7 +569,7 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream) if (substream->runtime->dma_area) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); + videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); dsp_buffer_free(dev); substream->runtime->dma_area = NULL; } diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 262830d..6fde042 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -22,9 +22,12 @@ #include #include +#include +#include #include "saa7134-reg.h" #include "saa7134.h" +#include "tuner-xc2028.h" #include #include @@ -2484,27 +2487,28 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .gpiomask = 0x080200000, - .inputs = {{ - .name = name_tv, - .vmux = 4, - .amux = TV, - .tv = 1, - },{ - .name = name_comp1, - .vmux = 1, - .amux = LINE2, - },{ - .name = name_comp2, - .vmux = 0, - .amux = LINE2, - },{ - .name = name_svideo, - .vmux = 8, - .amux = LINE2, - }}, + .inputs = { { + .name = name_tv, + .vmux = 4, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE2, + }, { + .name = name_comp2, + .vmux = 0, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, .radio = { - .name = name_radio, - .amux = LINE1, + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, }, }, [SAA7134_BOARD_ASUSTeK_P7131_DUAL] = { @@ -3991,6 +3995,169 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x6000, }, }, + [SAA7134_BOARD_PHILIPS_SNAKE] = { + .name = "NXP Snake DVB-S reference design", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + }, + [SAA7134_BOARD_CREATIX_CTX953] = { + .name = "Medion/Creatix CTX953 Hybrid", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 0, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 0, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + }, + [SAA7134_BOARD_MSI_TVANYWHERE_AD11] = { + .name = "MSI TV@nywhere A/D v1.1", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 2, + .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 0x0200000, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, + }, + }, + [SAA7134_BOARD_AVERMEDIA_CARDBUS_506] = { + .name = "AVerMedia Cardbus TV/Radio (E506R)", + .audio_clock = 0x187de7, + .tuner_type = TUNER_XC2028, + /* + TODO: + .mpeg = SAA7134_MPEG_DVB, + */ + + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + }, + }, + [SAA7134_BOARD_AVERMEDIA_A16D] = { + .name = "AVerMedia Hybrid TV/Radio (A16D)", + .audio_clock = 0x187de7, + .tuner_type = TUNER_XC2028, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE1, + }, + }, + [SAA7134_BOARD_AVERMEDIA_M115] = { + .name = "Avermedia M115", + .audio_clock = 0x187de7, + .tuner_type = TUNER_XC2028, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + }, + [SAA7134_BOARD_VIDEOMATE_T750] = { + /* John Newbigin */ + .name = "Compro VideoMate T750", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_XC2028, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + .radio = { + .name = name_radio, + .amux = TV, + } + } }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -4941,7 +5108,43 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1822, /*Twinhan Technology Co. Ltd*/ .subdevice = 0x0022, .driver_data = SAA7134_BOARD_TWINHAN_DTV_DVB_3056, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x16be, + .subdevice = 0x0010, /* Medion version CTX953_V.1.4.3 */ + .driver_data = SAA7134_BOARD_CREATIX_CTX953, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1462, /* MSI */ + .subdevice = 0x8625, /* TV@nywhere A/D v1.1 */ + .driver_data = SAA7134_BOARD_MSI_TVANYWHERE_AD11, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xf436, + .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS_506, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xf936, + .driver_data = SAA7134_BOARD_AVERMEDIA_A16D, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xa836, + .driver_data = SAA7134_BOARD_AVERMEDIA_M115, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x185b, + .subdevice = 0xc900, + .driver_data = SAA7134_BOARD_VIDEOMATE_T750, + }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -4997,6 +5200,67 @@ static void board_flyvideo(struct saa7134_dev *dev) dev->name, dev->name, dev->name); } +static int saa7134_xc2028_callback(struct saa7134_dev *dev, + int command, int arg) +{ + switch (command) { + case XC2028_TUNER_RESET: + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000); + saa_andorl(SAA7133_ANALOG_IO_SELECT >> 2, 0x02, 0x02); + saa_andorl(SAA7134_ANALOG_IN_CTRL1 >> 2, 0x81, 0x81); + saa_andorl(SAA7134_AUDIO_CLOCK0 >> 2, 0x03187de7, 0x03187de7); + saa_andorl(SAA7134_AUDIO_PLL_CTRL >> 2, 0x03, 0x03); + saa_andorl(SAA7134_AUDIO_CLOCKS_PER_FIELD0 >> 2, + 0x0001e000, 0x0001e000); + return 0; + } + return -EINVAL; +} + + +static int saa7134_tda8290_callback(struct saa7134_dev *dev, + int command, int arg) +{ + u8 sync_control; + + switch (command) { + case 0: /* switch LNA gain through GPIO 22*/ + saa7134_set_gpio(dev, 22, arg) ; + break; + case 1: /* vsync output at GPIO22. 50 / 60Hz */ + saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80); + saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03); + if (arg == 1) + sync_control = 11; + else + sync_control = 17; + saa_writeb(SAA7134_VGATE_START, sync_control); + saa_writeb(SAA7134_VGATE_STOP, sync_control + 1); + saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00); + break; + default: + return -EINVAL; + } + + return 0; +} + +int saa7134_tuner_callback(void *priv, int command, int arg) +{ + struct i2c_algo_bit_data *i2c_algo = priv; + struct saa7134_dev *dev = i2c_algo->data; + + switch (dev->tuner_type) { + case TUNER_PHILIPS_TDA8290: + return saa7134_tda8290_callback(dev, command, arg); + case TUNER_XC2028: + return saa7134_xc2028_callback(dev, command, arg); + } + return -EINVAL; +} +EXPORT_SYMBOL(saa7134_tuner_callback); + /* ----------------------------------------------------------- */ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) @@ -5066,6 +5330,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: case SAA7134_BOARD_VIDEOMATE_DVBT_200A: + case SAA7134_BOARD_VIDEOMATE_T750: case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: case SAA7134_BOARD_BEHOLD_409FM: @@ -5132,6 +5397,8 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000); break; case SAA7134_BOARD_AVERMEDIA_CARDBUS: + case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: + case SAA7134_BOARD_AVERMEDIA_M115: case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: /* power-up tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0xffffffff); @@ -5199,11 +5466,16 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->tuner_type = saa7134_boards[dev->board].tuner_type; if (TUNER_ABSENT != dev->tuner_type) { - tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; - tun_setup.type = dev->tuner_type; - tun_setup.addr = ADDR_UNSET; + tun_setup.mode_mask = T_RADIO | + T_ANALOG_TV | + T_DIGITAL_TV; + tun_setup.type = dev->tuner_type; + tun_setup.addr = ADDR_UNSET; + tun_setup.tuner_callback = saa7134_tuner_callback; - saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR, &tun_setup); + saa7134_i2c_call_clients(dev, + TUNER_SET_TYPE_ADDR, + &tun_setup); } break; case SAA7134_BOARD_MD7134: @@ -5274,14 +5546,25 @@ int saa7134_board_init2(struct saa7134_dev *dev) &tda9887_cfg); } - tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.mode_mask = T_RADIO | + T_ANALOG_TV | + T_DIGITAL_TV; tun_setup.type = dev->tuner_type; tun_setup.addr = ADDR_UNSET; - saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup); + saa7134_i2c_call_clients(dev, + TUNER_SET_TYPE_ADDR, &tun_setup); } break; case SAA7134_BOARD_PHILIPS_EUROPA: + if (dev->autodetected && (dev->eedata[0x41] == 0x1c)) { + /* Reconfigure board as Snake reference design */ + dev->board = SAA7134_BOARD_PHILIPS_SNAKE; + dev->tuner_type = saa7134_boards[dev->board].tuner_type; + printk(KERN_INFO "%s: Reconfigured board as %s\n", + dev->name, saa7134_boards[dev->board].name); + break; + } case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: /* The Philips EUROPA based hybrid boards have the tuner connected through @@ -5332,6 +5615,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) case SAA7134_BOARD_MEDION_MD8800_QUADRO: case SAA7134_BOARD_AVERMEDIA_SUPER_007: case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: + case SAA7134_BOARD_CREATIX_CTX953: /* this is a hybrid board, initialize to analog mode * and configure firmware eeprom address */ @@ -5402,12 +5686,26 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; } + + if (dev->tuner_type == TUNER_XC2028) { + struct v4l2_priv_tun_config xc2028_cfg; + struct xc2028_ctrl ctl; + + memset(&xc2028_cfg, 0, sizeof(ctl)); + memset(&ctl, 0, sizeof(ctl)); + + ctl.fname = XC2028_DEFAULT_FIRMWARE; + ctl.max_len = 64; + + /* FIXME: This should be device-dependent */ + ctl.demod = XC3028_FE_OREN538; + ctl.mts = 1; + + xc2028_cfg.tuner = TUNER_XC2028; + xc2028_cfg.priv = &ctl; + + saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg); + } + return 0; } - -/* ----------------------------------------------------------- */ -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 52baa4f..ed96ce7 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -42,23 +42,23 @@ MODULE_LICENSE("GPL"); /* ------------------------------------------------------------------ */ -static unsigned int irq_debug = 0; +static unsigned int irq_debug; module_param(irq_debug, int, 0644); MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]"); -static unsigned int core_debug = 0; +static unsigned int core_debug; module_param(core_debug, int, 0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); -static unsigned int gpio_tracking = 0; +static unsigned int gpio_tracking; module_param(gpio_tracking, int, 0644); MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); -static unsigned int alsa = 0; +static unsigned int alsa; module_param(alsa, int, 0644); MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]"); -static unsigned int oss = 0; +static unsigned int oss; module_param(oss, int, 0644); MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]"); @@ -142,39 +142,6 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value) } } -int saa7134_tuner_callback(void *ptr, int command, int arg) -{ - u8 sync_control; - struct saa7134_dev *dev = ptr; - - switch (dev->tuner_type) { - case TUNER_PHILIPS_TDA8290: - switch (command) { - case 0: /* switch LNA gain through GPIO 22*/ - saa7134_set_gpio(dev, 22, arg) ; - break; - case 1: /* vsync output at GPIO22. 50 / 60Hz */ - dprintk("setting GPIO22 to vsync %d\n", arg); - saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80); - saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03); - if (arg == 1) - sync_control = 11; - else - sync_control = 17; - saa_writeb(SAA7134_VGATE_START, sync_control); - saa_writeb(SAA7134_VGATE_STOP, sync_control + 1); - saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00); - break; - default: - return -EINVAL; - } - break; - default: - return -ENODEV; - } - return 0; -} - /* ------------------------------------------------------------------ */ @@ -1022,12 +989,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, saa7134_i2c_register(dev); /* initialize hardware #2 */ + if (TUNER_ABSENT != dev->tuner_type) + request_module("tuner"); saa7134_board_init2(dev); + saa7134_hwinit2(dev); /* load i2c helpers */ - if (TUNER_ABSENT != dev->tuner_type) - request_module("tuner"); if (card_is_empress(dev)) { request_module("saa6752hs"); } diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index ea2be9e..97d9178 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -38,25 +38,28 @@ #include "mt352_priv.h" /* FIXME */ #include "tda1004x.h" #include "nxt200x.h" +#include "tuner-xc2028.h" #include "tda10086.h" #include "tda826x.h" #include "tda827x.h" #include "isl6421.h" +#include "isl6405.h" +#include "lnbp21.h" MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); -static unsigned int antenna_pwr = 0; +static unsigned int antenna_pwr; module_param(antenna_pwr, int, 0444); MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)"); -static int use_frontend = 0; +static int use_frontend; module_param(use_frontend, int, 0644); MODULE_PARM_DESC(use_frontend,"for cards with multiple frontends (0: terrestrial, 1: satellite)"); -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off module debugging (default:off)."); @@ -188,6 +191,11 @@ static struct mt352_config avermedia_777 = { .demod_init = mt352_aver777_init, }; +static struct mt352_config avermedia_e506r_mt352_dev = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, +}; + /* ================================================================== * tda1004x based DVB-T cards, helper functions */ @@ -844,6 +852,36 @@ static struct tda10086_config flydvbs = { .diseqc_tone = 0, }; +/* ------------------------------------------------------------------ + * special case: lnb supply is connected to the gated i2c + */ + +static int md8800_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + int res = -EIO; + struct saa7134_dev *dev = fe->dvb->priv; + if (fe->ops.i2c_gate_ctrl) { + fe->ops.i2c_gate_ctrl(fe, 1); + if (dev->original_set_voltage) + res = dev->original_set_voltage(fe, voltage); + fe->ops.i2c_gate_ctrl(fe, 0); + } + return res; +}; + +static int md8800_set_high_voltage(struct dvb_frontend *fe, long arg) +{ + int res = -EIO; + struct saa7134_dev *dev = fe->dvb->priv; + if (fe->ops.i2c_gate_ctrl) { + fe->ops.i2c_gate_ctrl(fe, 1); + if (dev->original_set_high_voltage) + res = dev->original_set_high_voltage(fe, arg); + fe->ops.i2c_gate_ctrl(fe, 0); + } + return res; +}; + /* ================================================================== * nxt200x based ATSC cards, helper functions */ @@ -863,12 +901,14 @@ static struct nxt200x_config kworldatsc110 = { static int dvb_init(struct saa7134_dev *dev) { int ret; + int attach_xc3028 = 0; + /* init struct videobuf_dvb */ dev->ts.nr_bufs = 32; dev->ts.nr_packets = 32*4; dev->dvb.name = dev->name; - videobuf_queue_pci_init(&dev->dvb.dvbq, &saa7134_ts_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&dev->dvb.dvbq, &saa7134_ts_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_ALTERNATE, sizeof(struct saa7134_buf), @@ -990,7 +1030,35 @@ static int dvb_init(struct saa7134_dev *dev) configure_tda827x_fe(dev, &tevion_dvbt220rf_config); break; case SAA7134_BOARD_MEDION_MD8800_QUADRO: - configure_tda827x_fe(dev, &md8800_dvbt_config); + if (!use_frontend) { /* terrestrial */ + configure_tda827x_fe(dev, &md8800_dvbt_config); + } else { /* satellite */ + dev->dvb.frontend = dvb_attach(tda10086_attach, + &flydvbs, &dev->i2c_adap); + if (dev->dvb.frontend) { + struct dvb_frontend *fe; + if (dvb_attach(tda826x_attach, dev->dvb.frontend, + 0x60, &dev->i2c_adap, 0) == NULL) + wprintk("%s: Medion Quadro, no tda826x " + "found !\n", __FUNCTION__); + /* Note 10.2. Hac + * up to here. configuration for ctx948 and and one branch + * of md8800 should be identical + */ + /* we need to open the i2c gate (we know it exists) */ + fe = dev->dvb.frontend; + fe->ops.i2c_gate_ctrl(fe, 1); + if (dvb_attach(isl6405_attach, fe, + &dev->i2c_adap, 0x08, 0, 0) == NULL) + wprintk("%s: Medion Quadro, no ISL6405 " + "found !\n", __FUNCTION__); + fe->ops.i2c_gate_ctrl(fe, 0); + dev->original_set_voltage = fe->ops.set_voltage; + fe->ops.set_voltage = md8800_set_voltage; + dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage; + fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage; + } + } break; case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180, @@ -1064,11 +1132,53 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config); break; + case SAA7134_BOARD_PHILIPS_SNAKE: + dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, + &dev->i2c_adap); + if (dev->dvb.frontend) { + if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, + &dev->i2c_adap, 0) == NULL) + wprintk("%s: No tda826x found!\n", __FUNCTION__); + if (dvb_attach(lnbp21_attach, dev->dvb.frontend, + &dev->i2c_adap, 0, 0) == NULL) + wprintk("%s: No lnbp21 found!\n", __FUNCTION__); + } + break; + case SAA7134_BOARD_CREATIX_CTX953: + configure_tda827x_fe(dev, &md8800_dvbt_config); + break; + case SAA7134_BOARD_MSI_TVANYWHERE_AD11: + configure_tda827x_fe(dev, &philips_tiger_s_config); + break; + case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: + dev->dvb.frontend = dvb_attach(mt352_attach, + &avermedia_e506r_mt352_dev, + &dev->i2c_adap); + attach_xc3028 = 1; + break; default: wprintk("Huh? unknown DVB card?\n"); break; } + if (attach_xc3028) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &dev->i2c_adap, + .i2c_addr = 0x61, + .video_dev = dev, + }; + fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); + if (!fe) { + printk(KERN_ERR "%s/2: xc3028 attach failed\n", + dev->name); + dvb_frontend_detach(dev->dvb.frontend); + dvb_unregister_frontend(dev->dvb.frontend); + dev->dvb.frontend = NULL; + return -1; + } + } + if (NULL == dev->dvb.frontend) { printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name); return -1; diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 3d2ec30..e002be5 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -40,7 +40,7 @@ static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; module_param_array(empress_nr, int, NULL, 0444); MODULE_PARM_DESC(empress_nr,"ts device number"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages"); @@ -427,8 +427,8 @@ static int empress_init(struct saa7134_dev *dev) printk(KERN_INFO "%s: registered device video%d [mpeg]\n", dev->name,dev->empress_dev->minor & 0x1f); - videobuf_queue_pci_init(&dev->empress_tsq, &saa7134_ts_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_ALTERNATE, sizeof(struct saa7134_buf), diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index d3322c3..ba71dd0 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -33,11 +33,11 @@ /* ----------------------------------------------------------- */ -static unsigned int i2c_debug = 0; +static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]"); -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index b418881..65f8e59 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -27,15 +27,15 @@ #include "saa7134-reg.h" #include "saa7134.h" -static unsigned int disable_ir = 0; +static unsigned int disable_ir; module_param(disable_ir, int, 0444); MODULE_PARM_DESC(disable_ir,"disable infrared remote support"); -static unsigned int ir_debug = 0; +static unsigned int ir_debug; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); -static int pinnacle_remote = 0; +static int pinnacle_remote; module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index f1b8fca..eae72fd 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -32,7 +32,7 @@ /* ------------------------------------------------------------------ */ -static unsigned int ts_debug = 0; +static unsigned int ts_debug; module_param(ts_debug, int, 0644); MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]"); diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 4e98104..b90c55c 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -35,18 +35,18 @@ /* ------------------------------------------------------------------ */ -static unsigned int audio_debug = 0; +static unsigned int audio_debug; module_param(audio_debug, int, 0644); MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]"); -static unsigned int audio_ddep = 0; +static unsigned int audio_ddep; module_param(audio_ddep, int, 0644); MODULE_PARM_DESC(audio_ddep,"audio ddep overwrite"); static int audio_clock_override = UNSET; module_param(audio_clock_override, int, 0644); -static int audio_clock_tweak = 0; +static int audio_clock_tweak; module_param(audio_clock_tweak, int, 0644); MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with audio crystal that's slightly off (range [-1024 .. 1024])"); diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c index f0d5ed9..cb03042 100644 --- a/drivers/media/video/saa7134/saa7134-vbi.c +++ b/drivers/media/video/saa7134/saa7134-vbi.c @@ -31,7 +31,7 @@ /* ------------------------------------------------------------------ */ -static unsigned int vbi_debug = 0; +static unsigned int vbi_debug; module_param(vbi_debug, int, 0644); MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 39c41ad..ecc5243 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -40,7 +40,7 @@ unsigned int video_debug; static unsigned int gbuffers = 8; -static unsigned int noninterlaced = 0; +static unsigned int noninterlaced; /* 0 */ static unsigned int gbufsize = 720*576*4; static unsigned int gbufsize_max = 720*576*4; static char secam[] = "--"; @@ -1350,14 +1350,14 @@ static int video_open(struct inode *inode, struct file *file) fh->height = 576; v4l2_prio_open(&dev->prio,&fh->prio); - videobuf_queue_pci_init(&fh->cap, &video_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->cap, &video_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct saa7134_buf), fh); - videobuf_queue_pci_init(&fh->vbi, &saa7134_vbi_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vbi, &saa7134_vbi_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct saa7134_buf), diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index f940d02..ba88a10 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -253,7 +253,15 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_607_9FM 129 #define SAA7134_BOARD_BEHOLD_M6 130 #define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131 -#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 +#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 +#define SAA7134_BOARD_PHILIPS_SNAKE 133 +#define SAA7134_BOARD_CREATIX_CTX953 134 +#define SAA7134_BOARD_MSI_TVANYWHERE_AD11 135 +#define SAA7134_BOARD_AVERMEDIA_CARDBUS_506 136 +#define SAA7134_BOARD_AVERMEDIA_A16D 137 +#define SAA7134_BOARD_AVERMEDIA_M115 138 +#define SAA7134_BOARD_VIDEOMATE_T750 139 + #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 @@ -556,7 +564,9 @@ struct saa7134_dev { #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE) /* SAA7134_MPEG_DVB only */ struct videobuf_dvb dvb; - int (*original_demod_sleep)(struct dvb_frontend* fe); + int (*original_demod_sleep)(struct dvb_frontend *fe); + int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); + int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg); #endif }; @@ -594,7 +604,6 @@ extern int saa7134_no_overlay; void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value); -int saa7134_tuner_callback(void *ptr, int command, int arg); #define SAA7134_PGTABLE_SIZE 4096 @@ -631,6 +640,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[]; extern int saa7134_board_init1(struct saa7134_dev *dev); extern int saa7134_board_init2(struct saa7134_dev *dev); +int saa7134_tuner_callback(void *priv, int command, int arg); /* ----------------------------------------------------------- */ diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index 66cc92c..14d9ee2 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -52,7 +52,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index d5d7d6c..312a01a 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c @@ -35,7 +35,7 @@ static const char version[] = "0.24"; #include #include "se401.h" -static int flickerless=0; +static int flickerless; static int video_nr = -1; static struct usb_device_id device_table [] = { diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index c40ba3a..94f393e 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -528,7 +528,7 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) /* Search for the SOF marker (fixed part) in the header */ for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) { - if (unlikely(i+j) == len) + if (unlikely(i+j == len)) return NULL; if (*(m+i+j) == marker[cam->sof.bytesread]) { cam->sof.header[cam->sof.bytesread] = *(m+i+j); @@ -3239,7 +3239,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) { struct usb_device *udev = interface_to_usbdev(intf); struct sn9c102_device* cam; - static unsigned int dev_nr = 0; + static unsigned int dev_nr; unsigned int i; int err = 0, r; diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h index 2d7d786..2dc7c68 100644 --- a/drivers/media/video/sn9c102/sn9c102_sensor.h +++ b/drivers/media/video/sn9c102/sn9c102_sensor.h @@ -126,7 +126,7 @@ extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2], Register adresses must be < 256. */ #define sn9c102_write_const_regs(sn9c102_device, data...) \ - ({ const static u8 _valreg[][2] = {data}; \ + ({ static const u8 _valreg[][2] = {data}; \ sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); }) /*****************************************************************************/ diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c new file mode 100644 index 0000000..322f837 --- /dev/null +++ b/drivers/media/video/soc_camera.c @@ -0,0 +1,999 @@ +/* + * camera image capture (abstract) bus driver + * + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This driver provides an interface between platform-specific camera + * busses and camera devices. It should be used if the camera is + * connected not over a "proper" bus like PCI or USB, but over a + * special bus, like, for example, the Quick Capture interface on PXA270 + * SoCs. Later it should also be used for i.MX31 SoCs from Freescale. + * It can handle multiple cameras and / or multiple busses, which can + * be used, e.g., in stereo-vision applications. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static LIST_HEAD(hosts); +static LIST_HEAD(devices); +static DEFINE_MUTEX(list_lock); +static DEFINE_MUTEX(video_lock); + +const static struct soc_camera_data_format* +format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc) +{ + unsigned int i; + + for (i = 0; i < icd->ops->num_formats; i++) + if (icd->ops->formats[i].fourcc == fourcc) + return icd->ops->formats + i; + return NULL; +} + +static int soc_camera_try_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + enum v4l2_field field; + const struct soc_camera_data_format *fmt; + int ret; + + WARN_ON(priv != file->private_data); + + fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); + if (!fmt) { + dev_dbg(&icd->dev, "invalid format 0x%08x\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } + + dev_dbg(&icd->dev, "fmt: 0x%08x\n", fmt->fourcc); + + field = f->fmt.pix.field; + + if (field == V4L2_FIELD_ANY) { + field = V4L2_FIELD_NONE; + } else if (V4L2_FIELD_NONE != field) { + dev_err(&icd->dev, "Field type invalid.\n"); + return -EINVAL; + } + + /* limit to host capabilities */ + ret = ici->try_fmt_cap(ici, f); + + /* limit to sensor capabilities */ + if (!ret) + ret = icd->ops->try_fmt_cap(icd, f); + + /* calculate missing fields */ + f->fmt.pix.field = field; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + + return ret; +} + +static int soc_camera_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + if (inp->index != 0) + return -EINVAL; + + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_UNKNOWN; + strcpy(inp->name, "Camera"); + + return 0; +} + +static int soc_camera_g_input(struct file *file, void *priv, unsigned int *i) +{ + *i = 0; + + return 0; +} + +static int soc_camera_s_input(struct file *file, void *priv, unsigned int i) +{ + if (i > 0) + return -EINVAL; + + return 0; +} + +static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) +{ + return 0; +} + +static int soc_camera_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *p) +{ + int ret; + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + WARN_ON(priv != file->private_data); + + dev_dbg(&icd->dev, "%s: %d\n", __FUNCTION__, p->memory); + + ret = videobuf_reqbufs(&icf->vb_vidq, p); + if (ret < 0) + return ret; + + return ici->reqbufs(icf, p); + + return ret; +} + +static int soc_camera_querybuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct soc_camera_file *icf = file->private_data; + + WARN_ON(priv != file->private_data); + + return videobuf_querybuf(&icf->vb_vidq, p); +} + +static int soc_camera_qbuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct soc_camera_file *icf = file->private_data; + + WARN_ON(priv != file->private_data); + + return videobuf_qbuf(&icf->vb_vidq, p); +} + +static int soc_camera_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct soc_camera_file *icf = file->private_data; + + WARN_ON(priv != file->private_data); + + return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK); +} + +static int soc_camera_open(struct inode *inode, struct file *file) +{ + struct video_device *vdev; + struct soc_camera_device *icd; + struct soc_camera_host *ici; + struct soc_camera_file *icf; + int ret; + + icf = vmalloc(sizeof(*icf)); + if (!icf) + return -ENOMEM; + + /* Protect against icd->remove() until we module_get() both drivers. */ + mutex_lock(&video_lock); + + vdev = video_devdata(file); + icd = container_of(vdev->dev, struct soc_camera_device, dev); + ici = to_soc_camera_host(icd->dev.parent); + + if (!try_module_get(icd->ops->owner)) { + dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); + ret = -EINVAL; + goto emgd; + } + + if (!try_module_get(ici->owner)) { + dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); + ret = -EINVAL; + goto emgi; + } + + icd->use_count++; + + icf->icd = icd; + + /* Now we really have to activate the camera */ + if (icd->use_count == 1) { + ret = ici->add(icd); + if (ret < 0) { + dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); + icd->use_count--; + goto eiciadd; + } + } + + mutex_unlock(&video_lock); + + file->private_data = icf; + dev_dbg(&icd->dev, "camera device open\n"); + + /* We must pass NULL as dev pointer, then all pci_* dma operations + * transform to normal dma_* ones. Do we need an irqlock? */ + videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL, + V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, + ici->msize, icd); + + return 0; + + /* All errors are entered with the video_lock held */ +eiciadd: + module_put(ici->owner); +emgi: + module_put(icd->ops->owner); +emgd: + mutex_unlock(&video_lock); + vfree(icf); + return ret; +} + +static int soc_camera_close(struct inode *inode, struct file *file) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct video_device *vdev = icd->vdev; + + mutex_lock(&video_lock); + icd->use_count--; + if (!icd->use_count) + ici->remove(icd); + module_put(icd->ops->owner); + module_put(ici->owner); + mutex_unlock(&video_lock); + + vfree(file->private_data); + + dev_dbg(vdev->dev, "camera device close\n"); + + return 0; +} + +static int soc_camera_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct video_device *vdev = icd->vdev; + int err = -EINVAL; + + dev_err(vdev->dev, "camera device read not implemented\n"); + + return err; +} + +static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + int err; + + dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma); + + err = videobuf_mmap_mapper(&icf->vb_vidq, vma); + + dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n", + (unsigned long)vma->vm_start, + (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, + err); + + return err; +} + +static unsigned int soc_camera_poll(struct file *file, poll_table *pt) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + if (list_empty(&icf->vb_vidq.stream)) { + dev_err(&icd->dev, "Trying to poll with no queued buffers!\n"); + return POLLERR; + } + + return ici->poll(file, pt); +} + + +static struct file_operations soc_camera_fops = { + .owner = THIS_MODULE, + .open = soc_camera_open, + .release = soc_camera_close, + .ioctl = video_ioctl2, + .read = soc_camera_read, + .mmap = soc_camera_mmap, + .poll = soc_camera_poll, + .llseek = no_llseek, +}; + + +static int soc_camera_s_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + int ret; + struct v4l2_rect rect; + const static struct soc_camera_data_format *data_fmt; + + WARN_ON(priv != file->private_data); + + data_fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); + if (!data_fmt) + return -EINVAL; + + /* cached_datawidth may be further adjusted by the ici */ + icd->cached_datawidth = data_fmt->depth; + + ret = soc_camera_try_fmt_cap(file, icf, f); + if (ret < 0) + return ret; + + rect.left = icd->x_current; + rect.top = icd->y_current; + rect.width = f->fmt.pix.width; + rect.height = f->fmt.pix.height; + ret = ici->set_capture_format(icd, f->fmt.pix.pixelformat, &rect); + + if (!ret) { + icd->current_fmt = data_fmt; + icd->width = rect.width; + icd->height = rect.height; + icf->vb_vidq.field = f->fmt.pix.field; + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) + dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", + f->type); + + dev_dbg(&icd->dev, "set width: %d height: %d\n", + icd->width, icd->height); + } + + return ret; +} + +static int soc_camera_enum_fmt_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + const struct soc_camera_data_format *format; + + WARN_ON(priv != file->private_data); + + if (f->index >= icd->ops->num_formats) + return -EINVAL; + + format = &icd->ops->formats[f->index]; + + strlcpy(f->description, format->name, sizeof(f->description)); + f->pixelformat = format->fourcc; + return 0; +} + +static int soc_camera_g_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + f->fmt.pix.width = icd->width; + f->fmt.pix.height = icd->height; + f->fmt.pix.field = icf->vb_vidq.field; + f->fmt.pix.pixelformat = icd->current_fmt->fourcc; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * icd->current_fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", + icd->current_fmt->fourcc); + return 0; +} + +static int soc_camera_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + WARN_ON(priv != file->private_data); + + strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver)); + return ici->querycap(ici, cap); +} + +static int soc_camera_streamon(struct file *file, void *priv, + enum v4l2_buf_type i) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + + if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + icd->ops->start_capture(icd); + + /* This calls buf_queue from host driver's videobuf_queue_ops */ + return videobuf_streamon(&icf->vb_vidq); +} + +static int soc_camera_streamoff(struct file *file, void *priv, + enum v4l2_buf_type i) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + + if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + /* This calls buf_release from host driver's videobuf_queue_ops for all + * remaining buffers. When the last buffer is freed, stop capture */ + videobuf_streamoff(&icf->vb_vidq); + + icd->ops->stop_capture(icd); + + return 0; +} + +static int soc_camera_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + int i; + + WARN_ON(priv != file->private_data); + + if (!qc->id) + return -EINVAL; + + for (i = 0; i < icd->ops->num_controls; i++) + if (qc->id == icd->ops->controls[i].id) { + memcpy(qc, &(icd->ops->controls[i]), + sizeof(*qc)); + return 0; + } + + return -EINVAL; +} + +static int soc_camera_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + switch (ctrl->id) { + case V4L2_CID_GAIN: + if (icd->gain == (unsigned short)~0) + return -EINVAL; + ctrl->value = icd->gain; + return 0; + case V4L2_CID_EXPOSURE: + if (icd->exposure == (unsigned short)~0) + return -EINVAL; + ctrl->value = icd->exposure; + return 0; + } + + if (icd->ops->get_control) + return icd->ops->get_control(icd, ctrl); + return -EINVAL; +} + +static int soc_camera_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + if (icd->ops->set_control) + return icd->ops->set_control(icd, ctrl); + return -EINVAL; +} + +static int soc_camera_cropcap(struct file *file, void *fh, + struct v4l2_cropcap *a) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->bounds.left = icd->x_min; + a->bounds.top = icd->y_min; + a->bounds.width = icd->width_max; + a->bounds.height = icd->height_max; + a->defrect.left = icd->x_min; + a->defrect.top = icd->y_min; + a->defrect.width = 640; + a->defrect.height = 480; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int soc_camera_g_crop(struct file *file, void *fh, + struct v4l2_crop *a) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->c.left = icd->x_current; + a->c.top = icd->y_current; + a->c.width = icd->width; + a->c.height = icd->height; + + return 0; +} + +static int soc_camera_s_crop(struct file *file, void *fh, + struct v4l2_crop *a) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + int ret; + + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + ret = ici->set_capture_format(icd, 0, &a->c); + if (!ret) { + icd->width = a->c.width; + icd->height = a->c.height; + icd->x_current = a->c.left; + icd->y_current = a->c.top; + } + + return ret; +} + +static int soc_camera_g_chip_ident(struct file *file, void *fh, + struct v4l2_chip_ident *id) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + if (!icd->ops->get_chip_id) + return -EINVAL; + + return icd->ops->get_chip_id(icd, id); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int soc_camera_g_register(struct file *file, void *fh, + struct v4l2_register *reg) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + if (!icd->ops->get_register) + return -EINVAL; + + return icd->ops->get_register(icd, reg); +} + +static int soc_camera_s_register(struct file *file, void *fh, + struct v4l2_register *reg) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + if (!icd->ops->set_register) + return -EINVAL; + + return icd->ops->set_register(icd, reg); +} +#endif + +static int device_register_link(struct soc_camera_device *icd) +{ + int ret = device_register(&icd->dev); + + if (ret < 0) { + /* Prevent calling device_unregister() */ + icd->dev.parent = NULL; + dev_err(&icd->dev, "Cannot register device: %d\n", ret); + /* Even if probe() was unsuccessful for all registered drivers, + * device_register() returns 0, and we add the link, just to + * document this camera's control device */ + } else if (icd->control) + /* Have to sysfs_remove_link() before device_unregister()? */ + if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj, + "control")) + dev_warn(&icd->dev, + "Failed creating the control symlink\n"); + return ret; +} + +/* So far this function cannot fail */ +static void scan_add_host(struct soc_camera_host *ici) +{ + struct soc_camera_device *icd; + + mutex_lock(&list_lock); + + list_for_each_entry(icd, &devices, list) { + if (icd->iface == ici->nr) { + icd->dev.parent = &ici->dev; + device_register_link(icd); + } + } + + mutex_unlock(&list_lock); +} + +/* return: 0 if no match found or a match found and + * device_register() successful, error code otherwise */ +static int scan_add_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici; + int ret = 0; + + mutex_lock(&list_lock); + + list_add_tail(&icd->list, &devices); + + /* Watch out for class_for_each_device / class_find_device API by + * Dave Young */ + list_for_each_entry(ici, &hosts, list) { + if (icd->iface == ici->nr) { + ret = 1; + icd->dev.parent = &ici->dev; + break; + } + } + + mutex_unlock(&list_lock); + + if (ret) + ret = device_register_link(icd); + + return ret; +} + +static int soc_camera_probe(struct device *dev) +{ + struct soc_camera_device *icd = to_soc_camera_dev(dev); + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + int ret; + + if (!icd->probe) + return -ENODEV; + + /* We only call ->add() here to activate and probe the camera. + * We shall ->remove() and deactivate it immediately afterwards. */ + ret = ici->add(icd); + if (ret < 0) + return ret; + + ret = icd->probe(icd); + if (ret >= 0) { + const struct v4l2_queryctrl *qctrl; + + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); + icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); + icd->exposure = qctrl ? qctrl->default_value : + (unsigned short)~0; + } + ici->remove(icd); + + return ret; +} + +/* This is called on device_unregister, which only means we have to disconnect + * from the host, but not remove ourselves from the device list */ +static int soc_camera_remove(struct device *dev) +{ + struct soc_camera_device *icd = to_soc_camera_dev(dev); + + if (icd->remove) + icd->remove(icd); + + return 0; +} + +static struct bus_type soc_camera_bus_type = { + .name = "soc-camera", + .probe = soc_camera_probe, + .remove = soc_camera_remove, +}; + +static struct device_driver ic_drv = { + .name = "camera", + .bus = &soc_camera_bus_type, + .owner = THIS_MODULE, +}; + +/* + * Image capture host - this is a host device, not a bus device, so, + * no bus reference, no probing. + */ +static struct class soc_camera_host_class = { + .owner = THIS_MODULE, + .name = "camera_host", +}; + +static void dummy_release(struct device *dev) +{ +} + +int soc_camera_host_register(struct soc_camera_host *ici, struct module *owner) +{ + int ret; + struct soc_camera_host *ix; + + if (!ici->vbq_ops || !ici->add || !ici->remove || !owner) + return -EINVAL; + + /* Number might be equal to the platform device ID */ + sprintf(ici->dev.bus_id, "camera_host%d", ici->nr); + ici->dev.class = &soc_camera_host_class; + + mutex_lock(&list_lock); + list_for_each_entry(ix, &hosts, list) { + if (ix->nr == ici->nr) { + mutex_unlock(&list_lock); + return -EBUSY; + } + } + + list_add_tail(&ici->list, &hosts); + mutex_unlock(&list_lock); + + ici->owner = owner; + ici->dev.release = dummy_release; + + ret = device_register(&ici->dev); + + if (ret) + goto edevr; + + scan_add_host(ici); + + return 0; + +edevr: + mutex_lock(&list_lock); + list_del(&ici->list); + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(soc_camera_host_register); + +/* Unregister all clients! */ +void soc_camera_host_unregister(struct soc_camera_host *ici) +{ + struct soc_camera_device *icd; + + mutex_lock(&list_lock); + + list_del(&ici->list); + + list_for_each_entry(icd, &devices, list) { + if (icd->dev.parent == &ici->dev) { + device_unregister(&icd->dev); + /* Not before device_unregister(), .remove + * needs parent to call ici->remove() */ + icd->dev.parent = NULL; + memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj)); + } + } + + mutex_unlock(&list_lock); + + device_unregister(&ici->dev); +} +EXPORT_SYMBOL(soc_camera_host_unregister); + +/* Image capture device */ +int soc_camera_device_register(struct soc_camera_device *icd) +{ + struct soc_camera_device *ix; + int num = -1, i; + + if (!icd) + return -EINVAL; + + for (i = 0; i < 256 && num < 0; i++) { + num = i; + list_for_each_entry(ix, &devices, list) { + if (ix->iface == icd->iface && ix->devnum == i) { + num = -1; + break; + } + } + } + + if (num < 0) + /* ok, we have 256 cameras on this host... + * man, stay reasonable... */ + return -ENOMEM; + + icd->devnum = num; + icd->dev.bus = &soc_camera_bus_type; + snprintf(icd->dev.bus_id, sizeof(icd->dev.bus_id), + "%u-%u", icd->iface, icd->devnum); + + icd->dev.release = dummy_release; + + if (icd->ops->get_datawidth) + icd->cached_datawidth = icd->ops->get_datawidth(icd); + + return scan_add_device(icd); +} +EXPORT_SYMBOL(soc_camera_device_register); + +void soc_camera_device_unregister(struct soc_camera_device *icd) +{ + mutex_lock(&list_lock); + list_del(&icd->list); + + /* The bus->remove will be eventually called */ + if (icd->dev.parent) + device_unregister(&icd->dev); + mutex_unlock(&list_lock); +} +EXPORT_SYMBOL(soc_camera_device_unregister); + +int soc_camera_video_start(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int err = -ENOMEM; + struct video_device *vdev; + + if (!icd->dev.parent) + return -ENODEV; + + vdev = video_device_alloc(); + if (!vdev) + goto evidallocd; + dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev); + + strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); + /* Maybe better &ici->dev */ + vdev->dev = &icd->dev; + vdev->type = VID_TYPE_CAPTURE; + vdev->current_norm = V4L2_STD_UNKNOWN; + vdev->fops = &soc_camera_fops; + vdev->release = video_device_release; + vdev->minor = -1; + vdev->tvnorms = V4L2_STD_UNKNOWN, + vdev->vidioc_querycap = soc_camera_querycap; + vdev->vidioc_g_fmt_cap = soc_camera_g_fmt_cap; + vdev->vidioc_enum_fmt_cap = soc_camera_enum_fmt_cap; + vdev->vidioc_s_fmt_cap = soc_camera_s_fmt_cap; + vdev->vidioc_enum_input = soc_camera_enum_input; + vdev->vidioc_g_input = soc_camera_g_input; + vdev->vidioc_s_input = soc_camera_s_input; + vdev->vidioc_s_std = soc_camera_s_std; + vdev->vidioc_reqbufs = soc_camera_reqbufs; + vdev->vidioc_try_fmt_cap = soc_camera_try_fmt_cap; + vdev->vidioc_querybuf = soc_camera_querybuf; + vdev->vidioc_qbuf = soc_camera_qbuf; + vdev->vidioc_dqbuf = soc_camera_dqbuf; + vdev->vidioc_streamon = soc_camera_streamon; + vdev->vidioc_streamoff = soc_camera_streamoff; + vdev->vidioc_queryctrl = soc_camera_queryctrl; + vdev->vidioc_g_ctrl = soc_camera_g_ctrl; + vdev->vidioc_s_ctrl = soc_camera_s_ctrl; + vdev->vidioc_cropcap = soc_camera_cropcap; + vdev->vidioc_g_crop = soc_camera_g_crop; + vdev->vidioc_s_crop = soc_camera_s_crop; + vdev->vidioc_g_chip_ident = soc_camera_g_chip_ident; +#ifdef CONFIG_VIDEO_ADV_DEBUG + vdev->vidioc_g_register = soc_camera_g_register; + vdev->vidioc_s_register = soc_camera_s_register; +#endif + + icd->current_fmt = &icd->ops->formats[0]; + + err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor); + if (err < 0) { + dev_err(vdev->dev, "video_register_device failed\n"); + goto evidregd; + } + icd->vdev = vdev; + + return 0; + +evidregd: + video_device_release(vdev); +evidallocd: + return err; +} +EXPORT_SYMBOL(soc_camera_video_start); + +void soc_camera_video_stop(struct soc_camera_device *icd) +{ + struct video_device *vdev = icd->vdev; + + dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + + if (!icd->dev.parent || !vdev) + return; + + mutex_lock(&video_lock); + video_unregister_device(vdev); + icd->vdev = NULL; + mutex_unlock(&video_lock); +} +EXPORT_SYMBOL(soc_camera_video_stop); + +static int __init soc_camera_init(void) +{ + int ret = bus_register(&soc_camera_bus_type); + if (ret) + return ret; + ret = driver_register(&ic_drv); + if (ret) + goto edrvr; + ret = class_register(&soc_camera_host_class); + if (ret) + goto eclr; + + return 0; + +eclr: + driver_unregister(&ic_drv); +edrvr: + bus_unregister(&soc_camera_bus_type); + return ret; +} + +static void __exit soc_camera_exit(void) +{ + class_unregister(&soc_camera_host_class); + driver_unregister(&ic_drv); + bus_unregister(&soc_camera_bus_type); +} + +module_init(soc_camera_init); +module_exit(soc_camera_exit); + +MODULE_DESCRIPTION("Image capture bus driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index ceba45a..d2bf541 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -1465,7 +1465,7 @@ static void stk_camera_disconnect(struct usb_interface *interface) } #ifdef CONFIG_PM -int stk_camera_suspend(struct usb_interface *intf, pm_message_t message) +static int stk_camera_suspend(struct usb_interface *intf, pm_message_t message) { struct stk_camera *dev = usb_get_intfdata(intf); if (is_streaming(dev)) { @@ -1476,7 +1476,7 @@ int stk_camera_suspend(struct usb_interface *intf, pm_message_t message) return 0; } -int stk_camera_resume(struct usb_interface *intf) +static int stk_camera_resume(struct usb_interface *intf) { struct stk_camera *dev = usb_get_intfdata(intf); if (!is_initialised(dev)) diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 3fb85af..3118dd3 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -58,7 +58,7 @@ static struct saa7146 saa7146s[SAA7146_MAX]; -static int saa_num = 0; /* number of SAA7146s in use */ +static int saa_num; /* number of SAA7146s in use */ static int video_nr = -1; module_param(video_nr, int, 0); @@ -248,7 +248,7 @@ static void I2CBusScan(struct saa7146 *saa) attach_inform(saa, i); } -static int debiwait_maxwait = 0; +static int debiwait_maxwait; static int wait_for_debi_done(struct saa7146 *saa) { diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index afc32aa..1542797 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -72,10 +72,13 @@ #include "stv680.h" static int video_nr = -1; -static int swapRGB = 0; /* default for auto sleect */ -static int swapRGB_on = 0; /* default to allow auto select; -1=swap never, +1= swap always */ -static unsigned int debug = 0; +static int swapRGB; /* 0 = default for auto select */ + +/* 0 = default to allow auto select; -1 = swap never, +1 = swap always */ +static int swapRGB_on; + +static unsigned int debug; #define PDEBUG(level, fmt, args...) \ do { \ diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 55bc89a..6f2449a 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -32,8 +32,6 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tda8290" - /* ---------------------------------------------------------------------- */ struct tda8290_priv { @@ -674,6 +672,7 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "tda829x"; if (cfg) { priv->cfg.config = cfg->lna_cfg; priv->cfg.tuner_callback = cfg->tuner_callback; diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index ef494fe..845fc90 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c @@ -31,7 +31,7 @@ #include "tda9840.h" -static int debug = 0; /* insmod parameter */ +static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define dprintk(args...) \ diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 106c93b..75d0840 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -25,8 +25,6 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tda9887" - struct tda9887_priv { struct tuner_i2c_props i2c_props; @@ -673,6 +671,7 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "tda9887"; priv->mode = T_STANDBY; tuner_info("tda988[5/6/7] found\n"); diff --git a/drivers/media/video/tea5761.c b/drivers/media/video/tea5761.c index 5326eec..bd5ad54 100644 --- a/drivers/media/video/tea5761.c +++ b/drivers/media/video/tea5761.c @@ -14,12 +14,10 @@ #include "tuner-i2c.h" #include "tea5761.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tea5761" - struct tea5761_priv { struct tuner_i2c_props i2c_props; @@ -131,7 +129,7 @@ static void tea5761_status_dump(unsigned char *buffer) frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4; /* Freq in KHz */ - printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n", + printk(KERN_INFO "tea5761: Frequency %d.%03d KHz (divider = 0x%04x)\n", frq / 1000, frq % 1000, div); } @@ -302,6 +300,7 @@ struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "tea5761"; memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops, sizeof(struct dvb_tuner_ops)); diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index e1b48d8..833f276 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -16,12 +16,10 @@ #include "tuner-i2c.h" #include "tea5767.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tea5767" - /*****************************************************************************/ struct tea5767_priv { @@ -137,14 +135,14 @@ static void tea5767_status_dump(struct tea5767_priv *priv, unsigned int div, frq; if (TEA5767_READY_FLAG_MASK & buffer[0]) - printk(PREFIX "Ready Flag ON\n"); + tuner_info("Ready Flag ON\n"); else - printk(PREFIX "Ready Flag OFF\n"); + tuner_info("Ready Flag OFF\n"); if (TEA5767_BAND_LIMIT_MASK & buffer[0]) - printk(PREFIX "Tuner at band limit\n"); + tuner_info("Tuner at band limit\n"); else - printk(PREFIX "Tuner not at band limit\n"); + tuner_info("Tuner not at band limit\n"); div = ((buffer[0] & 0x3f) << 8) | buffer[1]; @@ -166,23 +164,23 @@ static void tea5767_status_dump(struct tea5767_priv *priv, buffer[0] = (div >> 8) & 0x3f; buffer[1] = div & 0xff; - printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n", - frq / 1000, frq % 1000, div); + tuner_info("Frequency %d.%03d KHz (divider = 0x%04x)\n", + frq / 1000, frq % 1000, div); if (TEA5767_STEREO_MASK & buffer[2]) - printk(PREFIX "Stereo\n"); + tuner_info("Stereo\n"); else - printk(PREFIX "Mono\n"); + tuner_info("Mono\n"); - printk(PREFIX "IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK); + tuner_info("IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK); - printk(PREFIX "ADC Level = %d\n", - (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4); + tuner_info("ADC Level = %d\n", + (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4); - printk(PREFIX "Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK)); + tuner_info("Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK)); - printk(PREFIX "Reserved = 0x%02x\n", - (buffer[4] & TEA5767_RESERVED_MASK)); + tuner_info("Reserved = 0x%02x\n", + (buffer[4] & TEA5767_RESERVED_MASK)); } /* Freq should be specifyed at 62.5 Hz */ @@ -456,6 +454,8 @@ struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "tea5767"; + priv->ctrl.xtal_freq = TEA5767_HIGH_LO_32768; priv->ctrl.port1 = 1; priv->ctrl.port2 = 1; diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index 523df0b..32c0b48 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c @@ -33,7 +33,7 @@ #include "tea6415c.h" -static int debug = 0; /* insmod parameter */ +static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define dprintk(args...) \ diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index ca05cd6..215b104 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c @@ -33,7 +33,7 @@ #include "tea6420.h" -static int debug = 0; /* insmod parameter */ +static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define dprintk(args...) \ diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 78a09a2..335a971 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -68,9 +68,9 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_INSMOD; /* insmod options used at init time => read/only */ -static unsigned int addr = 0; -static unsigned int no_autodetect = 0; -static unsigned int show_i2c = 0; +static unsigned int addr; +static unsigned int no_autodetect; +static unsigned int show_i2c; /* insmod options used at runtime => read/write */ static int tuner_debug; @@ -313,20 +313,10 @@ static void tuner_i2c_address_check(struct tuner *t) tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n"); tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n"); tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n", - t->i2c->adapter->name, t->i2c->addr, t->type, - tuners[t->type].name); + t->i2c->adapter->name, t->i2c->addr, t->type, t->i2c->name); tuner_warn("====================== WARNING! ======================\n"); } -static void attach_simple_tuner(struct tuner *t) -{ - struct simple_tuner_config cfg = { - .type = t->type, - .tun = &tuners[t->type] - }; - simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg); -} - static void attach_tda829x(struct tuner *t) { struct tda829x_config cfg = { @@ -352,11 +342,6 @@ static void set_type(struct i2c_client *c, unsigned int type, return; } - if (type >= tuner_count) { - tuner_warn ("tuner 0x%02x: Tuner count greater than %d\n",c->addr,tuner_count); - return; - } - t->type = type; t->config = new_config; if (tuner_callback != NULL) { @@ -409,7 +394,12 @@ static void set_type(struct i2c_client *c, unsigned int type, buffer[2] = 0x86; buffer[3] = 0x54; i2c_master_send(c, buffer, 4); - attach_simple_tuner(t); + if (simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, + t->type) == NULL) { + t->type = TUNER_ABSENT; + t->mode_mask = T_UNINITIALIZED; + return; + } break; case TUNER_PHILIPS_TD1316: buffer[0] = 0x0b; @@ -417,7 +407,12 @@ static void set_type(struct i2c_client *c, unsigned int type, buffer[2] = 0x86; buffer[3] = 0xa4; i2c_master_send(c,buffer,4); - attach_simple_tuner(t); + if (simple_tuner_attach(&t->fe, t->i2c->adapter, + t->i2c->addr, t->type) == NULL) { + t->type = TUNER_ABSENT; + t->mode_mask = T_UNINITIALIZED; + return; + } break; case TUNER_XC2028: { @@ -455,7 +450,12 @@ static void set_type(struct i2c_client *c, unsigned int type, } break; default: - attach_simple_tuner(t); + if (simple_tuner_attach(&t->fe, t->i2c->adapter, + t->i2c->addr, t->type) == NULL) { + t->type = TUNER_ABSENT; + t->mode_mask = T_UNINITIALIZED; + return; + } break; } diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h index de52e8f..60ba794 100644 --- a/drivers/media/video/tuner-i2c.h +++ b/drivers/media/video/tuner-i2c.h @@ -26,6 +26,10 @@ struct tuner_i2c_props { u8 addr; struct i2c_adapter *adap; + + /* used for tuner instance management */ + int count; + char *name; }; static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len) @@ -59,29 +63,111 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, return (ret == 2) ? ilen : ret; } -#define tuner_warn(fmt, arg...) do { \ - printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr, ##arg); \ +/* Callers must declare as a global for the module: + * + * static LIST_HEAD(hybrid_tuner_instance_list); + * + * hybrid_tuner_instance_list should be the third argument + * passed into hybrid_tuner_request_state(). + * + * state structure must contain the following: + * + * struct list_head hybrid_tuner_instance_list; + * struct tuner_i2c_props i2c_props; + * + * hybrid_tuner_instance_list (both within state structure and globally) + * is only required if the driver is using hybrid_tuner_request_state + * and hybrid_tuner_release_state to manage state sharing between + * multiple instances of hybrid tuners. + */ + +#define tuner_printk(kernlvl, i2cprops, fmt, arg...) do { \ + printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name, \ + i2cprops.adap ? \ + i2c_adapter_id(i2cprops.adap) : -1, \ + i2cprops.addr, ##arg); \ } while (0) -#define tuner_info(fmt, arg...) do { \ - printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr , ##arg); \ +/* TO DO: convert all callers of these macros to pass in + * struct tuner_i2c_props, then remove the macro wrappers */ + +#define __tuner_warn(i2cprops, fmt, arg...) do { \ + tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg); \ } while (0) -#define tuner_err(fmt, arg...) do { \ - printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr , ##arg); \ +#define __tuner_info(i2cprops, fmt, arg...) do { \ + tuner_printk(KERN_INFO, i2cprops, fmt, ##arg); \ } while (0) -#define tuner_dbg(fmt, arg...) do { \ +#define __tuner_err(i2cprops, fmt, arg...) do { \ + tuner_printk(KERN_ERR, i2cprops, fmt, ##arg); \ + } while (0) + +#define __tuner_dbg(i2cprops, fmt, arg...) do { \ if ((debug)) \ - printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr , ##arg); \ + tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg); \ } while (0) +#define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg) +#define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg) +#define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg) +#define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg) + +/****************************************************************************/ + +/* The return value of hybrid_tuner_request_state indicates the number of + * instances using this tuner object. + * + * 0 - no instances, indicates an error - kzalloc must have failed + * + * 1 - one instance, indicates that the tuner object was created successfully + * + * 2 (or more) instances, indicates that an existing tuner object was found + */ + +#define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\ +({ \ + int __ret = 0; \ + list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \ + if ((state->i2c_props.addr == i2caddr) && \ + ((state->i2c_props.adap ? \ + i2c_adapter_id(state->i2c_props.adap) : -1) == \ + (i2cadap ? i2c_adapter_id(i2cadap) : -1))) { \ + __tuner_info(state->i2c_props, \ + "attaching existing instance\n"); \ + state->i2c_props.count++; \ + __ret = state->i2c_props.count; \ + break; \ + } \ + } \ + if (0 == __ret) { \ + state = kzalloc(sizeof(type), GFP_KERNEL); \ + if (NULL == state) \ + goto __fail; \ + state->i2c_props.addr = i2caddr; \ + state->i2c_props.adap = i2cadap; \ + state->i2c_props.name = devname; \ + __tuner_info(state->i2c_props, \ + "creating new instance\n"); \ + list_add_tail(&state->hybrid_tuner_instance_list, &list);\ + state->i2c_props.count++; \ + __ret = state->i2c_props.count; \ + } \ +__fail: \ + __ret; \ +}) + +#define hybrid_tuner_release_state(state) \ +({ \ + int __ret; \ + state->i2c_props.count--; \ + __ret = state->i2c_props.count; \ + if (!state->i2c_props.count) { \ + __tuner_info(state->i2c_props, "destroying instance\n");\ + list_del(&state->hybrid_tuner_instance_list); \ + kfree(state); \ + } \ + __ret; \ +}) + #endif /* __TUNER_I2C_H__ */ diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index c1db576..ee5ef86 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -13,15 +13,13 @@ #include "tuner-i2c.h" #include "tuner-simple.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tuner-simple" - -static int offset = 0; +static int offset; module_param(offset, int, 0664); -MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); +MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner"); /* ---------------------------------------------------------------------- */ @@ -36,8 +34,8 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); */ #define TEMIC_SET_PAL_I 0x05 #define TEMIC_SET_PAL_DK 0x09 -#define TEMIC_SET_PAL_L 0x0a // SECAM ? -#define TEMIC_SET_PAL_L2 0x0b // change IF ! +#define TEMIC_SET_PAL_L 0x0a /* SECAM ? */ +#define TEMIC_SET_PAL_L2 0x0b /* change IF ! */ #define TEMIC_SET_PAL_BG 0x0c /* tv tuner system standard selection for Philips FQ1216ME @@ -107,7 +105,7 @@ static int tuner_read_status(struct dvb_frontend *fe) struct tuner_simple_priv *priv = fe->tuner_priv; unsigned char byte; - if (1 != tuner_i2c_xfer_recv(&priv->i2c_props,&byte,1)) + if (1 != tuner_i2c_xfer_recv(&priv->i2c_props, &byte, 1)) return 0; return byte; @@ -121,13 +119,13 @@ static inline int tuner_signal(const int status) static inline int tuner_stereo(const int type, const int status) { switch (type) { - case TUNER_PHILIPS_FM1216ME_MK3: - case TUNER_PHILIPS_FM1236_MK3: - case TUNER_PHILIPS_FM1256_IH3: - case TUNER_LG_NTSC_TAPE: - return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); - default: - return status & TUNER_STEREO; + case TUNER_PHILIPS_FM1216ME_MK3: + case TUNER_PHILIPS_FM1236_MK3: + case TUNER_PHILIPS_FM1256_IH3: + case TUNER_LG_NTSC_TAPE: + return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); + default: + return status & TUNER_STEREO; } } @@ -173,129 +171,137 @@ static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength) /* ---------------------------------------------------------------------- */ -static int simple_set_tv_freq(struct dvb_frontend *fe, - struct analog_parameters *params) +static inline char *tuner_param_name(enum param_type type) { - struct tuner_simple_priv *priv = fe->tuner_priv; - u8 config, cb, tuneraddr; - u16 div; - struct tunertype *tun; - u8 buffer[4]; - int rc, IFPCoff, i, j; - enum param_type desired_type; - struct tuner_params *t_params; + char *name; - tun = priv->tun; + switch (type) { + case TUNER_PARAM_TYPE_RADIO: + name = "radio"; + break; + case TUNER_PARAM_TYPE_PAL: + name = "pal"; + break; + case TUNER_PARAM_TYPE_SECAM: + name = "secam"; + break; + case TUNER_PARAM_TYPE_NTSC: + name = "ntsc"; + break; + default: + name = "unknown"; + break; + } + return name; +} - /* IFPCoff = Video Intermediate Frequency - Vif: - 940 =16*58.75 NTSC/J (Japan) - 732 =16*45.75 M/N STD - 704 =16*44 ATSC (at DVB code) - 632 =16*39.50 I U.K. - 622.4=16*38.90 B/G D/K I, L STD - 592 =16*37.00 D China - 590 =16.36.875 B Australia - 543.2=16*33.95 L' STD - 171.2=16*10.70 FM Radio (at set_radio_freq) - */ +static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe, + enum param_type desired_type) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + struct tunertype *tun = priv->tun; + int i; - if (params->std == V4L2_STD_NTSC_M_JP) { - IFPCoff = 940; - desired_type = TUNER_PARAM_TYPE_NTSC; - } else if ((params->std & V4L2_STD_MN) && - !(params->std & ~V4L2_STD_MN)) { - IFPCoff = 732; - desired_type = TUNER_PARAM_TYPE_NTSC; - } else if (params->std == V4L2_STD_SECAM_LC) { - IFPCoff = 543; - desired_type = TUNER_PARAM_TYPE_SECAM; - } else { - IFPCoff = 623; - desired_type = TUNER_PARAM_TYPE_PAL; - } + for (i = 0; i < tun->count; i++) + if (desired_type == tun->params[i].type) + break; - for (j = 0; j < tun->count-1; j++) { - if (desired_type != tun->params[j].type) - continue; - break; + /* use default tuner params if desired_type not available */ + if (i == tun->count) { + tuner_dbg("desired params (%s) undefined for tuner %d\n", + tuner_param_name(desired_type), priv->type); + i = 0; } - /* use default tuner_t_params if desired_type not available */ - if (desired_type != tun->params[j].type) { - tuner_dbg("IFPCoff = %d: tuner_t_params undefined for tuner %d\n", - IFPCoff, priv->type); - j = 0; - } - t_params = &tun->params[j]; + + tuner_dbg("using tuner params #%d (%s)\n", i, + tuner_param_name(tun->params[i].type)); + + return &tun->params[i]; +} + +static int simple_config_lookup(struct dvb_frontend *fe, + struct tuner_params *t_params, + int *frequency, u8 *config, u8 *cb) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + int i; for (i = 0; i < t_params->count; i++) { - if (params->frequency > t_params->ranges[i].limit) + if (*frequency > t_params->ranges[i].limit) continue; break; } if (i == t_params->count) { - tuner_dbg("TV frequency out of range (%d > %d)", - params->frequency, t_params->ranges[i - 1].limit); - params->frequency = t_params->ranges[--i].limit; + tuner_dbg("frequency out of range (%d > %d)\n", + *frequency, t_params->ranges[i - 1].limit); + *frequency = t_params->ranges[--i].limit; } - config = t_params->ranges[i].config; - cb = t_params->ranges[i].cb; - /* i == 0 -> VHF_LO - * i == 1 -> VHF_HI - * i == 2 -> UHF */ - tuner_dbg("tv: param %d, range %d\n",j,i); + *config = t_params->ranges[i].config; + *cb = t_params->ranges[i].cb; - div=params->frequency + IFPCoff + offset; + tuner_dbg("freq = %d.%02d (%d), range = %d, " + "config = 0x%02x, cb = 0x%02x\n", + *frequency / 16, *frequency % 16 * 100 / 16, *frequency, + i, *config, *cb); - tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n", - params->frequency / 16, params->frequency % 16 * 100 / 16, - IFPCoff / 16, IFPCoff % 16 * 100 / 16, - offset / 16, offset % 16 * 100 / 16, - div); + return i; +} + +/* ---------------------------------------------------------------------- */ + +static int simple_std_setup(struct dvb_frontend *fe, + struct analog_parameters *params, + u8 *config, u8 *cb) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + u8 tuneraddr; + int rc; /* tv norm specific stuff for multi-norm tuners */ switch (priv->type) { - case TUNER_PHILIPS_SECAM: // FI1216MF + case TUNER_PHILIPS_SECAM: /* FI1216MF */ /* 0x01 -> ??? no change ??? */ /* 0x02 -> PAL BDGHI / SECAM L */ /* 0x04 -> ??? PAL others / SECAM others ??? */ - cb &= ~0x03; - if (params->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM - cb |= PHILIPS_MF_SET_STD_L; + *cb &= ~0x03; + if (params->std & V4L2_STD_SECAM_L) + /* also valid for V4L2_STD_SECAM */ + *cb |= PHILIPS_MF_SET_STD_L; else if (params->std & V4L2_STD_SECAM_LC) - cb |= PHILIPS_MF_SET_STD_LC; + *cb |= PHILIPS_MF_SET_STD_LC; else /* V4L2_STD_B|V4L2_STD_GH */ - cb |= PHILIPS_MF_SET_STD_BG; + *cb |= PHILIPS_MF_SET_STD_BG; break; case TUNER_TEMIC_4046FM5: - cb &= ~0x0f; + *cb &= ~0x0f; if (params->std & V4L2_STD_PAL_BG) { - cb |= TEMIC_SET_PAL_BG; + *cb |= TEMIC_SET_PAL_BG; } else if (params->std & V4L2_STD_PAL_I) { - cb |= TEMIC_SET_PAL_I; + *cb |= TEMIC_SET_PAL_I; } else if (params->std & V4L2_STD_PAL_DK) { - cb |= TEMIC_SET_PAL_DK; + *cb |= TEMIC_SET_PAL_DK; } else if (params->std & V4L2_STD_SECAM_L) { - cb |= TEMIC_SET_PAL_L; + *cb |= TEMIC_SET_PAL_L; } break; case TUNER_PHILIPS_FQ1216ME: - cb &= ~0x0f; + *cb &= ~0x0f; if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { - cb |= PHILIPS_SET_PAL_BGDK; + *cb |= PHILIPS_SET_PAL_BGDK; } else if (params->std & V4L2_STD_PAL_I) { - cb |= PHILIPS_SET_PAL_I; + *cb |= PHILIPS_SET_PAL_I; } else if (params->std & V4L2_STD_SECAM_L) { - cb |= PHILIPS_SET_PAL_L; + *cb |= PHILIPS_SET_PAL_L; } break; @@ -305,42 +311,204 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, /* 0x01 -> ATSC antenna input 2 */ /* 0x02 -> NTSC antenna input 1 */ /* 0x03 -> NTSC antenna input 2 */ - cb &= ~0x03; + *cb &= ~0x03; if (!(params->std & V4L2_STD_ATSC)) - cb |= 2; + *cb |= 2; /* FIXME: input */ break; case TUNER_MICROTUNE_4042FI5: /* Set the charge pump for fast tuning */ - config |= TUNER_CHARGE_PUMP; + *config |= TUNER_CHARGE_PUMP; break; case TUNER_PHILIPS_TUV1236D: + { /* 0x40 -> ATSC antenna input 1 */ /* 0x48 -> ATSC antenna input 2 */ /* 0x00 -> NTSC antenna input 1 */ /* 0x08 -> NTSC antenna input 2 */ - buffer[0] = 0x14; - buffer[1] = 0x00; - buffer[2] = 0x17; - buffer[3] = 0x00; - cb &= ~0x40; + u8 buffer[4] = { 0x14, 0x00, 0x17, 0x00}; + *cb &= ~0x40; if (params->std & V4L2_STD_ATSC) { - cb |= 0x40; + *cb |= 0x40; buffer[1] = 0x04; } /* set to the correct mode (analog or digital) */ tuneraddr = priv->i2c_props.addr; priv->i2c_props.addr = 0x0a; - if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[0],2))) - tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); - if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[2],2))) - tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); + rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2); + if (2 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 2)\n", rc); + rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2); + if (2 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 2)\n", rc); priv->i2c_props.addr = tuneraddr; /* FIXME: input */ break; } + } + + return 0; +} + +static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer, + u16 div, u8 config, u8 cb) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + int rc; + + switch (priv->type) { + case TUNER_LG_TDVS_H06XF: + /* Set the Auxiliary Byte. */ + buffer[0] = buffer[2]; + buffer[0] &= ~0x20; + buffer[0] |= 0x18; + buffer[1] = 0x20; + tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]); + + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2); + if (2 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 2)\n", rc); + break; + case TUNER_MICROTUNE_4042FI5: + { + /* FIXME - this may also work for other tuners */ + unsigned long timeout = jiffies + msecs_to_jiffies(1); + u8 status_byte = 0; + + /* Wait until the PLL locks */ + for (;;) { + if (time_after(jiffies, timeout)) + return 0; + rc = tuner_i2c_xfer_recv(&priv->i2c_props, + &status_byte, 1); + if (1 != rc) { + tuner_warn("i2c i/o read error: rc == %d " + "(should be 1)\n", rc); + break; + } + if (status_byte & TUNER_PLL_LOCKED) + break; + udelay(10); + } + + /* Set the charge pump for optimized phase noise figure */ + config &= ~TUNER_CHARGE_PUMP; + buffer[0] = (div>>8) & 0x7f; + buffer[1] = div & 0xff; + buffer[2] = config; + buffer[3] = cb; + tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", + buffer[0], buffer[1], buffer[2], buffer[3]); + + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); + if (4 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 4)\n", rc); + break; + } + } + + return 0; +} + +static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + + switch (priv->type) { + case TUNER_TENA_9533_DI: + case TUNER_YMEC_TVF_5533MF: + tuner_dbg("This tuner doesn't have FM. " + "Most cards have a TEA5767 for FM\n"); + return 0; + case TUNER_PHILIPS_FM1216ME_MK3: + case TUNER_PHILIPS_FM1236_MK3: + case TUNER_PHILIPS_FMD1216ME_MK3: + case TUNER_LG_NTSC_TAPE: + case TUNER_PHILIPS_FM1256_IH3: + buffer[3] = 0x19; + break; + case TUNER_TNF_5335MF: + buffer[3] = 0x11; + break; + case TUNER_LG_PAL_FM: + buffer[3] = 0xa5; + break; + case TUNER_THOMSON_DTT761X: + buffer[3] = 0x39; + break; + case TUNER_MICROTUNE_4049FM5: + default: + buffer[3] = 0xa4; + break; + } + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static int simple_set_tv_freq(struct dvb_frontend *fe, + struct analog_parameters *params) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + u8 config, cb; + u16 div; + struct tunertype *tun; + u8 buffer[4]; + int rc, IFPCoff, i; + enum param_type desired_type; + struct tuner_params *t_params; + + tun = priv->tun; + + /* IFPCoff = Video Intermediate Frequency - Vif: + 940 =16*58.75 NTSC/J (Japan) + 732 =16*45.75 M/N STD + 704 =16*44 ATSC (at DVB code) + 632 =16*39.50 I U.K. + 622.4=16*38.90 B/G D/K I, L STD + 592 =16*37.00 D China + 590 =16.36.875 B Australia + 543.2=16*33.95 L' STD + 171.2=16*10.70 FM Radio (at set_radio_freq) + */ + + if (params->std == V4L2_STD_NTSC_M_JP) { + IFPCoff = 940; + desired_type = TUNER_PARAM_TYPE_NTSC; + } else if ((params->std & V4L2_STD_MN) && + !(params->std & ~V4L2_STD_MN)) { + IFPCoff = 732; + desired_type = TUNER_PARAM_TYPE_NTSC; + } else if (params->std == V4L2_STD_SECAM_LC) { + IFPCoff = 543; + desired_type = TUNER_PARAM_TYPE_SECAM; + } else { + IFPCoff = 623; + desired_type = TUNER_PARAM_TYPE_PAL; + } + + t_params = simple_tuner_params(fe, desired_type); + + i = simple_config_lookup(fe, t_params, ¶ms->frequency, + &config, &cb); + + div = params->frequency + IFPCoff + offset; + + tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, " + "Offset=%d.%02d MHz, div=%0d\n", + params->frequency / 16, params->frequency % 16 * 100 / 16, + IFPCoff / 16, IFPCoff % 16 * 100 / 16, + offset / 16, offset % 16 * 100 / 16, div); + + /* tv norm specific stuff for multi-norm tuners */ + simple_std_setup(fe, params, &config, &cb); if (t_params->cb_first_if_lower_freq && div < priv->last_div) { buffer[0] = config; @@ -357,8 +525,10 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, if (t_params->has_tda9887) { struct v4l2_priv_tun_config tda9887_cfg; int config = 0; - int is_secam_l = (params->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) && - !(params->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)); + int is_secam_l = (params->std & (V4L2_STD_SECAM_L | + V4L2_STD_SECAM_LC)) && + !(params->std & ~(V4L2_STD_SECAM_L | + V4L2_STD_SECAM_LC)); tda9887_cfg.tuner = TUNER_TDA9887; tda9887_cfg.priv = &config; @@ -368,8 +538,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, config |= TDA9887_PORT1_ACTIVE; if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc) config |= TDA9887_PORT2_ACTIVE; - } - else { + } else { if (t_params->port1_active) config |= TDA9887_PORT1_ACTIVE; if (t_params->port2_active) @@ -384,8 +553,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, config |= TDA9887_TOP(t_params->default_top_secam_mid); else if (t_params->default_top_secam_high) config |= TDA9887_TOP(t_params->default_top_secam_high); - } - else { + } else { if (i == 0 && t_params->default_top_low) config |= TDA9887_TOP(t_params->default_top_low); else if (i == 1 && t_params->default_top_mid) @@ -399,56 +567,14 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, &tda9887_cfg); } tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0],buffer[1],buffer[2],buffer[3]); + buffer[0], buffer[1], buffer[2], buffer[3]); - if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) - tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); + if (4 != rc) + tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc); - switch (priv->type) { - case TUNER_LG_TDVS_H06XF: - /* Set the Auxiliary Byte. */ - buffer[0] = buffer[2]; - buffer[0] &= ~0x20; - buffer[0] |= 0x18; - buffer[1] = 0x20; - tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]); + simple_post_tune(fe, &buffer[0], div, config, cb); - if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,2))) - tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); - break; - case TUNER_MICROTUNE_4042FI5: - { - // FIXME - this may also work for other tuners - unsigned long timeout = jiffies + msecs_to_jiffies(1); - u8 status_byte = 0; - - /* Wait until the PLL locks */ - for (;;) { - if (time_after(jiffies,timeout)) - return 0; - if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,&status_byte,1))) { - tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc); - break; - } - if (status_byte & TUNER_PLL_LOCKED) - break; - udelay(10); - } - - /* Set the charge pump for optimized phase noise figure */ - config &= ~TUNER_CHARGE_PUMP; - buffer[0] = (div>>8) & 0x7f; - buffer[1] = div & 0xff; - buffer[2] = config; - buffer[3] = cb; - tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0],buffer[1],buffer[2],buffer[3]); - - if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) - tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); - break; - } - } return 0; } @@ -483,37 +609,13 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, freq += (unsigned int)(41.3*16000); break; default: - tuner_warn("Unsupported radio_if value %d\n", t_params->radio_if); + tuner_warn("Unsupported radio_if value %d\n", + t_params->radio_if); return 0; } /* Bandswitch byte */ - switch (priv->type) { - case TUNER_TENA_9533_DI: - case TUNER_YMEC_TVF_5533MF: - tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n"); - return 0; - case TUNER_PHILIPS_FM1216ME_MK3: - case TUNER_PHILIPS_FM1236_MK3: - case TUNER_PHILIPS_FMD1216ME_MK3: - case TUNER_LG_NTSC_TAPE: - case TUNER_PHILIPS_FM1256_IH3: - buffer[3] = 0x19; - break; - case TUNER_TNF_5335MF: - buffer[3] = 0x11; - break; - case TUNER_LG_PAL_FM: - buffer[3] = 0xa5; - break; - case TUNER_THOMSON_DTT761X: - buffer[3] = 0x39; - break; - case TUNER_MICROTUNE_4049FM5: - default: - buffer[3] = 0xa4; - break; - } + simple_radio_bandswitch(fe, &buffer[0]); buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ @@ -534,7 +636,7 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, } tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0],buffer[1],buffer[2],buffer[3]); + buffer[0], buffer[1], buffer[2], buffer[3]); priv->last_div = div; if (t_params->has_tda9887) { @@ -544,9 +646,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, tda9887_cfg.tuner = TUNER_TDA9887; tda9887_cfg.priv = &config; - if (t_params->port1_active && !t_params->port1_fm_high_sensitivity) + if (t_params->port1_active && + !t_params->port1_fm_high_sensitivity) config |= TDA9887_PORT1_ACTIVE; - if (t_params->port2_active && !t_params->port2_fm_high_sensitivity) + if (t_params->port2_active && + !t_params->port2_fm_high_sensitivity) config |= TDA9887_PORT2_ACTIVE; if (t_params->intercarrier_mode) config |= TDA9887_INTERCARRIER; @@ -557,10 +661,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, if (t_params->radio_if == 2) config |= TDA9887_RIF_41_3; i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG, - &tda9887_cfg); + &tda9887_cfg); } - if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) - tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); + if (4 != rc) + tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc); return 0; } @@ -613,10 +718,16 @@ static struct dvb_tuner_ops simple_tuner_ops = { struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c_adap, u8 i2c_addr, - struct simple_tuner_config *cfg) + unsigned int type) { struct tuner_simple_priv *priv = NULL; + if (type >= tuner_count) { + printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n", + __FUNCTION__, type, tuner_count-1); + return NULL; + } + priv = kzalloc(sizeof(struct tuner_simple_priv), GFP_KERNEL); if (priv == NULL) return NULL; @@ -624,19 +735,21 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; - priv->type = cfg->type; - priv->tun = cfg->tun; + priv->i2c_props.name = "tuner-simple"; + + priv->type = type; + priv->tun = &tuners[type]; - memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops)); + memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, + sizeof(struct dvb_tuner_ops)); - tuner_info("type set to %d (%s)\n", cfg->type, cfg->tun->name); + tuner_info("type set to %d (%s)\n", priv->type, priv->tun->name); - strlcpy(fe->ops.tuner_ops.info.name, cfg->tun->name, sizeof(fe->ops.tuner_ops.info.name)); + strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name, + sizeof(fe->ops.tuner_ops.info.name)); return fe; } - - EXPORT_SYMBOL_GPL(simple_tuner_attach); MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver"); diff --git a/drivers/media/video/tuner-simple.h b/drivers/media/video/tuner-simple.h index 9089939..bf425f3 100644 --- a/drivers/media/video/tuner-simple.h +++ b/drivers/media/video/tuner-simple.h @@ -20,23 +20,16 @@ #include #include "dvb_frontend.h" -struct simple_tuner_config -{ - /* chip type */ - unsigned int type; - struct tunertype *tun; -}; - #if defined(CONFIG_TUNER_SIMPLE) || (defined(CONFIG_TUNER_SIMPLE_MODULE) && defined(MODULE)) extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c_adap, u8 i2c_addr, - struct simple_tuner_config *cfg); + unsigned int type); #else static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c_adap, u8 i2c_addr, - struct simple_tuner_config *cfg) + unsigned int type) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); return NULL; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 883047f..9276ad3 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -1480,5 +1480,11 @@ struct tunertype tuners[] = { /* see xc5000.c for details */ }, }; +EXPORT_SYMBOL(tuners); unsigned const int tuner_count = ARRAY_SIZE(tuners); +EXPORT_SYMBOL(tuner_count); + +MODULE_DESCRIPTION("Simple tuner device type database"); +MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 50cf876..a9caae1 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -23,8 +23,6 @@ #include "dvb_frontend.h" -#define PREFIX "xc2028" - static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); @@ -145,7 +143,7 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val) } #define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0) -void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq) +static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq) { if (type & BASE) printk("BASE "); @@ -906,9 +904,11 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, if (rc < 0) goto ret; - rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); - if (rc < 0) - goto ret; + /* Return code shouldn't be checked. + The reset CLK is needed only with tm6000. + Driver should work fine even if this fails. + */ + priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); msleep(10); @@ -1153,13 +1153,13 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, void *video_dev; if (debug) - printk(KERN_DEBUG PREFIX ": Xcv2028/3028 init called!\n"); + printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n"); if (NULL == cfg || NULL == cfg->video_dev) return NULL; if (!fe) { - printk(KERN_ERR PREFIX ": No frontend!\n"); + printk(KERN_ERR "xc2028: No frontend!\n"); return NULL; } @@ -1183,6 +1183,8 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, priv->i2c_props.addr = cfg->i2c_addr; priv->i2c_props.adap = cfg->i2c_adap; + priv->i2c_props.name = "xc2028"; + priv->video_dev = video_dev; priv->tuner_callback = cfg->callback; priv->ctrl.max_len = 13; diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 01ebcec..f29a2cd 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -38,7 +38,7 @@ /* ---------------------------------------------------------------------- */ /* insmod args */ -static int debug = 0; /* insmod parameter */ +static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips"); @@ -1235,11 +1235,11 @@ static int tda9850 = 1; static int tda9855 = 1; static int tda9873 = 1; static int tda9874a = 1; -static int tea6300 = 0; /* address clash with msp34xx */ -static int tea6320 = 0; /* address clash with msp34xx */ +static int tea6300; /* default 0 - address clash with msp34xx */ +static int tea6320; /* default 0 - address clash with msp34xx */ static int tea6420 = 1; static int pic16c54 = 1; -static int ta8874z = 0; /* address clash with tda9840 */ +static int ta8874z; /* default 0 - address clash with tda9840 */ module_param(tda8425, int, 0444); module_param(tda9840, int, 0444); diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index dc0da44..3cf8a8e 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -745,109 +745,6 @@ int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len) } EXPORT_SYMBOL(tveeprom_read); -/* ----------------------------------------------------------------------- */ -/* needed for ivtv.sf.net at the moment. Should go away in the long */ -/* run, just call the exported tveeprom_* directly, there is no point in */ -/* using the indirect way via i2c_driver->command() */ - -static unsigned short normal_i2c[] = { - 0xa0 >> 1, - I2C_CLIENT_END, -}; - -I2C_CLIENT_INSMOD; - -static struct i2c_driver i2c_driver_tveeprom; - -static int -tveeprom_command(struct i2c_client *client, - unsigned int cmd, - void *arg) -{ - struct tveeprom eeprom; - u32 *eeprom_props = arg; - u8 *buf; - - switch (cmd) { - case 0: - buf = kzalloc(256, GFP_KERNEL); - tveeprom_read(client, buf, 256); - tveeprom_hauppauge_analog(client, &eeprom, buf); - kfree(buf); - eeprom_props[0] = eeprom.tuner_type; - eeprom_props[1] = eeprom.tuner_formats; - eeprom_props[2] = eeprom.model; - eeprom_props[3] = eeprom.revision; - eeprom_props[4] = eeprom.has_radio; - break; - default: - return -EINVAL; - } - return 0; -} - -static int -tveeprom_detect_client(struct i2c_adapter *adapter, - int address, - int kind) -{ - struct i2c_client *client; - - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (NULL == client) - return -ENOMEM; - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver_tveeprom; - snprintf(client->name, sizeof(client->name), "tveeprom"); - i2c_attach_client(client); - - return 0; -} - -static int -tveeprom_attach_adapter(struct i2c_adapter *adapter) -{ - if (adapter->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adapter, &addr_data, tveeprom_detect_client); - return 0; -} - -static int -tveeprom_detach_client(struct i2c_client *client) -{ - int err; - - err = i2c_detach_client(client); - if (err < 0) - return err; - kfree(client); - return 0; -} - -static struct i2c_driver i2c_driver_tveeprom = { - .driver = { - .name = "tveeprom", - }, - .id = I2C_DRIVERID_TVEEPROM, - .attach_adapter = tveeprom_attach_adapter, - .detach_client = tveeprom_detach_client, - .command = tveeprom_command, -}; - -static int __init tveeprom_init(void) -{ - return i2c_add_driver(&i2c_driver_tveeprom); -} - -static void __exit tveeprom_exit(void) -{ - i2c_del_driver(&i2c_driver_tveeprom); -} - -module_init(tveeprom_init); -module_exit(tveeprom_exit); - /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 445eba4..d0bdf7d 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -27,7 +27,7 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_INSMOD; -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c index 14db95e..84ee6b1 100644 --- a/drivers/media/video/usbvideo/ibmcam.c +++ b/drivers/media/video/usbvideo/ibmcam.c @@ -121,7 +121,7 @@ static int init_model2_yb = -1; /* 01.01.08 - Added for RCA video in support -LO */ /* Settings for camera model 3 */ -static int init_model3_input = 0; +static int init_model3_input; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index 719b17c..9747960 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c @@ -61,7 +61,7 @@ static int debug; } #else #define DEBUG(n, arg...) -static const int debug = 0; +static const int debug; #endif diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index a2acba0..e0ee6d8 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c @@ -50,7 +50,7 @@ static int debug; } #else #define DEBUG(n, arg...) -static const int debug = 0; +static const int debug; #endif #define DRIVER_VERSION "v0.01" diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c index 95453c1..9544e64 100644 --- a/drivers/media/video/usbvideo/ultracam.c +++ b/drivers/media/video/usbvideo/ultracam.c @@ -28,9 +28,9 @@ typedef struct { static struct usbvideo *cams = NULL; -static int debug = 0; +static int debug; -static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ +static int flags; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ static const int min_canvasWidth = 8; static const int min_canvasHeight = 4; diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index fb434b5..537bead 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -522,7 +522,7 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) struct usbvideo_frame *frame; int num_cell = 0; int scan_length = 0; - static int num_pass = 0; + static int num_pass; if (uvd == NULL) { err("%s: uvd == NULL", __FUNCTION__); diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 56775ab..47f64a0 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -53,19 +53,21 @@ #include "usbvision.h" -static unsigned int core_debug = 0; +static unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); -static unsigned int force_testpattern = 0; +static unsigned int force_testpattern; module_param(force_testpattern,int,0644); MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]"); -static int adjustCompression = 1; // Set the compression to be adaptive +static int adjustCompression = 1; /* Set the compression to be adaptive */ module_param(adjustCompression, int, 0444); MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device. Default: 1 (On)"); -static int SwitchSVideoInput = 0; // To help people with Black and White output with using s-video input. Some cables and input device are wired differently. +/* To help people with Black and White output with using s-video input. + * Some cables and input device are wired differently. */ +static int SwitchSVideoInput; module_param(SwitchSVideoInput, int, 0444); MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)"); @@ -418,7 +420,7 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision, unsigned char *f; int num_cell = 0; int scan_length = 0; - static int num_pass = 0; + static int num_pass; if (usbvision == NULL) { printk(KERN_ERR "%s: usbvision == NULL\n", proc); @@ -1430,7 +1432,7 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, } #if ENABLE_HEXDUMP if (totlen > 0) { - static int foo = 0; + static int foo; if (foo < 1) { printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen); usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen); diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index aabc42c..a7ed6f2 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -40,7 +40,7 @@ #define DBG_I2C 1<<0 -static int i2c_debug = 0; +static int i2c_debug; module_param (i2c_debug, int, 0644); // debug_i2c_usb mode of the device driver MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index df52f8a..2c2e106 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -115,7 +115,7 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL) /* sequential number of usbvision device */ -static int usbvision_nr = 0; +static int usbvision_nr; static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { { 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" }, @@ -135,7 +135,7 @@ static void usbvision_release(struct usb_usbvision *usbvision); /* Set the default format for ISOC endpoint */ static int isocMode = ISOC_MODE_COMPRESS; /* Set the default Debug Mode of the device driver */ -static int video_debug = 0; +static int video_debug; /* Set the default device to power on at startup */ static int PowerOnAtOpen = 1; /* Sequential Number of Video Device */ diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index dcf22a3..ac76e3e 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -39,7 +39,7 @@ #include #endif -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages"); MODULE_AUTHOR("Bill Dirks"); @@ -126,7 +126,7 @@ set_v4l_control(struct inode *inode, /* ----------------------------------------------------------------- */ -const static unsigned int palette2pixelformat[] = { +static const unsigned int palette2pixelformat[] = { [VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY, [VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555, [VIDEO_PALETTE_RGB565] = V4L2_PIX_FMT_RGB565, diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 53fed4b..6141a13 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -1,5 +1,5 @@ /* - * helper functions for PCI DMA video4linux capture buffers + * helper functions for SG DMA video4linux capture buffers * * The functions expect the hardware being able to scatter gatter * (i.e. the buffers are not linear in physical memory, but fragmented @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -39,10 +39,10 @@ #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } -static int debug = 0; +static int debug; module_param(debug, int, 0644); -MODULE_DESCRIPTION("helper module to manage video4linux pci dma sg buffers"); +MODULE_DESCRIPTION("helper module to manage video4linux dma sg buffers"); MODULE_AUTHOR("Mauro Carvalho Chehab "); MODULE_LICENSE("GPL"); @@ -119,10 +119,10 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf) { - struct videbuf_pci_sg_memory *mem=buf->priv; - BUG_ON (!mem); + struct videobuf_dma_sg_memory *mem = buf->priv; + BUG_ON(!mem); - MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); return &mem->dma; } @@ -141,9 +141,14 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, dma->direction = direction; switch (dma->direction) { - case PCI_DMA_FROMDEVICE: rw = READ; break; - case PCI_DMA_TODEVICE: rw = WRITE; break; - default: BUG(); + case DMA_FROM_DEVICE: + rw = READ; + break; + case DMA_TO_DEVICE: + rw = WRITE; + break; + default: + BUG(); } first = (data & PAGE_MASK) >> PAGE_SHIFT; @@ -216,10 +221,8 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, return 0; } -int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) +int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma) { - void *dev=q->dev; - MAGIC_CHECK(dma->magic,MAGIC_DMABUF); BUG_ON(0 == dma->nr_pages); @@ -245,7 +248,7 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) return -ENOMEM; } if (!dma->bus_addr) { - dma->sglen = pci_map_sg(dev,dma->sglist, + dma->sglen = dma_map_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction); if (0 == dma->sglen) { printk(KERN_WARNING @@ -259,14 +262,12 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) return 0; } -int videobuf_dma_sync(struct videobuf_queue *q,struct videobuf_dmabuf *dma) +int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma) { - void *dev=q->dev; - - MAGIC_CHECK(dma->magic,MAGIC_DMABUF); + MAGIC_CHECK(dma->magic, MAGIC_DMABUF); BUG_ON(!dma->sglen); - pci_dma_sync_sg_for_cpu (dev,dma->sglist,dma->nr_pages,dma->direction); + dma_sync_sg_for_cpu(q->dev, dma->sglist, dma->nr_pages, dma->direction); return 0; } @@ -274,11 +275,11 @@ int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) { void *dev=q->dev; - MAGIC_CHECK(dma->magic,MAGIC_DMABUF); + MAGIC_CHECK(dma->magic, MAGIC_DMABUF); if (!dma->sglen) return 0; - pci_unmap_sg (dev,dma->sglist,dma->nr_pages,dma->direction); + dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction); kfree(dma->sglist); dma->sglist = NULL; @@ -306,28 +307,28 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma) if (dma->bus_addr) { dma->bus_addr = 0; } - dma->direction = PCI_DMA_NONE; + dma->direction = DMA_NONE; return 0; } /* --------------------------------------------------------------------- */ -int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma) +int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma) { struct videobuf_queue q; - q.dev=pci; + q.dev = dev; - return (videobuf_dma_map(&q,dma)); + return videobuf_dma_map(&q, dma); } -int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma) +int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma) { struct videobuf_queue q; - q.dev=pci; + q.dev = dev; - return (videobuf_dma_unmap(&q,dma)); + return videobuf_dma_unmap(&q, dma); } /* --------------------------------------------------------------------- */ @@ -347,7 +348,7 @@ videobuf_vm_close(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; struct videobuf_queue *q = map->q; - struct videbuf_pci_sg_memory *mem; + struct videobuf_dma_sg_memory *mem; int i; dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map, @@ -409,18 +410,18 @@ static struct vm_operations_struct videobuf_vm_ops = }; /* --------------------------------------------------------------------- - * PCI handlers for the generic methods + * SG handlers for the generic methods */ /* Allocated area consists on 3 parts: struct video_buffer struct _buffer (cx88_buffer, saa7134_buf, ...) - struct videobuf_pci_sg_memory + struct videobuf_dma_sg_memory */ static void *__videobuf_alloc(size_t size) { - struct videbuf_pci_sg_memory *mem; + struct videobuf_dma_sg_memory *mem; struct videobuf_buffer *vb; vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); @@ -443,10 +444,10 @@ static int __videobuf_iolock (struct videobuf_queue* q, { int err,pages; dma_addr_t bus; - struct videbuf_pci_sg_memory *mem=vb->priv; + struct videobuf_dma_sg_memory *mem = vb->priv; BUG_ON(!mem); - MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); switch (vb->memory) { case V4L2_MEMORY_MMAP: @@ -455,14 +456,14 @@ static int __videobuf_iolock (struct videobuf_queue* q, /* no userspace addr -- kernel bounce buffer */ pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; err = videobuf_dma_init_kernel( &mem->dma, - PCI_DMA_FROMDEVICE, + DMA_FROM_DEVICE, pages ); if (0 != err) return err; } else if (vb->memory == V4L2_MEMORY_USERPTR) { /* dma directly to userspace */ err = videobuf_dma_init_user( &mem->dma, - PCI_DMA_FROMDEVICE, + DMA_FROM_DEVICE, vb->baddr,vb->bsize ); if (0 != err) return err; @@ -473,7 +474,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, locking inversion, so don't take it here */ err = videobuf_dma_init_user_locked(&mem->dma, - PCI_DMA_FROMDEVICE, + DMA_FROM_DEVICE, vb->baddr, vb->bsize); if (0 != err) return err; @@ -490,7 +491,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, */ bus = (dma_addr_t)(unsigned long)fbuf->base + vb->boff; pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; - err = videobuf_dma_init_overlay(&mem->dma,PCI_DMA_FROMDEVICE, + err = videobuf_dma_init_overlay(&mem->dma, DMA_FROM_DEVICE, bus, pages); if (0 != err) return err; @@ -498,7 +499,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, default: BUG(); } - err = videobuf_dma_map(q,&mem->dma); + err = videobuf_dma_map(q, &mem->dma); if (0 != err) return err; @@ -508,8 +509,8 @@ static int __videobuf_iolock (struct videobuf_queue* q, static int __videobuf_sync(struct videobuf_queue *q, struct videobuf_buffer *buf) { - struct videbuf_pci_sg_memory *mem=buf->priv; - BUG_ON (!mem); + struct videobuf_dma_sg_memory *mem = buf->priv; + BUG_ON(!mem); MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); return videobuf_dma_sync(q,&mem->dma); @@ -532,7 +533,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) static int __videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) { - struct videbuf_pci_sg_memory *mem; + struct videobuf_dma_sg_memory *mem; struct videobuf_mapping *map; unsigned int first,last,size,i; int retval; @@ -552,7 +553,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, if (NULL == q->bufs[first]) continue; mem=q->bufs[first]->priv; - BUG_ON (!mem); + BUG_ON(!mem); MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) @@ -615,8 +616,8 @@ static int __videobuf_copy_to_user ( struct videobuf_queue *q, char __user *data, size_t count, int nonblocking ) { - struct videbuf_pci_sg_memory *mem=q->read_buf->priv; - BUG_ON (!mem); + struct videobuf_dma_sg_memory *mem = q->read_buf->priv; + BUG_ON(!mem); MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); /* copy to userspace */ @@ -634,8 +635,8 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q, int vbihack, int nonblocking ) { unsigned int *fc; - struct videbuf_pci_sg_memory *mem=q->read_buf->priv; - BUG_ON (!mem); + struct videobuf_dma_sg_memory *mem = q->read_buf->priv; + BUG_ON(!mem); MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); if (vbihack) { @@ -658,7 +659,7 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q, return count; } -static struct videobuf_qtype_ops pci_ops = { +static struct videobuf_qtype_ops sg_ops = { .magic = MAGIC_QTYPE_OPS, .alloc = __videobuf_alloc, @@ -670,21 +671,21 @@ static struct videobuf_qtype_ops pci_ops = { .copy_stream = __videobuf_copy_stream, }; -void *videobuf_pci_alloc (size_t size) +void *videobuf_sg_alloc(size_t size) { struct videobuf_queue q; /* Required to make generic handler to call __videobuf_alloc */ - q.int_ops=&pci_ops; + q.int_ops = &sg_ops; - q.msize=size; + q.msize = size; - return videobuf_alloc (&q); + return videobuf_alloc(&q); } -void videobuf_queue_pci_init(struct videobuf_queue* q, +void videobuf_queue_sg_init(struct videobuf_queue* q, struct videobuf_queue_ops *ops, - void *dev, + struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, @@ -692,7 +693,7 @@ void videobuf_queue_pci_init(struct videobuf_queue* q, void *priv) { videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, - priv, &pci_ops); + priv, &sg_ops); } /* --------------------------------------------------------------------- */ @@ -709,11 +710,11 @@ EXPORT_SYMBOL_GPL(videobuf_dma_sync); EXPORT_SYMBOL_GPL(videobuf_dma_unmap); EXPORT_SYMBOL_GPL(videobuf_dma_free); -EXPORT_SYMBOL_GPL(videobuf_pci_dma_map); -EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap); -EXPORT_SYMBOL_GPL(videobuf_pci_alloc); +EXPORT_SYMBOL_GPL(videobuf_sg_dma_map); +EXPORT_SYMBOL_GPL(videobuf_sg_dma_unmap); +EXPORT_SYMBOL_GPL(videobuf_sg_alloc); -EXPORT_SYMBOL_GPL(videobuf_queue_pci_init); +EXPORT_SYMBOL_GPL(videobuf_queue_sg_init); /* * Local variables: diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index b73aba6..4ba8b7d 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c @@ -30,7 +30,7 @@ MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages"); diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 5266ecc..4a2508d 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -33,7 +33,7 @@ #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers"); @@ -102,7 +102,7 @@ static struct vm_operations_struct videobuf_vm_ops = /* Allocated area consists on 3 parts: struct video_buffer struct _buffer (cx88_buffer, saa7134_buf, ...) - struct videobuf_pci_sg_memory + struct videobuf_dma_sg_memory */ static void *__videobuf_alloc(size_t size) diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c index 87951ec..b30b6b2 100644 --- a/drivers/media/video/videocodec.c +++ b/drivers/media/video/videocodec.c @@ -44,7 +44,7 @@ #include "videocodec.h" -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-4)"); @@ -325,7 +325,7 @@ videocodec_unregister (const struct videocodec *codec) /* ============ */ static char *videocodec_buf = NULL; -static int videocodec_bufsize = 0; +static int videocodec_bufsize; static int videocodec_build_table (void) diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 5bb7529..d545c98 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -333,7 +333,7 @@ struct vino_settings { * * Use non-zero value to enable conversion. */ -static int vino_pixel_conversion = 0; +static int vino_pixel_conversion; module_param_named(pixelconv, vino_pixel_conversion, int, 0); @@ -4370,8 +4370,8 @@ static int vino_ioctl(struct inode *inode, struct file *file, /* Initialization and cleanup */ -// __initdata -static int vino_init_stage = 0; +/* __initdata */ +static int vino_init_stage; static const struct file_operations vino_fops = { .owner = THIS_MODULE, @@ -4385,8 +4385,8 @@ static const struct file_operations vino_fops = { static struct video_device v4l_device_template = { .name = "NOT SET", - //.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | - // VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY + /*.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | */ + /* VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY */ .fops = &vino_fops, .minor = -1, }; diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index a913385..3529302 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -40,7 +40,7 @@ #define I2C_VPX3220 0x86 #define VPX3220_DEBUG KERN_DEBUG "vpx3220: " -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 08aaae0..cc8c824 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -61,7 +61,7 @@ #include #include -//#define DEBUG // Undef me for production +/*#define DEBUG*/ /* Undef me for production */ #ifdef DEBUG #define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __FUNCTION__ , ##a) @@ -134,7 +134,7 @@ MODULE_PARM_DESC(pardev, "pardev: where to search for\n\ \tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n\ \tcam 1 to parport3 and search every parport for cam 2 etc..."); -static int parmode = 0; +static int parmode; module_param(parmode, int, 0); MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp"); diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index 2ae1430..cce23d2 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -3481,7 +3481,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) enum w9968cf_model_id mod_id; struct list_head* ptr; u8 sc = 0; /* number of simultaneous cameras */ - static unsigned short dev_nr = 0; /* we are handling device number n */ + static unsigned short dev_nr; /* 0 - we are handling device number n */ if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[0].idVendor && le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct) diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 2c5665c..af357cb 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -1939,7 +1939,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) { struct usb_device *udev = interface_to_usbdev(intf); struct zc0301_device* cam; - static unsigned int dev_nr = 0; + static unsigned int dev_nr; unsigned int i; int err = 0; diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index 690281b..006d488 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c @@ -83,7 +83,7 @@ MODULE_PARM_DESC(decoder, "i2c TV decoder"); or set in in a VIDIOCSFBUF ioctl */ -static unsigned long vidmem = 0; /* Video memory base address */ +static unsigned long vidmem; /* default = 0 - Video memory base address */ module_param(vidmem, ulong, 0444); MODULE_PARM_DESC(vidmem, "Default video memory base address"); @@ -91,7 +91,7 @@ MODULE_PARM_DESC(vidmem, "Default video memory base address"); Default input and video norm at startup of the driver. */ -static unsigned int default_input = 0; /* 0=Composite, 1=S-Video */ +static unsigned int default_input; /* default 0 = Composite, 1 = S-Video */ module_param(default_input, uint, 0444); MODULE_PARM_DESC(default_input, "Default input (0=Composite, 1=S-Video, 2=Internal)"); @@ -101,7 +101,7 @@ module_param(default_mux, int, 0644); MODULE_PARM_DESC(default_mux, "Default 6 Eyes mux setting (Input selection)"); -static int default_norm = 0; /* 0=PAL, 1=NTSC 2=SECAM */ +static int default_norm; /* default 0 = PAL, 1 = NTSC 2 = SECAM */ module_param(default_norm, int, 0444); MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)"); diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index f97c206..10686c6 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -60,7 +60,8 @@ extern const struct zoran_format zoran_formats[]; -static int lml33dpath = 0; /* 1 will use digital path in capture +static int lml33dpath; /* default = 0 + * 1 will use digital path in capture * mode instead of analog. It can be * used for picture adjustments using * tool like xawtv while watching image @@ -987,7 +988,7 @@ void zr36057_enable_jpg (struct zoran *zr, enum zoran_codec_mode mode) { - static int zero = 0; + static int zero; static int one = 1; struct vfe_settings cap; int field_size = diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index dd3d7d2..36e7300 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -205,7 +205,7 @@ extern int jpg_nbufs; extern int jpg_bufsize; extern int pass_through; -static int lock_norm = 0; /* 1=Don't change TV standard (norm) */ +static int lock_norm; /* 0 = default 1 = Don't change TV standard (norm) */ module_param(lock_norm, int, 0644); MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)"); diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c index dd08455..00d132b 100644 --- a/drivers/media/video/zr36016.c +++ b/drivers/media/video/zr36016.c @@ -55,11 +55,10 @@ #define MAX_CODECS 20 /* amount of chips attached via this driver */ -static int zr36016_codecs = 0; +static int zr36016_codecs; /* debugging is available via module parameter */ - -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-4)"); diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c index faae4ec..cf8b271 100644 --- a/drivers/media/video/zr36050.c +++ b/drivers/media/video/zr36050.c @@ -52,11 +52,10 @@ #define MAX_CODECS 20 /* amount of chips attached via this driver */ -static int zr36050_codecs = 0; +static int zr36050_codecs; /* debugging is available via module parameter */ - -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-4)"); diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c index 7849b65..8e74054 100644 --- a/drivers/media/video/zr36060.c +++ b/drivers/media/video/zr36060.c @@ -52,14 +52,14 @@ #define MAX_CODECS 20 /* amount of chips attached via this driver */ -static int zr36060_codecs = 0; +static int zr36060_codecs; -static int low_bitrate = 0; +static int low_bitrate; module_param(low_bitrate, bool, 0); MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate"); /* debugging is available via module parameter */ -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-4)"); diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 1b44784..1cd6390 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -62,8 +62,8 @@ /* Module parameters */ -static int debug = 0; -static int mode = 0; +static int debug; +static int mode; /* Module parameters interface */ diff --git a/include/asm-arm/arch-pxa/camera.h b/include/asm-arm/arch-pxa/camera.h new file mode 100644 index 0000000..39516ce --- /dev/null +++ b/include/asm-arm/arch-pxa/camera.h @@ -0,0 +1,48 @@ +/* + camera.h - PXA camera driver header file + + Copyright (C) 2003, Intel Corporation + Copyright (C) 2008, Guennadi Liakhovetski + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ASM_ARCH_CAMERA_H_ +#define __ASM_ARCH_CAMERA_H_ + +#define PXA_CAMERA_MASTER 1 +#define PXA_CAMERA_DATAWIDTH_4 2 +#define PXA_CAMERA_DATAWIDTH_5 4 +#define PXA_CAMERA_DATAWIDTH_8 8 +#define PXA_CAMERA_DATAWIDTH_9 0x10 +#define PXA_CAMERA_DATAWIDTH_10 0x20 +#define PXA_CAMERA_PCLK_EN 0x40 +#define PXA_CAMERA_MCLK_EN 0x80 +#define PXA_CAMERA_PCP 0x100 +#define PXA_CAMERA_HSP 0x200 +#define PXA_CAMERA_VSP 0x400 + +struct pxacamera_platform_data { + int (*init)(struct device *); + int (*power)(struct device *, int); + int (*reset)(struct device *, int); + + unsigned long flags; + unsigned long mclk_10khz; +}; + +extern void pxa_set_camera_info(struct pxacamera_platform_data *); + +#endif /* __ASM_ARCH_CAMERA_H_ */ diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index 2357a73..87bfd7f 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -46,13 +46,13 @@ #define PCMCIA1AttrSp PCMCIAAttrSp /* PCMCIA 1 Attribute Space [byte] */ #define PCMCIA1MemSp PCMCIAMemSp /* PCMCIA 1 Memory Space [byte] */ -#define _PCMCIA(Nb) /* PCMCIA [0..1] */ \ - (0x20000000 + (Nb)*PCMCIASp) +#define _PCMCIA(Nb) /* PCMCIA [0..1] */ \ + (0x20000000 + (Nb)*PCMCIASp) #define _PCMCIAIO(Nb) _PCMCIA (Nb) /* PCMCIA I/O [0..1] */ -#define _PCMCIAAttr(Nb) /* PCMCIA Attribute [0..1] */ \ - (_PCMCIA (Nb) + 2*PCMCIAPrtSp) -#define _PCMCIAMem(Nb) /* PCMCIA Memory [0..1] */ \ - (_PCMCIA (Nb) + 3*PCMCIAPrtSp) +#define _PCMCIAAttr(Nb) /* PCMCIA Attribute [0..1] */ \ + (_PCMCIA (Nb) + 2*PCMCIAPrtSp) +#define _PCMCIAMem(Nb) /* PCMCIA Memory [0..1] */ \ + (_PCMCIA (Nb) + 3*PCMCIAPrtSp) #define _PCMCIA0 _PCMCIA (0) /* PCMCIA 0 */ #define _PCMCIA0IO _PCMCIAIO (0) /* PCMCIA 0 I/O */ @@ -1248,19 +1248,26 @@ #define GPIO10_RTCCLK 10 /* real time clock (1 Hz) */ #define GPIO11_3_6MHz 11 /* 3.6 MHz oscillator out */ #define GPIO12_32KHz 12 /* 32 kHz out */ +#define GPIO12_CIF_DD7 12 /* Capture Interface D7 (PXA27x) */ #define GPIO13_MBGNT 13 /* memory controller grant */ #define GPIO14_MBREQ 14 /* alternate bus master request */ #define GPIO15_nCS_1 15 /* chip select 1 */ #define GPIO16_PWM0 16 /* PWM0 output */ #define GPIO17_PWM1 17 /* PWM1 output */ +#define GPIO17_CIF_DD6 17 /* Capture Interface D6 (PXA27x) */ #define GPIO18_RDY 18 /* Ext. Bus Ready */ #define GPIO19_DREQ1 19 /* External DMA Request */ #define GPIO20_DREQ0 20 /* External DMA Request */ #define GPIO23_SCLK 23 /* SSP clock */ +#define GPIO23_CIF_MCLK 23 /* Capture Interface MCLK (PXA27x) */ #define GPIO24_SFRM 24 /* SSP Frame */ +#define GPIO24_CIF_FV 24 /* Capture Interface FV (PXA27x) */ #define GPIO25_STXD 25 /* SSP transmit */ +#define GPIO25_CIF_LV 25 /* Capture Interface LV (PXA27x) */ #define GPIO26_SRXD 26 /* SSP receive */ +#define GPIO26_CIF_PCLK 26 /* Capture Interface PCLK (PXA27x) */ #define GPIO27_SEXTCLK 27 /* SSP ext_clk */ +#define GPIO27_CIF_DD0 27 /* Capture Interface D0 (PXA27x) */ #define GPIO28_BITCLK 28 /* AC97/I2S bit_clk */ #define GPIO29_SDATA_IN 29 /* AC97 Sdata_in0 / I2S Sdata_in */ #define GPIO30_SDATA_OUT 30 /* AC97/I2S Sdata_out */ @@ -1281,28 +1288,40 @@ #define GPIO41_FFRTS 41 /* FFUART request to send */ #define GPIO42_BTRXD 42 /* BTUART receive data */ #define GPIO42_HWRXD 42 /* HWUART receive data */ +#define GPIO42_CIF_MCLK 42 /* Capture interface MCLK (PXA27x) */ #define GPIO43_BTTXD 43 /* BTUART transmit data */ #define GPIO43_HWTXD 43 /* HWUART transmit data */ +#define GPIO43_CIF_FV 43 /* Capture interface FV (PXA27x) */ #define GPIO44_BTCTS 44 /* BTUART clear to send */ #define GPIO44_HWCTS 44 /* HWUART clear to send */ +#define GPIO44_CIF_LV 44 /* Capture interface LV (PXA27x) */ #define GPIO45_BTRTS 45 /* BTUART request to send */ #define GPIO45_HWRTS 45 /* HWUART request to send */ #define GPIO45_AC97_SYSCLK 45 /* AC97 System Clock */ +#define GPIO45_CIF_PCLK 45 /* Capture interface PCLK (PXA27x) */ #define GPIO46_ICPRXD 46 /* ICP receive data */ #define GPIO46_STRXD 46 /* STD_UART receive data */ #define GPIO47_ICPTXD 47 /* ICP transmit data */ #define GPIO47_STTXD 47 /* STD_UART transmit data */ +#define GPIO47_CIF_DD0 47 /* Capture interface D0 (PXA27x) */ #define GPIO48_nPOE 48 /* Output Enable for Card Space */ +#define GPIO48_CIF_DD5 48 /* Capture interface D5 (PXA27x) */ #define GPIO49_nPWE 49 /* Write Enable for Card Space */ #define GPIO50_nPIOR 50 /* I/O Read for Card Space */ +#define GPIO50_CIF_DD3 50 /* Capture interface D3 (PXA27x) */ #define GPIO51_nPIOW 51 /* I/O Write for Card Space */ +#define GPIO51_CIF_DD2 51 /* Capture interface D2 (PXA27x) */ #define GPIO52_nPCE_1 52 /* Card Enable for Card Space */ +#define GPIO52_CIF_DD4 52 /* Capture interface D4 (PXA27x) */ #define GPIO53_nPCE_2 53 /* Card Enable for Card Space */ #define GPIO53_MMCCLK 53 /* MMC Clock */ +#define GPIO53_CIF_MCLK 53 /* Capture interface MCLK (PXA27x) */ #define GPIO54_MMCCLK 54 /* MMC Clock */ #define GPIO54_pSKTSEL 54 /* Socket Select for Card Space */ #define GPIO54_nPCE_2 54 /* Card Enable for Card Space (PXA27x) */ +#define GPIO54_CIF_PCLK 54 /* Capture interface PCLK (PXA27x) */ #define GPIO55_nPREG 55 /* Card Address bit 26 */ +#define GPIO55_CIF_DD1 55 /* Capture interface D1 (PXA27x) */ #define GPIO56_nPWAIT 56 /* Wait signal for Card Space */ #define GPIO57_nIOIS16 57 /* Bus Width select for I/O Card Space */ #define GPIO58_LDD_0 58 /* LCD data pin 0 */ @@ -1337,11 +1356,28 @@ #define GPIO79_nCS_3 79 /* chip select 3 */ #define GPIO80_nCS_4 80 /* chip select 4 */ #define GPIO81_NSCLK 81 /* NSSP clock */ +#define GPIO81_CIF_DD0 81 /* Capture Interface D0 (PXA27x) */ #define GPIO82_NSFRM 82 /* NSSP Frame */ +#define GPIO82_CIF_DD5 82 /* Capture Interface D5 (PXA27x) */ #define GPIO83_NSTXD 83 /* NSSP transmit */ +#define GPIO83_CIF_DD4 83 /* Capture Interface D4 (PXA27x) */ #define GPIO84_NSRXD 84 /* NSSP receive */ +#define GPIO84_CIF_FV 84 /* Capture Interface FV (PXA27x) */ #define GPIO85_nPCE_1 85 /* Card Enable for Card Space (PXA27x) */ +#define GPIO85_CIF_LV 85 /* Capture Interface LV (PXA27x) */ +#define GPIO90_CIF_DD4 90 /* Capture Interface DD4 (PXA27x) */ +#define GPIO91_CIF_DD5 91 /* Capture Interface DD5 (PXA27x) */ #define GPIO92_MMCDAT0 92 /* MMC DAT0 (PXA27x) */ +#define GPIO93_CIF_DD6 93 /* Capture interface D6 (PXA27x) */ +#define GPIO94_CIF_DD5 94 /* Capture interface D5 (PXA27x) */ +#define GPIO95_CIF_DD4 95 /* Capture interface D4 (PXA27x) */ +#define GPIO98_CIF_DD0 98 /* Capture interface D0 (PXA27x) */ +#define GPIO103_CIF_DD3 103 /* Capture interface D3 (PXA27x) */ +#define GPIO104_CIF_DD2 104 /* Capture interface D2 (PXA27x) */ +#define GPIO105_CIF_DD1 105 /* Capture interface D1 (PXA27x) */ +#define GPIO106_CIF_DD9 106 /* Capture interface D9 (PXA27x) */ +#define GPIO107_CIF_DD8 107 /* Capture interface D8 (PXA27x) */ +#define GPIO108_CIF_DD7 108 /* Capture interface D7 (PXA27x) */ #define GPIO102_nPCE_1 102 /* PCMCIA (PXA27x) */ #define GPIO109_MMCDAT1 109 /* MMC DAT1 (PXA27x) */ #define GPIO110_MMCDAT2 110 /* MMC DAT2 (PXA27x) */ @@ -1351,6 +1387,9 @@ #define GPIO112_MMCCMD 112 /* MMC CMD (PXA27x) */ #define GPIO113_I2S_SYSCLK 113 /* I2S System Clock (PXA27x) */ #define GPIO113_AC97_RESET_N 113 /* AC97 NRESET on (PXA27x) */ +#define GPIO114_CIF_DD1 114 /* Capture interface D1 (PXA27x) */ +#define GPIO115_CIF_DD3 115 /* Capture interface D3 (PXA27x) */ +#define GPIO116_CIF_DD2 116 /* Capture interface D2 (PXA27x) */ /* GPIO alternate function mode & direction */ @@ -1376,19 +1415,26 @@ #define GPIO10_RTCCLK_MD (10 | GPIO_ALT_FN_1_OUT) #define GPIO11_3_6MHz_MD (11 | GPIO_ALT_FN_1_OUT) #define GPIO12_32KHz_MD (12 | GPIO_ALT_FN_1_OUT) +#define GPIO12_CIF_DD7_MD (12 | GPIO_ALT_FN_2_IN) #define GPIO13_MBGNT_MD (13 | GPIO_ALT_FN_2_OUT) #define GPIO14_MBREQ_MD (14 | GPIO_ALT_FN_1_IN) #define GPIO15_nCS_1_MD (15 | GPIO_ALT_FN_2_OUT) #define GPIO16_PWM0_MD (16 | GPIO_ALT_FN_2_OUT) #define GPIO17_PWM1_MD (17 | GPIO_ALT_FN_2_OUT) +#define GPIO17_CIF_DD6_MD (17 | GPIO_ALT_FN_2_IN) #define GPIO18_RDY_MD (18 | GPIO_ALT_FN_1_IN) #define GPIO19_DREQ1_MD (19 | GPIO_ALT_FN_1_IN) #define GPIO20_DREQ0_MD (20 | GPIO_ALT_FN_1_IN) +#define GPIO23_CIF_MCLK_MD (23 | GPIO_ALT_FN_1_OUT) #define GPIO23_SCLK_MD (23 | GPIO_ALT_FN_2_OUT) +#define GPIO24_CIF_FV_MD (24 | GPIO_ALT_FN_1_OUT) #define GPIO24_SFRM_MD (24 | GPIO_ALT_FN_2_OUT) +#define GPIO25_CIF_LV_MD (25 | GPIO_ALT_FN_1_OUT) #define GPIO25_STXD_MD (25 | GPIO_ALT_FN_2_OUT) #define GPIO26_SRXD_MD (26 | GPIO_ALT_FN_1_IN) +#define GPIO26_CIF_PCLK_MD (26 | GPIO_ALT_FN_2_IN) #define GPIO27_SEXTCLK_MD (27 | GPIO_ALT_FN_1_IN) +#define GPIO27_CIF_DD0_MD (27 | GPIO_ALT_FN_3_IN) #define GPIO28_BITCLK_AC97_MD (28 | GPIO_ALT_FN_1_IN) #define GPIO28_BITCLK_IN_I2S_MD (28 | GPIO_ALT_FN_2_IN) #define GPIO28_BITCLK_OUT_I2S_MD (28 | GPIO_ALT_FN_1_OUT) @@ -1413,34 +1459,46 @@ #define GPIO40_FFDTR_MD (40 | GPIO_ALT_FN_2_OUT) #define GPIO41_FFRTS_MD (41 | GPIO_ALT_FN_2_OUT) #define GPIO42_BTRXD_MD (42 | GPIO_ALT_FN_1_IN) +#define GPIO42_CIF_MCLK_MD (42 | GPIO_ALT_FN_3_OUT) #define GPIO42_HWRXD_MD (42 | GPIO_ALT_FN_3_IN) #define GPIO43_BTTXD_MD (43 | GPIO_ALT_FN_2_OUT) +#define GPIO43_CIF_FV_MD (43 | GPIO_ALT_FN_3_OUT) #define GPIO43_HWTXD_MD (43 | GPIO_ALT_FN_3_OUT) #define GPIO44_BTCTS_MD (44 | GPIO_ALT_FN_1_IN) #define GPIO44_HWCTS_MD (44 | GPIO_ALT_FN_3_IN) +#define GPIO44_CIF_LV_MD (44 | GPIO_ALT_FN_3_OUT) #define GPIO45_BTRTS_MD (45 | GPIO_ALT_FN_2_OUT) #define GPIO45_HWRTS_MD (45 | GPIO_ALT_FN_3_OUT) #define GPIO45_SYSCLK_AC97_MD (45 | GPIO_ALT_FN_1_OUT) +#define GPIO45_CIF_PCLK_MD (45 | GPIO_ALT_FN_3_IN) #define GPIO46_ICPRXD_MD (46 | GPIO_ALT_FN_1_IN) #define GPIO46_STRXD_MD (46 | GPIO_ALT_FN_2_IN) #define GPIO47_ICPTXD_MD (47 | GPIO_ALT_FN_2_OUT) #define GPIO47_STTXD_MD (47 | GPIO_ALT_FN_1_OUT) +#define GPIO47_CIF_DD0_MD (47 | GPIO_ALT_FN_1_IN) #define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT) +#define GPIO48_CIF_DD5_MD (48 | GPIO_ALT_FN_1_IN) #define GPIO48_HWTXD_MD (48 | GPIO_ALT_FN_1_OUT) #define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT) #define GPIO49_HWRXD_MD (49 | GPIO_ALT_FN_1_IN) #define GPIO49_nPWE_MD (49 | GPIO_ALT_FN_2_OUT) #define GPIO50_nPIOR_MD (50 | GPIO_ALT_FN_2_OUT) +#define GPIO50_CIF_DD3_MD (50 | GPIO_ALT_FN_1_IN) #define GPIO50_HWCTS_MD (50 | GPIO_ALT_FN_1_IN) #define GPIO51_HWRTS_MD (51 | GPIO_ALT_FN_1_OUT) #define GPIO51_nPIOW_MD (51 | GPIO_ALT_FN_2_OUT) +#define GPIO51_CIF_DD2_MD (51 | GPIO_ALT_FN_1_IN) #define GPIO52_nPCE_1_MD (52 | GPIO_ALT_FN_2_OUT) +#define GPIO52_CIF_DD4_MD (52 | GPIO_ALT_FN_1_IN) #define GPIO53_nPCE_2_MD (53 | GPIO_ALT_FN_2_OUT) #define GPIO53_MMCCLK_MD (53 | GPIO_ALT_FN_1_OUT) +#define GPIO53_CIF_MCLK_MD (53 | GPIO_ALT_FN_2_OUT) #define GPIO54_MMCCLK_MD (54 | GPIO_ALT_FN_1_OUT) #define GPIO54_nPCE_2_MD (54 | GPIO_ALT_FN_2_OUT) #define GPIO54_pSKTSEL_MD (54 | GPIO_ALT_FN_2_OUT) +#define GPIO54_CIF_PCLK_MD (54 | GPIO_ALT_FN_3_IN) #define GPIO55_nPREG_MD (55 | GPIO_ALT_FN_2_OUT) +#define GPIO55_CIF_DD1_MD (55 | GPIO_ALT_FN_1_IN) #define GPIO56_nPWAIT_MD (56 | GPIO_ALT_FN_1_IN) #define GPIO57_nIOIS16_MD (57 | GPIO_ALT_FN_1_IN) #define GPIO58_LDD_0_MD (58 | GPIO_ALT_FN_2_OUT) @@ -1477,16 +1535,33 @@ #define GPIO80_nCS_4_MD (80 | GPIO_ALT_FN_2_OUT) #define GPIO81_NSSP_CLK_OUT (81 | GPIO_ALT_FN_1_OUT) #define GPIO81_NSSP_CLK_IN (81 | GPIO_ALT_FN_1_IN) +#define GPIO81_CIF_DD0_MD (81 | GPIO_ALT_FN_2_IN) #define GPIO82_NSSP_FRM_OUT (82 | GPIO_ALT_FN_1_OUT) #define GPIO82_NSSP_FRM_IN (82 | GPIO_ALT_FN_1_IN) +#define GPIO82_CIF_DD5_MD (82 | GPIO_ALT_FN_3_IN) #define GPIO83_NSSP_TX (83 | GPIO_ALT_FN_1_OUT) #define GPIO83_NSSP_RX (83 | GPIO_ALT_FN_2_IN) +#define GPIO83_CIF_DD4_MD (83 | GPIO_ALT_FN_3_IN) #define GPIO84_NSSP_TX (84 | GPIO_ALT_FN_1_OUT) #define GPIO84_NSSP_RX (84 | GPIO_ALT_FN_2_IN) +#define GPIO84_CIF_FV_MD (84 | GPIO_ALT_FN_3_OUT) #define GPIO85_nPCE_1_MD (85 | GPIO_ALT_FN_1_OUT) +#define GPIO85_CIF_LV_MD (85 | GPIO_ALT_FN_3_OUT) +#define GPIO90_CIF_DD4_MD (90 | GPIO_ALT_FN_3_IN) +#define GPIO91_CIF_DD5_MD (91 | GPIO_ALT_FN_3_IN) #define GPIO92_MMCDAT0_MD (92 | GPIO_ALT_FN_1_OUT) +#define GPIO93_CIF_DD6_MD (93 | GPIO_ALT_FN_2_IN) +#define GPIO94_CIF_DD5_MD (94 | GPIO_ALT_FN_2_IN) +#define GPIO95_CIF_DD4_MD (95 | GPIO_ALT_FN_2_IN) +#define GPIO98_CIF_DD0_MD (98 | GPIO_ALT_FN_2_IN) #define GPIO102_nPCE_1_MD (102 | GPIO_ALT_FN_1_OUT) +#define GPIO103_CIF_DD3_MD (103 | GPIO_ALT_FN_1_IN) #define GPIO104_pSKTSEL_MD (104 | GPIO_ALT_FN_1_OUT) +#define GPIO104_CIF_DD2_MD (104 | GPIO_ALT_FN_1_IN) +#define GPIO105_CIF_DD1_MD (105 | GPIO_ALT_FN_1_IN) +#define GPIO106_CIF_DD9_MD (106 | GPIO_ALT_FN_1_IN) +#define GPIO107_CIF_DD8_MD (107 | GPIO_ALT_FN_1_IN) +#define GPIO108_CIF_DD7_MD (108 | GPIO_ALT_FN_1_IN) #define GPIO109_MMCDAT1_MD (109 | GPIO_ALT_FN_1_OUT) #define GPIO110_MMCDAT2_MD (110 | GPIO_ALT_FN_1_OUT) #define GPIO110_MMCCS0_MD (110 | GPIO_ALT_FN_1_OUT) @@ -1715,7 +1790,7 @@ #define LCCR0_Color (LCCR0_CMS*0) /* Color display */ #define LCCR0_Mono (LCCR0_CMS*1) /* Monochrome display */ #define LCCR0_SDS (1 << 2) /* Single/Dual Panel Display */ - /* Select */ + /* Select */ #define LCCR0_Sngl (LCCR0_SDS*0) /* Single panel display */ #define LCCR0_Dual (LCCR0_SDS*1) /* Dual panel display */ @@ -1727,11 +1802,11 @@ #define LCCR0_Pas (LCCR0_PAS*0) /* Passive display (STN) */ #define LCCR0_Act (LCCR0_PAS*1) /* Active display (TFT) */ #define LCCR0_DPD (1 << 9) /* Double Pixel Data (monochrome */ - /* display mode) */ + /* display mode) */ #define LCCR0_4PixMono (LCCR0_DPD*0) /* 4-Pixel/clock Monochrome */ - /* display */ + /* display */ #define LCCR0_8PixMono (LCCR0_DPD*1) /* 8-Pixel/clock Monochrome */ - /* display */ + /* display */ #define LCCR0_DIS (1 << 10) /* LCD Disable */ #define LCCR0_QDM (1 << 11) /* LCD Quick Disable mask */ #define LCCR0_PDD (0xff << 12) /* Palette DMA request delay */ @@ -1746,47 +1821,47 @@ #define LCCR1_PPL Fld (10, 0) /* Pixels Per Line - 1 */ #define LCCR1_DisWdth(Pixel) /* Display Width [1..800 pix.] */ \ - (((Pixel) - 1) << FShft (LCCR1_PPL)) + (((Pixel) - 1) << FShft (LCCR1_PPL)) #define LCCR1_HSW Fld (6, 10) /* Horizontal Synchronization */ #define LCCR1_HorSnchWdth(Tpix) /* Horizontal Synchronization */ \ - /* pulse Width [1..64 Tpix] */ \ - (((Tpix) - 1) << FShft (LCCR1_HSW)) + /* pulse Width [1..64 Tpix] */ \ + (((Tpix) - 1) << FShft (LCCR1_HSW)) #define LCCR1_ELW Fld (8, 16) /* End-of-Line pixel clock Wait */ - /* count - 1 [Tpix] */ + /* count - 1 [Tpix] */ #define LCCR1_EndLnDel(Tpix) /* End-of-Line Delay */ \ - /* [1..256 Tpix] */ \ - (((Tpix) - 1) << FShft (LCCR1_ELW)) + /* [1..256 Tpix] */ \ + (((Tpix) - 1) << FShft (LCCR1_ELW)) #define LCCR1_BLW Fld (8, 24) /* Beginning-of-Line pixel clock */ - /* Wait count - 1 [Tpix] */ + /* Wait count - 1 [Tpix] */ #define LCCR1_BegLnDel(Tpix) /* Beginning-of-Line Delay */ \ - /* [1..256 Tpix] */ \ - (((Tpix) - 1) << FShft (LCCR1_BLW)) + /* [1..256 Tpix] */ \ + (((Tpix) - 1) << FShft (LCCR1_BLW)) #define LCCR2_LPP Fld (10, 0) /* Line Per Panel - 1 */ #define LCCR2_DisHght(Line) /* Display Height [1..1024 lines] */ \ - (((Line) - 1) << FShft (LCCR2_LPP)) + (((Line) - 1) << FShft (LCCR2_LPP)) #define LCCR2_VSW Fld (6, 10) /* Vertical Synchronization pulse */ - /* Width - 1 [Tln] (L_FCLK) */ + /* Width - 1 [Tln] (L_FCLK) */ #define LCCR2_VrtSnchWdth(Tln) /* Vertical Synchronization pulse */ \ - /* Width [1..64 Tln] */ \ - (((Tln) - 1) << FShft (LCCR2_VSW)) + /* Width [1..64 Tln] */ \ + (((Tln) - 1) << FShft (LCCR2_VSW)) #define LCCR2_EFW Fld (8, 16) /* End-of-Frame line clock Wait */ - /* count [Tln] */ + /* count [Tln] */ #define LCCR2_EndFrmDel(Tln) /* End-of-Frame Delay */ \ - /* [0..255 Tln] */ \ - ((Tln) << FShft (LCCR2_EFW)) + /* [0..255 Tln] */ \ + ((Tln) << FShft (LCCR2_EFW)) #define LCCR2_BFW Fld (8, 24) /* Beginning-of-Frame line clock */ - /* Wait count [Tln] */ + /* Wait count [Tln] */ #define LCCR2_BegFrmDel(Tln) /* Beginning-of-Frame Delay */ \ - /* [0..255 Tln] */ \ - ((Tln) << FShft (LCCR2_BFW)) + /* [0..255 Tln] */ \ + ((Tln) << FShft (LCCR2_BFW)) #if 0 #define LCCR3_PCD (0xff) /* Pixel clock divisor */ @@ -1803,7 +1878,7 @@ #define LCCR3_PixFlEdg (LCCR3_PCP*1) /* Pixel clock Falling-Edge */ #define LCCR3_OEP (1 << 23) /* Output Enable Polarity (L_BIAS, */ - /* active display mode) */ + /* active display mode) */ #define LCCR3_OutEnH (LCCR3_OEP*0) /* Output Enable active High */ #define LCCR3_OutEnL (LCCR3_OEP*1) /* Output Enable active Low */ @@ -1816,25 +1891,25 @@ #define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */ #define LCCR3_PixClkDiv(Div) /* Pixel Clock Divisor */ \ - (((Div) << FShft (LCCR3_PCD))) + (((Div) << FShft (LCCR3_PCD))) #define LCCR3_BPP Fld (3, 24) /* Bit Per Pixel */ #define LCCR3_Bpp(Bpp) /* Bit Per Pixel */ \ - (((Bpp) << FShft (LCCR3_BPP))) + (((Bpp) << FShft (LCCR3_BPP))) #define LCCR3_ACB Fld (8, 8) /* AC Bias */ #define LCCR3_Acb(Acb) /* BAC Bias */ \ - (((Acb) << FShft (LCCR3_ACB))) + (((Acb) << FShft (LCCR3_ACB))) #define LCCR3_HorSnchH (LCCR3_HSP*0) /* Horizontal Synchronization */ - /* pulse active High */ + /* pulse active High */ #define LCCR3_HorSnchL (LCCR3_HSP*1) /* Horizontal Synchronization */ #define LCCR3_VrtSnchH (LCCR3_VSP*0) /* Vertical Synchronization pulse */ - /* active High */ + /* active High */ #define LCCR3_VrtSnchL (LCCR3_VSP*1) /* Vertical Synchronization pulse */ - /* active Low */ + /* active Low */ #define LCSR_LDD (1 << 0) /* LCD Disable Done */ #define LCSR_SOF (1 << 1) /* Start of frame */ diff --git a/include/linux/meye.h b/include/linux/meye.h index 39fd9c8..12010ac 100644 --- a/include/linux/meye.h +++ b/include/linux/meye.h @@ -58,7 +58,7 @@ struct meye_params { /* V4L2 private controls */ #define V4L2_CID_AGC V4L2_CID_PRIVATE_BASE -#define V4L2_CID_SHARPNESS (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_MEYE_SHARPNESS (V4L2_CID_PRIVATE_BASE + 1) #define V4L2_CID_PICTURE (V4L2_CID_PRIVATE_BASE + 2) #define V4L2_CID_JPEGQUAL (V4L2_CID_PRIVATE_BASE + 3) #define V4L2_CID_FRAMERATE (V4L2_CID_PRIVATE_BASE + 4) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 17a8017..50e6c35 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -282,6 +282,7 @@ struct v4l2_pix_format #define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B','G','R','4') /* 32 BGR-8-8-8-8 */ #define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R','G','B','4') /* 32 RGB-8-8-8-8 */ #define V4L2_PIX_FMT_GREY v4l2_fourcc('G','R','E','Y') /* 8 Greyscale */ +#define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y','1','6',' ') /* 16 Greyscale */ #define V4L2_PIX_FMT_PAL8 v4l2_fourcc('P','A','L','8') /* 8 8-bit palette */ #define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y','V','U','9') /* 9 YVU 4:1:0 */ #define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */ @@ -308,6 +309,7 @@ struct v4l2_pix_format /* see http://www.siliconimaging.com/RGB%20Bayer.htm */ #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B','Y','R','2') /* 16 BGBG.. GRGR.. */ /* compressed formats */ #define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M','J','P','G') /* Motion-JPEG */ @@ -793,6 +795,7 @@ struct v4l2_ext_controls /* Values for ctrl_class field */ #define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ #define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */ +#define V4L2_CTRL_CLASS_CAMERA 0x009a0000 /* Camera class controls */ #define V4L2_CTRL_ID_MASK (0x0fffffff) #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) @@ -849,21 +852,34 @@ struct v4l2_querymenu #define V4L2_CID_AUDIO_TREBLE (V4L2_CID_BASE+8) #define V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9) #define V4L2_CID_AUDIO_LOUDNESS (V4L2_CID_BASE+10) -#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) +#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) /* Deprecated */ #define V4L2_CID_AUTO_WHITE_BALANCE (V4L2_CID_BASE+12) #define V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13) #define V4L2_CID_RED_BALANCE (V4L2_CID_BASE+14) #define V4L2_CID_BLUE_BALANCE (V4L2_CID_BASE+15) #define V4L2_CID_GAMMA (V4L2_CID_BASE+16) -#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* ? Not sure */ +#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* Deprecated */ #define V4L2_CID_EXPOSURE (V4L2_CID_BASE+17) #define V4L2_CID_AUTOGAIN (V4L2_CID_BASE+18) #define V4L2_CID_GAIN (V4L2_CID_BASE+19) #define V4L2_CID_HFLIP (V4L2_CID_BASE+20) #define V4L2_CID_VFLIP (V4L2_CID_BASE+21) -#define V4L2_CID_HCENTER (V4L2_CID_BASE+22) -#define V4L2_CID_VCENTER (V4L2_CID_BASE+23) -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+24) /* last CID + 1 */ + +/* Deprecated, use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */ +#define V4L2_CID_HCENTER_DEPRECATED (V4L2_CID_BASE+22) +#define V4L2_CID_VCENTER_DEPRECATED (V4L2_CID_BASE+23) + +#define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_BASE+24) +enum v4l2_power_line_frequency { + V4L2_CID_POWER_LINE_FREQUENCY_DISABLED = 0, + V4L2_CID_POWER_LINE_FREQUENCY_50HZ = 1, + V4L2_CID_POWER_LINE_FREQUENCY_60HZ = 2, +}; +#define V4L2_CID_HUE_AUTO (V4L2_CID_BASE+25) +#define V4L2_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_BASE+26) +#define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27) +#define V4L2_CID_BACKLIGHT_COMPENSATION (V4L2_CID_BASE+28) +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+29) /* last CID + 1 */ /* MPEG-class control IDs defined by V4L2 */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) @@ -1051,6 +1067,32 @@ enum v4l2_mpeg_cx2341x_video_median_filter_type { #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+10) #define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS (V4L2_CID_MPEG_CX2341X_BASE+11) +/* Camera class control IDs */ +#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900) +#define V4L2_CID_CAMERA_CLASS (V4L2_CTRL_CLASS_CAMERA | 1) + +#define V4L2_CID_EXPOSURE_AUTO (V4L2_CID_CAMERA_CLASS_BASE+1) +enum v4l2_exposure_auto_type { + V4L2_EXPOSURE_AUTO = 0, + V4L2_EXPOSURE_MANUAL = 1, + V4L2_EXPOSURE_SHUTTER_PRIORITY = 2, + V4L2_EXPOSURE_APERTURE_PRIORITY = 3 +}; +#define V4L2_CID_EXPOSURE_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+2) +#define V4L2_CID_EXPOSURE_AUTO_PRIORITY (V4L2_CID_CAMERA_CLASS_BASE+3) + +#define V4L2_CID_PAN_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+4) +#define V4L2_CID_TILT_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+5) +#define V4L2_CID_PAN_RESET (V4L2_CID_CAMERA_CLASS_BASE+6) +#define V4L2_CID_TILT_RESET (V4L2_CID_CAMERA_CLASS_BASE+7) + +#define V4L2_CID_PAN_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+8) +#define V4L2_CID_TILT_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+9) + +#define V4L2_CID_FOCUS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+10) +#define V4L2_CID_FOCUS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+11) +#define V4L2_CID_FOCUS_AUTO (V4L2_CID_CAMERA_CLASS_BASE+12) + /* * T U N I N G */ diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h new file mode 100644 index 0000000..c886b1e --- /dev/null +++ b/include/media/soc_camera.h @@ -0,0 +1,149 @@ +/* + * camera image capture (abstract) bus driver header + * + * Copyright (C) 2006, Sascha Hauer, Pengutronix + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef SOC_CAMERA_H +#define SOC_CAMERA_H + +#include +#include + +struct soc_camera_device { + struct list_head list; + struct device dev; + struct device *control; + unsigned short width; /* Current window */ + unsigned short height; /* sizes */ + unsigned short x_min; /* Camera capabilities */ + unsigned short y_min; + unsigned short x_current; /* Current window location */ + unsigned short y_current; + unsigned short width_min; + unsigned short width_max; + unsigned short height_min; + unsigned short height_max; + unsigned short y_skip_top; /* Lines to skip at the top */ + unsigned short gain; + unsigned short exposure; + unsigned char iface; /* Host number */ + unsigned char devnum; /* Device number per host */ + unsigned char cached_datawidth; /* See comment in .c */ + struct soc_camera_ops *ops; + struct video_device *vdev; + const struct soc_camera_data_format *current_fmt; + int (*probe)(struct soc_camera_device *icd); + void (*remove)(struct soc_camera_device *icd); + struct module *owner; + /* soc_camera.c private count. Only accessed with video_lock held */ + int use_count; +}; + +struct soc_camera_file { + struct soc_camera_device *icd; + struct videobuf_queue vb_vidq; +}; + +struct soc_camera_host { + struct list_head list; + struct device dev; + unsigned char nr; /* Host number */ + size_t msize; + struct videobuf_queue_ops *vbq_ops; + struct module *owner; + void *priv; + char *drv_name; + int (*add)(struct soc_camera_device *); + void (*remove)(struct soc_camera_device *); + int (*set_capture_format)(struct soc_camera_device *, __u32, + struct v4l2_rect *); + int (*try_fmt_cap)(struct soc_camera_host *, struct v4l2_format *); + int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); + int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); + unsigned int (*poll)(struct file *, poll_table *); +}; + +struct soc_camera_link { + /* Camera bus id, used to match a camera and a bus */ + int bus_id; + /* GPIO number to switch between 8 and 10 bit modes */ + unsigned int gpio; +}; + +static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev) +{ + return container_of(dev, struct soc_camera_device, dev); +} + +static inline struct soc_camera_host *to_soc_camera_host(struct device *dev) +{ + return container_of(dev, struct soc_camera_host, dev); +} + +extern int soc_camera_host_register(struct soc_camera_host *ici, + struct module *owner); +extern void soc_camera_host_unregister(struct soc_camera_host *ici); +extern int soc_camera_device_register(struct soc_camera_device *icd); +extern void soc_camera_device_unregister(struct soc_camera_device *icd); + +extern int soc_camera_video_start(struct soc_camera_device *icd); +extern void soc_camera_video_stop(struct soc_camera_device *icd); + +struct soc_camera_data_format { + char *name; + unsigned int depth; + __u32 fourcc; + enum v4l2_colorspace colorspace; +}; + +struct soc_camera_ops { + struct module *owner; + int (*init)(struct soc_camera_device *); + int (*release)(struct soc_camera_device *); + int (*start_capture)(struct soc_camera_device *); + int (*stop_capture)(struct soc_camera_device *); + int (*set_capture_format)(struct soc_camera_device *, __u32, + struct v4l2_rect *, unsigned int); + int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); + int (*get_chip_id)(struct soc_camera_device *, + struct v4l2_chip_ident *); +#ifdef CONFIG_VIDEO_ADV_DEBUG + int (*get_register)(struct soc_camera_device *, struct v4l2_register *); + int (*set_register)(struct soc_camera_device *, struct v4l2_register *); +#endif + const struct soc_camera_data_format *formats; + int num_formats; + int (*get_control)(struct soc_camera_device *, struct v4l2_control *); + int (*set_control)(struct soc_camera_device *, struct v4l2_control *); + const struct v4l2_queryctrl *controls; + int num_controls; + unsigned int(*get_datawidth)(struct soc_camera_device *icd); +}; + +static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( + struct soc_camera_ops *ops, int id) +{ + int i; + + for (i = 0; i < ops->num_controls; i++) + if (ops->controls[i].id == id) + return &ops->controls[i]; + + return NULL; +} + +#define IS_MASTER (1<<0) +#define IS_HSYNC_ACTIVE_HIGH (1<<1) +#define IS_VSYNC_ACTIVE_HIGH (1<<2) +#define IS_DATAWIDTH_8 (1<<3) +#define IS_DATAWIDTH_9 (1<<4) +#define IS_DATAWIDTH_10 (1<<5) +#define IS_PCLK_SAMPLE_RISING (1<<6) + +#endif diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 032bb75..0ea0bd8 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -153,6 +153,12 @@ enum { V4L2_IDENT_MSP4428G = 44287, V4L2_IDENT_MSP4448G = 44487, V4L2_IDENT_MSP4458G = 44587, + + /* Micron CMOS sensor chips: 45000-45099 */ + V4L2_IDENT_MT9M001C12ST = 45000, + V4L2_IDENT_MT9M001C12STM = 45005, + V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ + V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ }; #endif diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h index 3810503..b6ab080 100644 --- a/include/media/videobuf-dma-sg.h +++ b/include/media/videobuf-dma-sg.h @@ -1,5 +1,5 @@ /* - * helper functions for PCI DMA video4linux capture buffers + * helper functions for SG DMA video4linux capture buffers * * The functions expect the hardware being able to scatter gatter * (i.e. the buffers are not linear in physical memory, but fragmented @@ -81,7 +81,7 @@ struct videobuf_dmabuf { int direction; }; -struct videbuf_pci_sg_memory +struct videobuf_dma_sg_memory { u32 magic; @@ -103,11 +103,11 @@ int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma); int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma); struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf); -void *videobuf_pci_alloc (size_t size); +void *videobuf_sg_alloc(size_t size); -void videobuf_queue_pci_init(struct videobuf_queue* q, +void videobuf_queue_sg_init(struct videobuf_queue* q, struct videobuf_queue_ops *ops, - void *dev, + struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, @@ -117,6 +117,6 @@ void videobuf_queue_pci_init(struct videobuf_queue* q, /*FIXME: these variants are used only on *-alsa code, where videobuf is * used without queue */ -int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma); -int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma); +int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma); +int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma);